about summary refs log tree commit diff
diff options
context:
space:
mode:
authorThe Miri Cronjob Bot <miri@cron.bot>2024-03-12 05:45:33 +0000
committerThe Miri Cronjob Bot <miri@cron.bot>2024-03-12 05:45:33 +0000
commit19378ca0969c5a105a03a2d156c10be7b58f6a66 (patch)
tree867759edc0e773810a18d5349733a6d4a11d3ee8
parent9123df0300897fdcd718f0be193ac4ca4a30aa41 (diff)
parent6b082b5e6672ed6d5fdb08d1966d15d3080f1d21 (diff)
downloadrust-19378ca0969c5a105a03a2d156c10be7b58f6a66.tar.gz
rust-19378ca0969c5a105a03a2d156c10be7b58f6a66.zip
Merge from rustc
-rw-r--r--.github/workflows/ci.yml4
-rw-r--r--Cargo.lock14
-rw-r--r--Cargo.toml1
-rw-r--r--INSTALL.md20
-rw-r--r--compiler/rustc_ast_lowering/src/errors.rs62
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs10
-rw-r--r--compiler/rustc_attr/src/session_diagnostics.rs12
-rw-r--r--compiler/rustc_borrowck/src/consumers.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_name.rs6
-rw-r--r--compiler/rustc_borrowck/src/lib.rs5
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/errors.rs16
-rw-r--r--compiler/rustc_codegen_cranelift/example/mini_core.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/src/main_shim.rs8
-rw-r--r--compiler/rustc_codegen_gcc/.github/workflows/ci.yml89
-rw-r--r--compiler/rustc_codegen_gcc/.github/workflows/failures.yml70
-rw-r--r--compiler/rustc_codegen_gcc/.github/workflows/gcc12.yml55
-rw-r--r--compiler/rustc_codegen_gcc/.github/workflows/m68k.yml71
-rw-r--r--compiler/rustc_codegen_gcc/.github/workflows/release.yml69
-rw-r--r--compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml86
-rw-r--r--compiler/rustc_codegen_gcc/.gitignore8
-rw-r--r--compiler/rustc_codegen_gcc/.ignore1
-rw-r--r--compiler/rustc_codegen_gcc/.rustfmt.toml2
-rw-r--r--compiler/rustc_codegen_gcc/Cargo.lock19
-rw-r--r--compiler/rustc_codegen_gcc/Cargo.toml7
-rw-r--r--compiler/rustc_codegen_gcc/Readme.md259
-rw-r--r--compiler/rustc_codegen_gcc/build.rs6
-rwxr-xr-xcompiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh34
-rw-r--r--compiler/rustc_codegen_gcc/build_system/Cargo.lock9
-rw-r--r--compiler/rustc_codegen_gcc/build_system/Cargo.toml3
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/build.rs199
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/cargo.rs114
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/clean.rs82
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/clone_gcc.rs79
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/config.rs638
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/info.rs19
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/main.rs32
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/prepare.rs75
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/test.rs1215
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/utils.rs323
-rwxr-xr-xcompiler/rustc_codegen_gcc/cargo.sh23
-rwxr-xr-xcompiler/rustc_codegen_gcc/clean_all.sh6
-rw-r--r--compiler/rustc_codegen_gcc/config.example.toml2
-rw-r--r--compiler/rustc_codegen_gcc/config.sh85
-rw-r--r--compiler/rustc_codegen_gcc/crate_patches/0002-rand-Disable-failing-test.patch32
-rw-r--r--compiler/rustc_codegen_gcc/deps/libLLVM-18-rust-1.78.0-nightly.so1
-rw-r--r--compiler/rustc_codegen_gcc/doc/debugging-gcc-lto.md3
-rw-r--r--compiler/rustc_codegen_gcc/doc/debugging-libgccjit.md74
-rw-r--r--compiler/rustc_codegen_gcc/doc/errors.md27
-rw-r--r--compiler/rustc_codegen_gcc/doc/subtree.md52
-rw-r--r--compiler/rustc_codegen_gcc/doc/tips.md72
-rw-r--r--compiler/rustc_codegen_gcc/example/mini_core.rs2
-rw-r--r--compiler/rustc_codegen_gcc/libgccjit.version1
-rw-r--r--compiler/rustc_codegen_gcc/messages.ftl2
-rw-r--r--compiler/rustc_codegen_gcc/patches/0022-core-Disable-not-compiling-tests.patch4
-rw-r--r--compiler/rustc_codegen_gcc/patches/crates/0001-Remove-deny-warnings.patch24
-rw-r--r--compiler/rustc_codegen_gcc/patches/cross_patches/0001-Disable-libstd-and-libtest-dylib.patch (renamed from compiler/rustc_codegen_gcc/cross_patches/0001-Disable-libstd-and-libtest-dylib.patch)16
-rw-r--r--compiler/rustc_codegen_gcc/rust-toolchain2
-rwxr-xr-xcompiler/rustc_codegen_gcc/rustup.sh29
-rw-r--r--compiler/rustc_codegen_gcc/src/abi.rs107
-rw-r--r--compiler/rustc_codegen_gcc/src/allocator.rs62
-rw-r--r--compiler/rustc_codegen_gcc/src/asm.rs225
-rw-r--r--compiler/rustc_codegen_gcc/src/attributes.rs77
-rw-r--r--compiler/rustc_codegen_gcc/src/back/lto.rs94
-rw-r--r--compiler/rustc_codegen_gcc/src/back/write.rs54
-rw-r--r--compiler/rustc_codegen_gcc/src/base.rs59
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs1431
-rw-r--r--compiler/rustc_codegen_gcc/src/callee.rs259
-rw-r--r--compiler/rustc_codegen_gcc/src/common.rs168
-rw-r--r--compiler/rustc_codegen_gcc/src/consts.rs143
-rw-r--r--compiler/rustc_codegen_gcc/src/context.rs250
-rw-r--r--compiler/rustc_codegen_gcc/src/debuginfo.rs243
-rw-r--r--compiler/rustc_codegen_gcc/src/declare.rs225
-rw-r--r--compiler/rustc_codegen_gcc/src/errors.rs27
-rw-r--r--compiler/rustc_codegen_gcc/src/gcc_util.rs67
-rw-r--r--compiler/rustc_codegen_gcc/src/int.rs942
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/archs.rs27
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs524
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/mod.rs1101
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/simd.rs230
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs240
-rw-r--r--compiler/rustc_codegen_gcc/src/mono_item.rs39
-rw-r--r--compiler/rustc_codegen_gcc/src/type_.rs67
-rw-r--r--compiler/rustc_codegen_gcc/src/type_of.rs163
-rwxr-xr-xcompiler/rustc_codegen_gcc/test.sh479
-rw-r--r--compiler/rustc_codegen_gcc/tests/failing-lto-tests.txt (renamed from compiler/rustc_codegen_gcc/failing-lto-tests.txt)11
-rw-r--r--compiler/rustc_codegen_gcc/tests/failing-non-lto-tests.txt (renamed from compiler/rustc_codegen_gcc/failing-non-lto-tests.txt)2
-rw-r--r--compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt (renamed from compiler/rustc_codegen_gcc/failing-ui-tests.txt)8
-rw-r--r--compiler/rustc_codegen_gcc/tests/failing-ui-tests12.txt (renamed from compiler/rustc_codegen_gcc/failing-ui-tests12.txt)8
-rw-r--r--compiler/rustc_codegen_gcc/tests/lang_tests_common.rs88
-rwxr-xr-xcompiler/rustc_codegen_gcc/y.sh6
-rw-r--r--compiler/rustc_codegen_llvm/src/abi.rs20
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs24
-rw-r--r--compiler/rustc_codegen_llvm/src/errors.rs18
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs9
-rw-r--r--compiler/rustc_codegen_llvm/src/type_of.rs30
-rw-r--r--compiler/rustc_codegen_ssa/src/assert_module_sources.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs23
-rw-r--r--compiler/rustc_codegen_ssa/src/back/linker.rs101
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs9
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs29
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs19
-rw-r--r--compiler/rustc_codegen_ssa/src/meth.rs19
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/backend.rs7
-rw-r--r--compiler/rustc_const_eval/messages.ftl3
-rw-r--r--compiler/rustc_const_eval/src/const_eval/error.rs14
-rw-r--r--compiler/rustc_const_eval/src/const_eval/eval_queries.rs18
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs6
-rw-r--r--compiler/rustc_const_eval/src/errors.rs11
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs43
-rw-r--r--compiler/rustc_const_eval/src/interpret/validity.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs1
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs15
-rw-r--r--compiler/rustc_driver_impl/src/pretty.rs6
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs62
-rw-r--r--compiler/rustc_errors/src/diagnostic_impls.rs154
-rw-r--r--compiler/rustc_errors/src/lib.rs67
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs2
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_hir/src/hir.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/bounds.rs22
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/coherence/mod.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs31
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs30
-rw-r--r--compiler/rustc_hir_analysis/src/outlives/test.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/variance/test.rs13
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs20
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/inherited.rs2
-rw-r--r--compiler/rustc_infer/messages.ftl8
-rw-r--r--compiler/rustc_infer/src/errors/mod.rs48
-rw-r--r--compiler/rustc_infer/src/errors/note_and_explain.rs14
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs8
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs6
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs4
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs6
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs6
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note.rs20
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs13
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types/mod.rs65
-rw-r--r--compiler/rustc_interface/src/interface.rs61
-rw-r--r--compiler/rustc_interface/src/passes.rs33
-rw-r--r--compiler/rustc_interface/src/tests.rs13
-rw-r--r--compiler/rustc_interface/src/util.rs47
-rw-r--r--compiler/rustc_lint/messages.ftl4
-rw-r--r--compiler/rustc_lint/src/builtin.rs4
-rw-r--r--compiler/rustc_lint/src/context.rs10
-rw-r--r--compiler/rustc_lint/src/errors.rs6
-rw-r--r--compiler/rustc_lint/src/internal.rs31
-rw-r--r--compiler/rustc_lint/src/levels.rs6
-rw-r--r--compiler/rustc_lint/src/lints.rs60
-rw-r--r--compiler/rustc_macros/src/diagnostics/diagnostic.rs11
-rw-r--r--compiler/rustc_macros/src/diagnostics/mod.rs8
-rw-r--r--compiler/rustc_macros/src/diagnostics/subdiagnostic.rs12
-rw-r--r--compiler/rustc_macros/src/lib.rs4
-rw-r--r--compiler/rustc_metadata/src/errors.rs14
-rw-r--r--compiler/rustc_metadata/src/locator.rs6
-rw-r--r--compiler/rustc_middle/src/mir/consts.rs16
-rw-r--r--compiler/rustc_middle/src/mir/interpret/error.rs18
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs2
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs2
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs5
-rw-r--r--compiler/rustc_middle/src/mir/terminator.rs2
-rw-r--r--compiler/rustc_middle/src/mir/type_foldable.rs10
-rw-r--r--compiler/rustc_middle/src/thir.rs8
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs24
-rw-r--r--compiler/rustc_middle/src/traits/solve.rs2
-rw-r--r--compiler/rustc_middle/src/ty/codec.rs10
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs6
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs6
-rw-r--r--compiler/rustc_middle/src/ty/context.rs20
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs8
-rw-r--r--compiler/rustc_middle/src/ty/generic_args.rs8
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs16
-rw-r--r--compiler/rustc_middle/src/ty/predicate.rs22
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs12
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs16
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs118
-rw-r--r--compiler/rustc_mir_build/src/build/matches/simplify.rs17
-rw-r--r--compiler/rustc_mir_build/src/build/matches/util.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs150
-rw-r--r--compiler/rustc_mir_build/src/errors.rs18
-rw-r--r--compiler/rustc_mir_transform/src/errors.rs14
-rw-r--r--compiler/rustc_mir_transform/src/ffi_unwind_calls.rs2
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs6
-rw-r--r--compiler/rustc_monomorphize/src/errors.rs6
-rw-r--r--compiler/rustc_parse/messages.ftl4
-rw-r--r--compiler/rustc_parse/src/errors.rs26
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs8
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs6
-rw-r--r--compiler/rustc_parse/src/parser/path.rs86
-rw-r--r--compiler/rustc_passes/messages.ftl5
-rw-r--r--compiler/rustc_passes/src/check_attr.rs8
-rw-r--r--compiler/rustc_passes/src/dead.rs96
-rw-r--r--compiler/rustc_passes/src/entry.rs8
-rw-r--r--compiler/rustc_passes/src/errors.rs28
-rw-r--r--compiler/rustc_pattern_analysis/src/errors.rs10
-rw-r--r--compiler/rustc_pattern_analysis/src/lints.rs2
-rw-r--r--compiler/rustc_query_system/src/dep_graph/graph.rs84
-rw-r--r--compiler/rustc_query_system/src/dep_graph/serialized.rs23
-rw-r--r--compiler/rustc_resolve/src/errors.rs2
-rw-r--r--compiler/rustc_resolve/src/late.rs6
-rw-r--r--compiler/rustc_resolve/src/macros.rs3
-rw-r--r--compiler/rustc_session/src/config.rs26
-rw-r--r--compiler/rustc_session/src/errors.rs8
-rw-r--r--compiler/rustc_session/src/filesearch.rs6
-rw-r--r--compiler/rustc_session/src/options.rs2
-rw-r--r--compiler/rustc_session/src/session.rs25
-rw-r--r--compiler/rustc_span/src/symbol.rs7
-rw-r--r--compiler/rustc_symbol_mangling/src/errors.rs6
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs37
-rw-r--r--compiler/rustc_target/src/abi/call/x86_64.rs2
-rw-r--r--compiler/rustc_target/src/json.rs15
-rw-r--r--compiler/rustc_target/src/spec/base/avr_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/mod.rs76
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabihf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armebv7r_none_eabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armebv7r_none_eabihf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv4t_unknown_linux_gnueabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_gnueabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv6_unknown_netbsd_eabihf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7_linux_androideabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabihf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7_unknown_linux_ohos.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabihf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7_unknown_netbsd_eabihf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7_wrs_vxworks_eabihf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabihf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2hf.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/i386_apple_ios.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_linux_android.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/m68k_unknown_linux_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/mipsel_sony_psp.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/msp430_none_elf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs11
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc_unknown_freebsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc_unknown_netbsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc_unknown_openbsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv32i_unknown_none_elf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv32im_risc0_zkvm_elf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv32im_unknown_none_elf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv32imac_esp_espidf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv32imac_unknown_none_elf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv32imafc_esp_espidf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_none_elf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv32imc_esp_espidf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv32imc_unknown_none_elf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/thumbv6m_none_eabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/thumbv7a_uwp_windows_msvc.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/thumbv7em_none_eabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/thumbv7em_none_eabihf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/thumbv7m_none_eabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/thumbv7neon_linux_androideabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_gnueabihf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/thumbv8m_base_none_eabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabihf.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs7
-rw-r--r--compiler/rustc_target/src/spec/tests/tests_impl.rs5
-rw-r--r--compiler/rustc_trait_selection/src/errors.rs12
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs7
-rw-r--r--compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs5
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs19
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs27
-rw-r--r--compiler/rustc_ty_utils/src/sig_types.rs14
-rw-r--r--config.example.toml15
-rw-r--r--library/alloc/src/ffi/c_str.rs2
-rw-r--r--library/alloc/src/ffi/mod.rs10
-rw-r--r--library/alloc/src/raw_vec.rs3
-rw-r--r--library/alloc/src/slice.rs4
m---------library/backtrace0
-rw-r--r--library/core/src/ffi/c_str.rs17
-rw-r--r--library/core/src/ffi/mod.rs14
-rw-r--r--library/core/src/io/borrowed_buf.rs6
-rw-r--r--library/core/src/lib.rs1
-rw-r--r--library/core/src/marker.rs10
-rw-r--r--library/core/src/slice/index.rs67
-rw-r--r--library/core/src/slice/mod.rs2
-rw-r--r--library/core/src/task/wake.rs21
-rw-r--r--library/panic_unwind/src/gcc.rs2
-rw-r--r--library/panic_unwind/src/lib.rs2
-rw-r--r--library/std/src/ffi/c_str.rs19
-rw-r--r--library/std/src/ffi/mod.rs32
-rw-r--r--library/std/src/io/mod.rs17
-rw-r--r--library/std/src/io/tests.rs2
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/os/android/net.rs3
-rw-r--r--library/std/src/os/freebsd/mod.rs1
-rw-r--r--library/std/src/os/freebsd/net.rs65
-rw-r--r--library/std/src/os/linux/net.rs3
-rw-r--r--library/std/src/os/net/linux_ext/mod.rs3
-rw-r--r--library/std/src/os/net/linux_ext/socket.rs63
-rw-r--r--library/std/src/os/netbsd/mod.rs1
-rw-r--r--library/std/src/os/netbsd/net.rs65
-rw-r--r--library/std/src/os/unix/net/datagram.rs75
-rw-r--r--library/std/src/os/unix/net/stream.rs75
-rw-r--r--library/std/src/os/unix/net/tests.rs4
-rw-r--r--library/std/src/sys/pal/unix/net.rs26
-rw-r--r--library/std/src/sys/pal/unix/rand.rs10
-rw-r--r--library/std/src/sys/pal/unix/stack_overflow.rs50
-rw-r--r--library/std/src/sys/pal/unix/thread.rs5
-rw-r--r--library/std/src/sys/pal/windows/alloc.rs55
-rw-r--r--library/std/src/sys/pal/windows/c.rs1
-rw-r--r--library/std/src/sys/pal/windows/c/bindings.txt1
-rw-r--r--library/std/src/sys/pal/windows/c/windows_sys.rs4
-rw-r--r--library/std/src/sys/personality/mod.rs8
-rw-r--r--library/test/src/console.rs7
-rw-r--r--library/unwind/src/lib.rs8
-rw-r--r--library/unwind/src/libunwind.rs2
-rw-r--r--library/unwind/src/unwinding.rs2
-rw-r--r--library/unwind/src/wasm.rs65
-rw-r--r--src/bootstrap/README.md27
-rwxr-xr-xsrc/bootstrap/configure.py2
-rw-r--r--src/bootstrap/defaults/config.compiler.toml2
-rw-r--r--src/bootstrap/defaults/config.dist.toml2
-rw-r--r--src/bootstrap/defaults/config.library.toml2
-rw-r--r--src/bootstrap/defaults/config.tools.toml2
-rw-r--r--src/bootstrap/src/core/build_steps/check.rs24
-rw-r--r--src/bootstrap/src/core/build_steps/clean.rs5
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs55
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs21
-rw-r--r--src/bootstrap/src/core/build_steps/doc.rs41
-rw-r--r--src/bootstrap/src/core/build_steps/install.rs3
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs70
-rw-r--r--src/bootstrap/src/core/build_steps/tool.rs1
-rw-r--r--src/bootstrap/src/core/builder.rs21
-rw-r--r--src/bootstrap/src/core/builder/tests.rs2
-rw-r--r--src/bootstrap/src/core/config/config.rs25
-rw-r--r--src/bootstrap/src/core/metadata.rs9
-rw-r--r--src/bootstrap/src/core/sanity.rs17
-rw-r--r--src/bootstrap/src/lib.rs62
-rw-r--r--src/bootstrap/src/utils/cache.rs11
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs10
-rw-r--r--src/ci/docker/host-x86_64/dist-various-2/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-linux/build-gccjit.sh29
-rw-r--r--src/ci/docker/host-x86_64/test-various/Dockerfile17
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile11
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile13
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile13
-rw-r--r--src/ci/github-actions/ci.yml3
-rwxr-xr-xsrc/ci/scripts/install-msys2.sh14
-rw-r--r--src/doc/rustc/src/platform-support.md2
-rw-r--r--src/doc/rustc/src/platform-support/unknown-uefi.md2
-rw-r--r--src/etc/wasm32-shim.js24
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/utils.rs60
-rw-r--r--src/tools/clippy/clippy_lints/src/macro_use.rs6
-rw-r--r--src/tools/compiletest/src/common.rs6
-rw-r--r--src/tools/compiletest/src/header.rs128
-rw-r--r--src/tools/compiletest/src/header/test-auxillary/error_annotation.rs6
-rw-r--r--src/tools/compiletest/src/header/test-auxillary/known_directive.rs4
-rw-r--r--src/tools/compiletest/src/header/test-auxillary/known_legacy_directive.rs1
-rw-r--r--src/tools/compiletest/src/header/test-auxillary/not_rs.Makefile1
-rw-r--r--src/tools/compiletest/src/header/test-auxillary/unknown_directive.rs1
-rw-r--r--src/tools/compiletest/src/header/tests.rs62
-rw-r--r--src/tools/compiletest/src/lib.rs6
-rw-r--r--src/tools/compiletest/src/runtest.rs103
-rw-r--r--src/tools/llvm-bitcode-linker/Cargo.toml14
-rw-r--r--src/tools/llvm-bitcode-linker/README.md5
-rw-r--r--src/tools/llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs62
-rw-r--r--src/tools/llvm-bitcode-linker/src/lib.rs7
-rw-r--r--src/tools/llvm-bitcode-linker/src/linker.rs163
-rw-r--r--src/tools/llvm-bitcode-linker/src/opt.rs53
-rw-r--r--src/tools/llvm-bitcode-linker/src/target.rs20
-rw-r--r--src/tools/miri/src/shims/time.rs5
-rw-r--r--src/tools/miri/src/shims/windows/foreign_items.rs4
-rw-r--r--src/tools/miri/tests/pass/alloc-access-tracking.rs25
-rw-r--r--src/tools/miri/tests/pass/alloc-access-tracking.stderr37
-rw-r--r--src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs18
-rw-r--r--src/tools/run-make-support/Cargo.toml1
-rw-r--r--src/tools/run-make-support/src/lib.rs16
-rw-r--r--src/tools/rust-analyzer/.cargo/config.toml1
-rw-r--r--src/tools/rust-analyzer/.github/workflows/ci.yaml3
-rw-r--r--src/tools/rust-analyzer/.typos.toml1
-rw-r--r--src/tools/rust-analyzer/Cargo.lock638
-rw-r--r--src/tools/rust-analyzer/Cargo.toml23
-rw-r--r--src/tools/rust-analyzer/crates/base-db/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/flycheck/src/command.rs156
-rw-r--r--src/tools/rust-analyzer/crates/flycheck/src/lib.rs201
-rw-r--r--src/tools/rust-analyzer/crates/flycheck/src/test_runner.rs76
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/attr.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs23
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/data.rs5
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/db.rs13
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/expander.rs31
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/find_path.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/hir.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs5
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs71
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs40
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lib.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lower.rs37
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres.rs334
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs181
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs31
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs43
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/visibility.rs21
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/Cargo.toml3
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/builtin_attr_macro.rs25
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs95
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs54
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/change.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/db.rs26
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/eager.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/files.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs24
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/name.rs14
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/span_map.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/db.rs49
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs26
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs106
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs35
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/layout.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower.rs96
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs47
-rw-r--r--src/tools/rust-analyzer/crates/hir/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/db.rs28
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/display.rs37
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs63
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics.rs78
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/Cargo.toml5
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs27
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs18
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs80
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs33
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_macro.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_from_mod_rs.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_to_mod_rs.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/tests.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/format_string.rs95
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs20
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix/format_like.rs16
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/Cargo.toml3
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs419
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/helpers.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/lib.rs11
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string_exprs.rs58
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs9
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/tests/line_index.rs49
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml5
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs18
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/Cargo.toml12
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/expand_macro.rs60
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_definition.rs18
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/render.rs7
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/tests.rs666
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/lib.rs20
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/parent_module.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/rename.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/runnables.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/static_index.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/test_explorer.rs135
-rw-r--r--src/tools/rust-analyzer/crates/load-cargo/src/lib.rs162
-rw-r--r--src/tools/rust-analyzer/crates/parser/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar.rs6
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs14
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs5
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/items.rs45
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/items/traits.rs6
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/params.rs7
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs8
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/types.rs6
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/lexed_str.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/lib.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/parser.rs9
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/shortcuts.rs19
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0054_float_split_scientific_notation.rast88
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/err/0054_float_split_scientific_notation.rs5
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml9
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml8
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml3
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs14
-rw-r--r--src/tools/rust-analyzer/crates/profile/src/lib.rs23
-rw-r--r--src/tools/rust-analyzer/crates/project-model/Cargo.toml3
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs8
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs17
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs9
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/sysroot.rs39
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/target_data_layout.rs7
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/workspace.rs40
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs19
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs14
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs4
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs12
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs22
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/hack_recover_crate_name.rs25
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs9
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs71
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs96
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs1
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs102
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs26
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs123
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs7
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/config.rs41
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/hprof.rs23
-rw-r--r--src/tools/rust-analyzer/crates/salsa/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/salsa/salsa-macros/src/query_group.rs13
-rw-r--r--src/tools/rust-analyzer/crates/salsa/src/derived.rs14
-rw-r--r--src/tools/rust-analyzer/crates/salsa/src/runtime.rs2
-rw-r--r--src/tools/rust-analyzer/crates/salsa/tests/cycles.rs49
-rw-r--r--src/tools/rust-analyzer/crates/salsa/tests/on_demand_inputs.rs26
-rw-r--r--src/tools/rust-analyzer/crates/salsa/tests/parallel/parallel_cycle_all_recover.rs1
-rw-r--r--src/tools/rust-analyzer/crates/salsa/tests/parallel/parallel_cycle_mid_recover.rs1
-rw-r--r--src/tools/rust-analyzer/crates/salsa/tests/parallel/parallel_cycle_none_recover.rs5
-rw-r--r--src/tools/rust-analyzer/crates/salsa/tests/parallel/parallel_cycle_one_recovers.rs1
-rw-r--r--src/tools/rust-analyzer/crates/span/src/ast_id.rs14
-rw-r--r--src/tools/rust-analyzer/crates/stdx/src/process.rs5
-rw-r--r--src/tools/rust-analyzer/crates/syntax/Cargo.toml1
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/make.rs5
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/lib.rs22
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/parsing.rs2
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/tests.rs4
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/validation.rs31
-rw-r--r--src/tools/rust-analyzer/crates/test-fixture/src/lib.rs23
-rw-r--r--src/tools/rust-analyzer/crates/toolchain/src/lib.rs106
-rw-r--r--src/tools/rust-analyzer/crates/vfs/src/file_set.rs5
-rw-r--r--src/tools/rust-analyzer/crates/vfs/src/lib.rs4
-rw-r--r--src/tools/rust-analyzer/docs/dev/lsp-extensions.md126
-rw-r--r--src/tools/rust-analyzer/docs/user/generated_config.adoc10
-rw-r--r--src/tools/rust-analyzer/editors/code/package.json19
-rw-r--r--src/tools/rust-analyzer/editors/code/src/client.ts8
-rw-r--r--src/tools/rust-analyzer/editors/code/src/config.ts4
-rw-r--r--src/tools/rust-analyzer/editors/code/src/ctx.ts16
-rw-r--r--src/tools/rust-analyzer/editors/code/src/debug.ts60
-rw-r--r--src/tools/rust-analyzer/editors/code/src/lsp_ext.ts36
-rw-r--r--src/tools/rust-analyzer/editors/code/src/test_explorer.ts173
-rw-r--r--src/tools/rust-analyzer/lib/line-index/Cargo.toml5
-rw-r--r--src/tools/rust-analyzer/lib/line-index/src/tests.rs53
-rw-r--r--src/tools/rust-analyzer/lib/lsp-server/src/req_queue.rs6
-rw-r--r--src/tools/rust-analyzer/xtask/Cargo.toml3
-rw-r--r--src/tools/rust-analyzer/xtask/src/codegen.rs218
-rw-r--r--src/tools/rust-analyzer/xtask/src/codegen/assists_doc_tests.rs (renamed from src/tools/rust-analyzer/crates/ide-assists/src/tests/sourcegen.rs)26
-rw-r--r--src/tools/rust-analyzer/xtask/src/codegen/diagnostics_docs.rs (renamed from src/tools/rust-analyzer/crates/ide-diagnostics/src/tests/sourcegen.rs)28
-rw-r--r--src/tools/rust-analyzer/xtask/src/codegen/lints.rs (renamed from src/tools/rust-analyzer/crates/ide-db/src/tests/sourcegen_lints.rs)40
-rw-r--r--src/tools/rust-analyzer/xtask/src/flags.rs33
-rw-r--r--src/tools/rust-analyzer/xtask/src/main.rs18
-rw-r--r--src/tools/rust-analyzer/xtask/src/release.rs6
-rw-r--r--src/tools/tidy/src/fluent_alphabetical.rs58
-rw-r--r--src/tools/tidy/src/fluent_used.rs43
-rw-r--r--src/tools/tidy/src/lib.rs1
-rw-r--r--tests/assembly/nvptx-arch-default.rs3
-rw-r--r--tests/assembly/nvptx-arch-emit-asm.rs1
-rw-r--r--tests/assembly/nvptx-arch-target-cpu.rs3
-rw-r--r--tests/assembly/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs13
-rw-r--r--tests/assembly/nvptx-safe-naming.rs5
-rw-r--r--tests/assembly/wasm_exceptions.rs2
-rw-r--r--tests/codegen/abi-main-signature-32bit-c-int.rs1
-rw-r--r--tests/codegen/align-byval-vector.rs8
-rw-r--r--tests/codegen/align-byval.rs92
-rw-r--r--tests/codegen/align-enum.rs1
-rw-r--r--tests/codegen/align-struct.rs4
-rw-r--r--tests/codegen/debuginfo-inline-callsite-location.rs4
-rw-r--r--tests/codegen/drop.rs1
-rw-r--r--tests/codegen/dst-offset.rs4
-rw-r--r--tests/codegen/enum/enum-debug-clike.rs1
-rw-r--r--tests/codegen/enum/enum-debug-niche.rs1
-rw-r--r--tests/codegen/enum/enum-debug-tagged.rs1
-rw-r--r--tests/codegen/enum/enum-u128.rs1
-rw-r--r--tests/codegen/fn-impl-trait-self.rs1
-rw-r--r--tests/codegen/function-arguments-noopt.rs4
-rw-r--r--tests/codegen/function-arguments.rs2
-rw-r--r--tests/codegen/generic-debug.rs1
-rw-r--r--tests/codegen/link_section.rs2
-rw-r--r--tests/codegen/loongarch-abi/loongarch64-lp64d-abi.rs14
-rw-r--r--tests/codegen/mainsubprogram.rs1
-rw-r--r--tests/codegen/mainsubprogramstart.rs1
-rw-r--r--tests/codegen/mem-replace-big-type.rs2
-rw-r--r--tests/codegen/personality_lifetimes.rs1
-rw-r--r--tests/codegen/repr/transparent-imm-array.rs57
-rw-r--r--tests/codegen/repr/transparent-mips64.rs40
-rw-r--r--tests/codegen/repr/transparent-sparc64.rs101
-rw-r--r--tests/codegen/repr/transparent-struct-ptr.rs50
-rw-r--r--tests/codegen/repr/transparent-sysv64.rs23
-rw-r--r--tests/codegen/simd/unpadded-simd.rs4
-rw-r--r--tests/codegen/unwind-abis/nounwind-on-stable-panic-abort.rs1
-rw-r--r--tests/codegen/unwind-abis/nounwind-on-stable-panic-unwind.rs1
-rw-r--r--tests/codegen/unwind-abis/nounwind.rs2
-rw-r--r--tests/codegen/unwind-extern-exports.rs1
-rw-r--r--tests/codegen/unwind-extern-imports.rs1
-rw-r--r--tests/codegen/vtable-upcast.rs85
-rw-r--r--tests/codegen/wasm_exceptions.rs2
-rw-r--r--tests/incremental/change_crate_dep_kind.rs1
-rw-r--r--tests/incremental/issue-54059.rs1
-rw-r--r--tests/mir-opt/building/custom/consts.consts.built.after.mir4
-rw-r--r--tests/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir2
-rw-r--r--tests/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff2
-rw-r--r--tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir2
-rw-r--r--tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff2
-rw-r--r--tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff2
-rw-r--r--tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff2
-rw-r--r--tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff2
-rw-r--r--tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff2
-rw-r--r--tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-abort.diff2
-rw-r--r--tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-unwind.diff2
-rw-r--r--tests/mir-opt/const_prop/overwrite_with_const_with_params.rs2
-rw-r--r--tests/mir-opt/const_prop/overwrite_with_const_with_params.size_of.GVN.diff2
-rw-r--r--tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-abort.diff2
-rw-r--r--tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-unwind.diff2
-rw-r--r--tests/mir-opt/const_prop/pointer_expose_address.rs2
-rw-r--r--tests/mir-opt/const_prop/ref_deref.main.GVN.diff2
-rw-r--r--tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff2
-rw-r--r--tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff2
-rw-r--r--tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff2
-rw-r--r--tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff2
-rw-r--r--tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff2
-rw-r--r--tests/mir-opt/const_prop/transmute.invalid_char.GVN.32bit.diff2
-rw-r--r--tests/mir-opt/const_prop/transmute.invalid_char.GVN.64bit.diff2
-rw-r--r--tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff2
-rw-r--r--tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff2
-rw-r--r--tests/mir-opt/dataflow-const-prop/checked.rs2
-rw-r--r--tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.32bit.diff2
-rw-r--r--tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.64bit.diff2
-rw-r--r--tests/mir-opt/dataflow-const-prop/enum.rs2
-rw-r--r--tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-abort.diff4
-rw-r--r--tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-unwind.diff4
-rw-r--r--tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-abort.diff4
-rw-r--r--tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-unwind.diff4
-rw-r--r--tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff4
-rw-r--r--tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff4
-rw-r--r--tests/mir-opt/dataflow-const-prop/transmute.invalid_char.DataflowConstProp.32bit.diff2
-rw-r--r--tests/mir-opt/dataflow-const-prop/transmute.invalid_char.DataflowConstProp.64bit.diff2
-rw-r--r--tests/mir-opt/derefer_complex_case.main.Derefer.panic-abort.diff2
-rw-r--r--tests/mir-opt/derefer_complex_case.main.Derefer.panic-unwind.diff2
-rw-r--r--tests/mir-opt/gvn.arithmetic.GVN.panic-abort.diff4
-rw-r--r--tests/mir-opt/gvn.arithmetic.GVN.panic-unwind.diff4
-rw-r--r--tests/mir-opt/gvn.constant_index_overflow.GVN.panic-abort.diff2
-rw-r--r--tests/mir-opt/gvn.constant_index_overflow.GVN.panic-unwind.diff2
-rw-r--r--tests/mir-opt/gvn.wide_ptr_provenance.GVN.panic-abort.diff4
-rw-r--r--tests/mir-opt/gvn.wide_ptr_provenance.GVN.panic-unwind.diff4
-rw-r--r--tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-abort.diff2
-rw-r--r--tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-unwind.diff2
-rw-r--r--tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff2
-rw-r--r--tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff2
-rw-r--r--tests/mir-opt/inline/inline_retag.bar.Inline.after.mir4
-rw-r--r--tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff4
-rw-r--r--tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff4
-rw-r--r--tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify.diff2
-rw-r--r--tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-abort.diff2
-rw-r--r--tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-unwind.diff2
-rw-r--r--tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.panic-abort.diff6
-rw-r--r--tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.panic-unwind.diff6
-rw-r--r--tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.mir2
-rw-r--r--tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff2
-rw-r--r--tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff2
-rw-r--r--tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff2
-rw-r--r--tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff2
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir2
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir2
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir2
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir2
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir2
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir2
-rw-r--r--tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff6
-rw-r--r--tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-abort.mir2
-rw-r--r--tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-unwind.mir2
-rw-r--r--tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-abort.mir2
-rw-r--r--tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir2
-rw-r--r--tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff2
-rw-r--r--tests/mir-opt/sroa/structs.constant.ScalarReplacementOfAggregates.diff2
-rw-r--r--tests/run-make/min-global-align/min_global_align.rs2
-rw-r--r--tests/run-make/wasm-abi/Makefile7
-rw-r--r--tests/run-make/wasm-abi/foo.js22
-rw-r--r--tests/run-make/wasm-abi/host.wat22
-rw-r--r--tests/run-make/wasm-abi/rmake.rs43
-rw-r--r--tests/run-make/wasm-custom-section/Makefile8
-rw-r--r--tests/run-make/wasm-custom-section/foo.js36
-rw-r--r--tests/run-make/wasm-custom-section/rmake.rs28
-rw-r--r--tests/run-make/wasm-custom-sections-opt/Makefile7
-rw-r--r--tests/run-make/wasm-custom-sections-opt/foo.js15
-rw-r--r--tests/run-make/wasm-custom-sections-opt/rmake.rs30
-rw-r--r--tests/run-make/wasm-export-all-symbols/Makefile19
-rw-r--r--tests/run-make/wasm-export-all-symbols/rmake.rs60
-rw-r--r--tests/run-make/wasm-export-all-symbols/verify.js32
-rw-r--r--tests/run-make/wasm-import-module/Makefile8
-rw-r--r--tests/run-make/wasm-import-module/foo.js18
-rw-r--r--tests/run-make/wasm-import-module/rmake.rs32
-rw-r--r--tests/run-make/wasm-panic-small/Makefile17
-rw-r--r--tests/run-make/wasm-panic-small/rmake.rs32
-rw-r--r--tests/run-make/wasm-spurious-import/Makefile7
-rw-r--r--tests/run-make/wasm-spurious-import/rmake.rs35
-rw-r--r--tests/run-make/wasm-spurious-import/verify.js9
-rw-r--r--tests/run-make/wasm-stringify-ints-small/Makefile10
-rw-r--r--tests/run-make/wasm-stringify-ints-small/rmake.rs17
-rw-r--r--tests/run-make/wasm-symbols-different-module/Makefile28
-rw-r--r--tests/run-make/wasm-symbols-different-module/rmake.rs52
-rw-r--r--tests/run-make/wasm-symbols-different-module/verify-imports.js32
-rw-r--r--tests/run-make/wasm-symbols-not-exported/Makefile13
-rw-r--r--tests/run-make/wasm-symbols-not-exported/rmake.rs41
-rw-r--r--tests/run-make/wasm-symbols-not-exported/verify-exported-symbols.js21
-rw-r--r--tests/run-make/wasm-symbols-not-imported/Makefile13
-rw-r--r--tests/run-make/wasm-symbols-not-imported/rmake.rs31
-rw-r--r--tests/run-make/wasm-symbols-not-imported/verify-no-imports.js10
-rw-r--r--tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh25
-rw-r--r--tests/run-pass-valgrind/exit-flushes.rs2
-rw-r--r--tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs9
-rw-r--r--tests/rustdoc/empty-section.rs4
-rw-r--r--tests/rustdoc/synthetic_auto/basic.rs2
-rw-r--r--tests/rustdoc/synthetic_auto/manual.rs2
-rw-r--r--tests/ui-fulldeps/internal-lints/diagnostics.rs48
-rw-r--r--tests/ui-fulldeps/internal-lints/diagnostics.stderr4
-rw-r--r--tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs12
-rw-r--r--tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr12
-rw-r--r--tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs6
-rw-r--r--tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr4
-rw-r--r--tests/ui/abi/anon-extern-mod.rs1
-rw-r--r--tests/ui/abi/c-stack-as-value.rs1
-rw-r--r--tests/ui/abi/c-stack-returning-int64.rs1
-rw-r--r--tests/ui/abi/cabi-int-widening.rs1
-rw-r--r--tests/ui/abi/cross-crate/anon-extern-mod-cross-crate-2.rs1
-rw-r--r--tests/ui/abi/cross-crate/duplicated-external-mods.rs1
-rw-r--r--tests/ui/abi/extern/extern-call-deep.rs1
-rw-r--r--tests/ui/abi/extern/extern-call-indirect.rs1
-rw-r--r--tests/ui/abi/extern/extern-crosscrate.rs1
-rw-r--r--tests/ui/abi/extern/extern-pass-TwoU16s.rs2
-rw-r--r--tests/ui/abi/extern/extern-pass-TwoU32s.rs2
-rw-r--r--tests/ui/abi/extern/extern-pass-TwoU64s.rs2
-rw-r--r--tests/ui/abi/extern/extern-pass-TwoU8s.rs2
-rw-r--r--tests/ui/abi/extern/extern-pass-char.rs1
-rw-r--r--tests/ui/abi/extern/extern-pass-double.rs1
-rw-r--r--tests/ui/abi/extern/extern-pass-u32.rs1
-rw-r--r--tests/ui/abi/extern/extern-pass-u64.rs1
-rw-r--r--tests/ui/abi/extern/extern-return-TwoU16s.rs2
-rw-r--r--tests/ui/abi/extern/extern-return-TwoU32s.rs2
-rw-r--r--tests/ui/abi/extern/extern-return-TwoU64s.rs2
-rw-r--r--tests/ui/abi/extern/extern-return-TwoU8s.rs2
-rw-r--r--tests/ui/abi/foreign/foreign-dupe.rs1
-rw-r--r--tests/ui/abi/foreign/foreign-fn-with-byval.rs2
-rw-r--r--tests/ui/abi/foreign/foreign-no-abi.rs1
-rw-r--r--tests/ui/abi/foreign/invoke-external-foreign.rs1
-rw-r--r--tests/ui/abi/homogenous-floats-target-feature-mixup.rs2
-rw-r--r--tests/ui/abi/issue-28676.rs2
-rw-r--r--tests/ui/abi/issues/issue-62350-sysv-neg-reg-counts.rs2
-rw-r--r--tests/ui/abi/issues/issue-97463-broken-abi-leaked-uninit-data.rs1
-rw-r--r--tests/ui/abi/lib-defaults.rs2
-rw-r--r--tests/ui/abi/mir/mir_codegen_calls_variadic.rs1
-rw-r--r--tests/ui/abi/segfault-no-out-of-stack.rs2
-rw-r--r--tests/ui/abi/statics/static-mut-foreign.rs2
-rw-r--r--tests/ui/abi/statics/static-mut-foreign.stderr4
-rw-r--r--tests/ui/abi/struct-enums/struct-return.rs1
-rw-r--r--tests/ui/abi/union/union-c-interop.rs2
-rw-r--r--tests/ui/abi/variadic-ffi.rs1
-rw-r--r--tests/ui/alloc-error/default-alloc-error-hook.rs2
-rw-r--r--tests/ui/allocator/no_std-alloc-error-handler-custom.rs1
-rw-r--r--tests/ui/allocator/no_std-alloc-error-handler-default.rs1
-rw-r--r--tests/ui/asm/issue-87802.rs1
-rw-r--r--tests/ui/asm/issue-87802.stderr2
-rw-r--r--tests/ui/asm/naked-functions.rs1
-rw-r--r--tests/ui/asm/naked-functions.stderr70
-rw-r--r--tests/ui/asm/named-asm-labels.rs1
-rw-r--r--tests/ui/asm/named-asm-labels.stderr92
-rw-r--r--tests/ui/asm/type-check-1.rs1
-rw-r--r--tests/ui/asm/type-check-1.stderr34
-rw-r--r--tests/ui/asm/type-check-4.rs1
-rw-r--r--tests/ui/asm/type-check-4.stderr4
-rw-r--r--tests/ui/associated-consts/assoc-const-eq-supertraits.rs16
-rw-r--r--tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs16
-rw-r--r--tests/ui/associated-consts/freeze.rs12
-rw-r--r--tests/ui/associated-inherent-types/bugs/wf-check-skipped.next.stderr8
-rw-r--r--tests/ui/associated-inherent-types/bugs/wf-check-skipped.rs11
-rw-r--r--tests/ui/associated-inherent-types/inference.rs1
-rw-r--r--tests/ui/associated-types/defaults-unsound-62211-1.current.stderr (renamed from tests/ui/associated-types/defaults-unsound-62211-2.stderr)16
-rw-r--r--tests/ui/associated-types/defaults-unsound-62211-1.next.stderr13
-rw-r--r--tests/ui/associated-types/defaults-unsound-62211-1.rs14
-rw-r--r--tests/ui/associated-types/defaults-unsound-62211-2.current.stderr (renamed from tests/ui/associated-types/defaults-unsound-62211-1.stderr)16
-rw-r--r--tests/ui/associated-types/defaults-unsound-62211-2.next.stderr13
-rw-r--r--tests/ui/associated-types/defaults-unsound-62211-2.rs14
-rw-r--r--tests/ui/async-await/async-closures/is-fn.rs1
-rw-r--r--tests/ui/async-await/async-closures/once.rs1
-rw-r--r--tests/ui/async-await/async-fn/higher-ranked-async-fn.rs1
-rw-r--r--tests/ui/async-await/async-fn/project.rs1
-rw-r--r--tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-completion.rs2
-rw-r--r--tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs1
-rw-r--r--tests/ui/async-await/issues/issue-65419/issue-65419-coroutine-resume-after-completion.rs2
-rw-r--r--tests/ui/async-await/normalize-output-in-signature-deduction.rs1
-rw-r--r--tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.current.stderr2
-rw-r--r--tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.next.stderr2
-rw-r--r--tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.rs1
-rw-r--r--tests/ui/attributes/unix_sigpipe/unix_sigpipe-bare.rs2
-rw-r--r--tests/ui/attributes/unix_sigpipe/unix_sigpipe-bare.stderr4
-rw-r--r--tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.rs2
-rw-r--r--tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr6
-rw-r--r--tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.rs2
-rw-r--r--tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.stderr11
-rw-r--r--tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.rs2
-rw-r--r--tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.stderr2
-rw-r--r--tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.rs2
-rw-r--r--tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.stderr2
-rw-r--r--tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.rs2
-rw-r--r--tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.stderr2
-rw-r--r--tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.rs2
-rw-r--r--tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.stderr2
-rw-r--r--tests/ui/auto-traits/issue-23080-2.current.stderr2
-rw-r--r--tests/ui/auto-traits/issue-23080-2.next.stderr2
-rw-r--r--tests/ui/auto-traits/issue-23080-2.rs1
-rw-r--r--tests/ui/backtrace.rs2
-rw-r--r--tests/ui/binop/issue-77910-1.stderr26
-rw-r--r--tests/ui/binop/issue-77910-2.stderr26
-rw-r--r--tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr46
-rw-r--r--tests/ui/borrowck/two-phase-reservation-sharing-interference.rs2
-rw-r--r--tests/ui/cfg/cfg-family.rs2
-rw-r--r--tests/ui/check-static-recursion-foreign.rs1
-rw-r--r--tests/ui/closures/infer-signature-from-impl.next.stderr2
-rw-r--r--tests/ui/closures/infer-signature-from-impl.rs1
-rw-r--r--tests/ui/codegen/issue-27859.rs1
-rw-r--r--tests/ui/coherence/indirect-impl-for-trait-obj-coherence.next.stderr9
-rw-r--r--tests/ui/coherence/indirect-impl-for-trait-obj-coherence.rs8
-rw-r--r--tests/ui/coherence/normalize-for-errors.current.stderr2
-rw-r--r--tests/ui/coherence/normalize-for-errors.next.stderr2
-rw-r--r--tests/ui/coherence/normalize-for-errors.rs1
-rw-r--r--tests/ui/command/command-argv0.rs2
-rw-r--r--tests/ui/command/command-current-dir.rs2
-rw-r--r--tests/ui/command/command-exec.rs2
-rw-r--r--tests/ui/command/command-pre-exec.rs2
-rw-r--r--tests/ui/command/command-setgroups.rs2
-rw-r--r--tests/ui/command/issue-10626.rs2
-rw-r--r--tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr12
-rw-r--r--tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr16
-rw-r--r--tests/ui/const-generics/transmute-fail.stderr24
-rw-r--r--tests/ui/const-generics/type_mismatch.stderr12
-rw-r--r--tests/ui/consts/enclosing-scope-rule.rs16
-rw-r--r--tests/ui/consts/promote-not.rs21
-rw-r--r--tests/ui/consts/promote-not.stderr73
-rw-r--r--tests/ui/consts/refs-to-cell-in-final.rs23
-rw-r--r--tests/ui/consts/refs-to-cell-in-final.stderr8
-rw-r--r--tests/ui/consts/trait_specialization.rs1
-rw-r--r--tests/ui/consts/trait_specialization.stderr2
-rw-r--r--tests/ui/coroutine/clone-rpit.next.stderr18
-rw-r--r--tests/ui/coroutine/clone-rpit.rs1
-rw-r--r--tests/ui/coroutine/non-static-is-unpin.rs1
-rw-r--r--tests/ui/coroutine/size-moved-locals.rs1
-rw-r--r--tests/ui/coroutine/static-not-unpin.current.stderr8
-rw-r--r--tests/ui/coroutine/static-not-unpin.next.stderr8
-rw-r--r--tests/ui/coroutine/static-not-unpin.rs1
-rw-r--r--tests/ui/duplicate/dupe-symbols-7.rs1
-rw-r--r--tests/ui/duplicate/dupe-symbols-7.stderr2
-rw-r--r--tests/ui/duplicate/dupe-symbols-8.rs1
-rw-r--r--tests/ui/duplicate/dupe-symbols-8.stderr2
-rw-r--r--tests/ui/dyn-star/box.rs1
-rw-r--r--tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.current.stderr2
-rw-r--r--tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.next.stderr2
-rw-r--r--tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs1
-rw-r--r--tests/ui/dyn-star/thin.next.stderr11
-rw-r--r--tests/ui/dyn-star/thin.old.stderr11
-rw-r--r--tests/ui/dyn-star/thin.rs16
-rw-r--r--tests/ui/env-args-reverse-iterator.rs2
-rw-r--r--tests/ui/env-funky-keys.rs2
-rw-r--r--tests/ui/env-null-vars.rs1
-rw-r--r--tests/ui/env-vars.rs1
-rw-r--r--tests/ui/exec-env.rs2
-rw-r--r--tests/ui/explicit-tail-calls/return-mismatches.stderr12
-rw-r--r--tests/ui/expr/if/if-no-match-bindings.stderr18
-rw-r--r--tests/ui/extern/extern-const.fixed1
-rw-r--r--tests/ui/extern/extern-const.rs1
-rw-r--r--tests/ui/extern/extern-const.stderr2
-rw-r--r--tests/ui/extern/issue-1251.rs1
-rw-r--r--tests/ui/feature-gates/feature-gate-freeze-impls.rs15
-rw-r--r--tests/ui/feature-gates/feature-gate-freeze-impls.stderr23
-rw-r--r--tests/ui/for/issue-20605.current.stderr2
-rw-r--r--tests/ui/for/issue-20605.next.stderr10
-rw-r--r--tests/ui/for/issue-20605.rs1
-rw-r--r--tests/ui/foreign/foreign-fn-linkname.rs1
-rw-r--r--tests/ui/foreign/foreign2.rs1
-rw-r--r--tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.current.stderr (renamed from tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.stderr)6
-rw-r--r--tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.rs6
-rw-r--r--tests/ui/generic-associated-types/issue-102114.current.stderr2
-rw-r--r--tests/ui/generic-associated-types/issue-102114.next.stderr2
-rw-r--r--tests/ui/generic-associated-types/issue-102114.rs1
-rw-r--r--tests/ui/generic-associated-types/issue-74684-2.stderr32
-rw-r--r--tests/ui/generic-associated-types/issue-88595.rs1
-rw-r--r--tests/ui/generic-associated-types/issue-88595.stderr16
-rw-r--r--tests/ui/generic-associated-types/issue-90014-tait2.next-solver.stderr15
-rw-r--r--tests/ui/generic-const-items/associated-const-equality.rs11
-rw-r--r--tests/ui/higher-ranked/trait-bounds/fn-ptr.current.stderr19
-rw-r--r--tests/ui/higher-ranked/trait-bounds/fn-ptr.rs5
-rw-r--r--tests/ui/higher-ranked/trait-bounds/future.current.stderr6
-rw-r--r--tests/ui/higher-ranked/trait-bounds/future.rs17
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr26
-rw-r--r--tests/ui/hygiene/panic-location.rs1
-rw-r--r--tests/ui/hygiene/panic-location.run.stderr2
-rw-r--r--tests/ui/impl-trait/auto-trait-leak.stderr6
-rw-r--r--tests/ui/impl-trait/autoderef.rs1
-rw-r--r--tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr4
-rw-r--r--tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr4
-rw-r--r--tests/ui/impl-trait/erased-regions-in-hidden-ty.rs1
-rw-r--r--tests/ui/impl-trait/in-trait/object-safety-sized.rs1
-rw-r--r--tests/ui/impl-trait/in-trait/refine-normalize.rs1
-rw-r--r--tests/ui/impl-trait/issue-103181-1.current.stderr2
-rw-r--r--tests/ui/impl-trait/issue-103181-1.next.stderr2
-rw-r--r--tests/ui/impl-trait/issue-103181-1.rs1
-rw-r--r--tests/ui/impl-trait/issues/issue-78722-2.rs4
-rw-r--r--tests/ui/impl-trait/issues/issue-78722-2.stderr33
-rw-r--r--tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr4
-rw-r--r--tests/ui/impl-trait/recursive-coroutine-boxed.rs1
-rw-r--r--tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr2
-rw-r--r--tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr2
-rw-r--r--tests/ui/impl-trait/recursive-coroutine-indirect.rs1
-rw-r--r--tests/ui/impl-trait/reveal-during-codegen.rs1
-rw-r--r--tests/ui/impl-trait/two_tait_defining_each_other.current.stderr6
-rw-r--r--tests/ui/impl-trait/two_tait_defining_each_other.rs1
-rw-r--r--tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr8
-rw-r--r--tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr2
-rw-r--r--tests/ui/impl-trait/two_tait_defining_each_other2.rs1
-rw-r--r--tests/ui/impl-trait/two_tait_defining_each_other3.current.stderr6
-rw-r--r--tests/ui/impl-trait/two_tait_defining_each_other3.rs1
-rw-r--r--tests/ui/inference/type-infer-generalize-ty-var.rs1
-rw-r--r--tests/ui/inherit-env.rs3
-rw-r--r--tests/ui/intrinsics/intrinsic-alignment.rs11
-rw-r--r--tests/ui/intrinsics/panic-uninitialized-zeroed.rs2
-rw-r--r--tests/ui/io-checks/non-ice-error-on-worker-io-fail.rs1
-rw-r--r--tests/ui/issues/issue-11374.stderr18
-rw-r--r--tests/ui/issues/issue-12133-3.rs2
-rw-r--r--tests/ui/issues/issue-12699.rs1
-rw-r--r--tests/ui/issues/issue-13167.rs1
-rw-r--r--tests/ui/issues/issue-15734.rs1
-rw-r--r--tests/ui/issues/issue-2214.rs2
-rw-r--r--tests/ui/issues/issue-25185.rs1
-rw-r--r--tests/ui/issues/issue-33770.rs2
-rw-r--r--tests/ui/issues/issue-33992.rs2
-rw-r--r--tests/ui/issues/issue-3656.rs1
-rw-r--r--tests/ui/issues/issue-39175.rs2
-rw-r--r--tests/ui/issues/issue-44216-add-instant.rs5
-rw-r--r--tests/ui/kindck/kindck-impl-type-params.stderr18
-rw-r--r--tests/ui/kindck/kindck-send-object1.stderr16
-rw-r--r--tests/ui/lazy-type-alias/coerce-behind-lazy.current.stderr2
-rw-r--r--tests/ui/lazy-type-alias/coerce-behind-lazy.next.stderr2
-rw-r--r--tests/ui/lazy-type-alias/coerce-behind-lazy.rs1
-rw-r--r--tests/ui/lazy-type-alias/inherent-impls-overflow.current.stderr43
-rw-r--r--tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr8
-rw-r--r--tests/ui/lazy-type-alias/inherent-impls-overflow.rs13
-rw-r--r--tests/ui/lifetimes/issue-17728.stderr32
-rw-r--r--tests/ui/linkage-attr/common-linkage-non-zero-init.rs1
-rw-r--r--tests/ui/lint/dead-code/issue-41883.stderr2
-rw-r--r--tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr2
-rw-r--r--tests/ui/lint/dead-code/unused-adt-impls-pub-trait.rs17
-rw-r--r--tests/ui/lint/dead-code/unused-adt-impls-pub-trait.stderr14
-rw-r--r--tests/ui/lint/issue-99387.rs2
-rw-r--r--tests/ui/lint/issue-99387.stderr17
-rw-r--r--tests/ui/liveness/liveness-consts.stderr12
-rw-r--r--tests/ui/liveness/liveness-forgot-ret.stderr22
-rw-r--r--tests/ui/liveness/liveness-unused.stderr30
-rw-r--r--tests/ui/loops/issue-69225-SCEVAddExpr-wrap-flag.rs2
-rw-r--r--tests/ui/loops/issue-69225-layout-repeated-checked-add.rs2
-rw-r--r--tests/ui/macros/assert-long-condition.rs1
-rw-r--r--tests/ui/macros/assert-long-condition.run.stderr2
-rw-r--r--tests/ui/macros/macros-in-extern.rs1
-rw-r--r--tests/ui/mir/alignment/misaligned_lhs.rs1
-rw-r--r--tests/ui/mir/alignment/misaligned_rhs.rs1
-rw-r--r--tests/ui/mir/alignment/two_pointers.rs1
-rw-r--r--tests/ui/never_type/never-from-impl-is-reserved.current.stderr2
-rw-r--r--tests/ui/never_type/never-from-impl-is-reserved.next.stderr2
-rw-r--r--tests/ui/never_type/never-from-impl-is-reserved.rs1
-rw-r--r--tests/ui/nll/issue-53119.rs1
-rw-r--r--tests/ui/non-copyable-void.rs2
-rw-r--r--tests/ui/non-copyable-void.stderr2
-rw-r--r--tests/ui/numbers-arithmetic/location-add-assign-overflow.rs1
-rw-r--r--tests/ui/numbers-arithmetic/location-add-overflow.rs1
-rw-r--r--tests/ui/numbers-arithmetic/location-divide-assign-by-zero.rs1
-rw-r--r--tests/ui/numbers-arithmetic/location-divide-by-zero.rs1
-rw-r--r--tests/ui/numbers-arithmetic/location-mod-assign-by-zero.rs1
-rw-r--r--tests/ui/numbers-arithmetic/location-mod-by-zero.rs1
-rw-r--r--tests/ui/numbers-arithmetic/location-mul-assign-overflow.rs1
-rw-r--r--tests/ui/numbers-arithmetic/location-mul-overflow.rs1
-rw-r--r--tests/ui/numbers-arithmetic/location-sub-assign-overflow.rs1
-rw-r--r--tests/ui/numbers-arithmetic/location-sub-overflow.rs1
-rw-r--r--tests/ui/object-safety/call-when-assoc-ty-is-sized.rs1
-rw-r--r--tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs2
-rw-r--r--tests/ui/panic-runtime/abort.rs2
-rw-r--r--tests/ui/panic-runtime/lto-abort.rs2
-rw-r--r--tests/ui/panics/abort-on-panic.rs3
-rw-r--r--tests/ui/panics/runtime-switch.rs2
-rw-r--r--tests/ui/panics/short-ice-remove-middle-frames-2.rs1
-rw-r--r--tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr2
-rw-r--r--tests/ui/panics/short-ice-remove-middle-frames.rs1
-rw-r--r--tests/ui/panics/short-ice-remove-middle-frames.run.stderr2
-rw-r--r--tests/ui/panics/test-should-fail-bad-message.rs2
-rw-r--r--tests/ui/panics/test-should-panic-bad-message.rs2
-rw-r--r--tests/ui/panics/test-should-panic-no-message.rs2
-rw-r--r--tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-1.rs14
-rw-r--r--tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-1.stderr17
-rw-r--r--tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-2.rs5
-rw-r--r--tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-2.stderr10
-rw-r--r--tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-3.rs14
-rw-r--r--tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-3.stderr16
-rw-r--r--tests/ui/paths-containing-nul.rs3
-rw-r--r--tests/ui/precondition-checks/misaligned-slice.rs1
-rw-r--r--tests/ui/precondition-checks/null-slice.rs1
-rw-r--r--tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs1
-rw-r--r--tests/ui/print-stdout-eprint-stderr.rs2
-rw-r--r--tests/ui/privacy/pub-extern-privacy.rs1
-rw-r--r--tests/ui/proc-macro/crt-static.rs1
-rw-r--r--tests/ui/proc-macro/macros-in-extern.rs1
-rw-r--r--tests/ui/process/core-run-destroy.rs2
-rw-r--r--tests/ui/process/fds-are-cloexec.rs2
-rw-r--r--tests/ui/process/issue-13304.rs2
-rw-r--r--tests/ui/process/issue-14456.rs2
-rw-r--r--tests/ui/process/issue-14940.rs2
-rw-r--r--tests/ui/process/issue-16272.rs2
-rw-r--r--tests/ui/process/issue-20091.rs3
-rw-r--r--tests/ui/process/multi-panic.rs2
-rw-r--r--tests/ui/process/no-stdio.rs2
-rw-r--r--tests/ui/process/println-with-broken-pipe.rs2
-rw-r--r--tests/ui/process/process-envs.rs2
-rw-r--r--tests/ui/process/process-exit.rs2
-rw-r--r--tests/ui/process/process-panic-after-fork.rs4
-rw-r--r--tests/ui/process/process-remove-from-env.rs2
-rw-r--r--tests/ui/process/process-sigpipe.rs1
-rw-r--r--tests/ui/process/process-spawn-nonexistent.rs2
-rw-r--r--tests/ui/process/process-spawn-with-unicode-params.rs2
-rw-r--r--tests/ui/process/process-status-inherits-stdin.rs2
-rw-r--r--tests/ui/process/signal-exit-status.rs2
-rw-r--r--tests/ui/process/sigpipe-should-be-ignored.rs2
-rw-r--r--tests/ui/process/tls-exit-status.rs2
-rw-r--r--tests/ui/process/try-wait.rs3
-rw-r--r--tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr22
-rw-r--r--tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr22
-rw-r--r--tests/ui/regions/regions-lifetime-bounds-on-fns.stderr22
-rw-r--r--tests/ui/rfcs/rfc-1014-stdout-existential-crisis/rfc-1014.rs1
-rw-r--r--tests/ui/rfcs/rfc-1717-dllimport/1717-dllimport/library-override.rs1
-rw-r--r--tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr2
-rw-r--r--tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr2
-rw-r--r--tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs1
-rw-r--r--tests/ui/runtime/atomic-print.rs2
-rw-r--r--tests/ui/runtime/backtrace-debuginfo.rs2
-rw-r--r--tests/ui/runtime/out-of-stack.rs2
-rw-r--r--tests/ui/runtime/running-with-no-runtime.rs2
-rw-r--r--tests/ui/runtime/signal-alternate-stack-cleanup.rs2
-rw-r--r--tests/ui/rust-2018/uniform-paths/issue-55779.rs2
-rw-r--r--tests/ui/simd/target-feature-mixup.rs2
-rw-r--r--tests/ui/single-use-lifetime/dedup.rs9
-rw-r--r--tests/ui/single-use-lifetime/dedup.stderr11
-rw-r--r--tests/ui/std-backtrace.rs2
-rw-r--r--tests/ui/stdio-is-blocking.rs2
-rw-r--r--tests/ui/structs-enums/rec-align-u64.rs9
-rw-r--r--tests/ui/suggestions/issue-102892.stderr32
-rw-r--r--tests/ui/test-attrs/test-passed-wasm.rs20
-rw-r--r--tests/ui/test-attrs/test-passed-wasm.run.stdout7
-rw-r--r--tests/ui/test-attrs/test-passed.rs1
-rw-r--r--tests/ui/threads-sendsync/sync-send-in-std.rs2
-rw-r--r--tests/ui/traits/augmented-assignments-trait.rs2
-rw-r--r--tests/ui/traits/deny-builtin-object-impl.current.stderr6
-rw-r--r--tests/ui/traits/deny-builtin-object-impl.next.stderr6
-rw-r--r--tests/ui/traits/deny-builtin-object-impl.rs1
-rw-r--r--tests/ui/traits/issue-24010.rs3
-rw-r--r--tests/ui/traits/issue-33187.rs2
-rw-r--r--tests/ui/traits/negative-impls/negative-impl-normalizes-to.rs1
-rw-r--r--tests/ui/traits/next-solver/env-shadows-impls/discard-impls-shadowed-by-env-2.rs3
-rw-r--r--tests/ui/traits/next-solver/normalize-param-env-4.next.stderr8
-rw-r--r--tests/ui/traits/next-solver/normalize-param-env-4.rs1
-rw-r--r--tests/ui/traits/non-lifetime-via-dyn-builtin.current.stderr2
-rw-r--r--tests/ui/traits/non-lifetime-via-dyn-builtin.next.stderr2
-rw-r--r--tests/ui/traits/non-lifetime-via-dyn-builtin.rs1
-rw-r--r--tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.current.stderr2
-rw-r--r--tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.next.stderr2
-rw-r--r--tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.rs1
-rw-r--r--tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.current.stderr2
-rw-r--r--tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.next.stderr2
-rw-r--r--tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.rs1
-rw-r--r--tests/ui/traits/pointee-tail-is-generic.rs10
-rw-r--r--tests/ui/traits/trait-upcasting/add-supertrait-auto-traits.rs1
-rw-r--r--tests/ui/traits/trait-upcasting/fewer-associated.rs1
-rw-r--r--tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.current.stderr2
-rw-r--r--tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.next.stderr2
-rw-r--r--tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.rs1
-rw-r--r--tests/ui/traits/trait-upcasting/issue-11515.current.stderr2
-rw-r--r--tests/ui/traits/trait-upcasting/issue-11515.next.stderr2
-rw-r--r--tests/ui/traits/trait-upcasting/issue-11515.rs1
-rw-r--r--tests/ui/traits/trait-upcasting/normalization.rs1
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr2
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-1.next.stderr2
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-1.rs1
-rw-r--r--tests/ui/traits/trait-upcasting/upcast-through-struct-tail.current.stderr2
-rw-r--r--tests/ui/traits/trait-upcasting/upcast-through-struct-tail.next.stderr2
-rw-r--r--tests/ui/traits/trait-upcasting/upcast-through-struct-tail.rs1
-rw-r--r--tests/ui/transmutability/primitives/bool.current.stderr4
-rw-r--r--tests/ui/transmutability/primitives/bool.next.stderr4
-rw-r--r--tests/ui/transmutability/primitives/bool.rs1
-rw-r--r--tests/ui/transmutability/primitives/numbers.current.stderr228
-rw-r--r--tests/ui/transmutability/primitives/numbers.next.stderr228
-rw-r--r--tests/ui/transmutability/primitives/numbers.rs1
-rw-r--r--tests/ui/transmutability/primitives/unit.current.stderr4
-rw-r--r--tests/ui/transmutability/primitives/unit.next.stderr4
-rw-r--r--tests/ui/transmutability/primitives/unit.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/assoc-type-const.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr6
-rw-r--r--tests/ui/type-alias-impl-trait/cross_inference.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr24
-rw-r--r--tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr18
-rw-r--r--tests/ui/type-alias-impl-trait/hidden_type_mismatch.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr27
-rw-r--r--tests/ui/type-alias-impl-trait/higher_kinded_params2.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/higher_kinded_params2.stderr13
-rw-r--r--tests/ui/type-alias-impl-trait/higher_kinded_params3.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr26
-rw-r--r--tests/ui/type-alias-impl-trait/implied_bounds_from_types.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/implied_bounds_from_types.stderr17
-rw-r--r--tests/ui/type-alias-impl-trait/in-where-clause.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/inference-cycle.stderr6
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53092-2.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53092-2.stderr20
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53092.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53092.stderr21
-rw-r--r--tests/ui/type-alias-impl-trait/issue-70121.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-70121.stderr17
-rw-r--r--tests/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/issue-77179.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-77179.stderr36
-rw-r--r--tests/ui/type-alias-impl-trait/issue-78450.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/multi-error.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/multi-error.stderr11
-rw-r--r--tests/ui/type-alias-impl-trait/nested_inference_failure.rs5
-rw-r--r--tests/ui/type-alias-impl-trait/non-defining-method.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/non-defining-method.stderr10
-rw-r--r--tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/normalize-hidden-types.rs7
-rw-r--r--tests/ui/type-alias-impl-trait/reveal_local.stderr12
-rw-r--r--tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/self-referential-2.current.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/self-referential-2.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.next.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/type_of_a_let.current.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/type_of_a_let.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/variance.stderr132
-rw-r--r--tests/ui/typeck/issue-103899.rs12
-rw-r--r--tests/ui/unsized/issue-71659.current.stderr4
-rw-r--r--tests/ui/unsized/issue-71659.next.stderr4
-rw-r--r--tests/ui/unsized/issue-71659.rs1
-rw-r--r--tests/ui/unsized/issue-75899.rs1
-rw-r--r--tests/ui/variance/variance-associated-consts.stderr12
-rw-r--r--tests/ui/variance/variance-regions-direct.stderr16
-rw-r--r--tests/ui/variance/variance-regions-indirect.stderr60
-rw-r--r--tests/ui/variance/variance-trait-bounds.stderr48
-rw-r--r--tests/ui/wait-forked-but-failed-child.rs2
-rw-r--r--tests/ui/wf/wf-normalization-sized.next.stderr30
-rw-r--r--tests/ui/wf/wf-normalization-sized.rs11
-rw-r--r--triagebot.toml1
1350 files changed, 19368 insertions, 10687 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index cd13ce35007..f436c236dc9 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -337,7 +337,7 @@ jobs:
           - name: dist-x86_64-apple
             env:
               SCRIPT: "./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin"
-              RUST_CONFIGURE_ARGS: "--enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set rust.lto=thin"
+              RUST_CONFIGURE_ARGS: "--enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set rust.lto=thin --set rust.codegen-units=1"
               RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
               MACOSX_DEPLOYMENT_TARGET: 10.12
               SELECT_XCODE: /Applications/Xcode_14.3.1.app
@@ -442,7 +442,7 @@ jobs:
             os: windows-2019-8core-32gb
           - name: dist-x86_64-msvc
             env:
-              RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=x86_64-pc-windows-msvc --target=x86_64-pc-windows-msvc --enable-full-tools --enable-profiler"
+              RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --host=x86_64-pc-windows-msvc --target=x86_64-pc-windows-msvc --enable-full-tools --enable-profiler --set rust.codegen-units=1"
               SCRIPT: python x.py build --set rust.debug=true opt-dist && PGO_HOST=x86_64-pc-windows-msvc ./build/x86_64-pc-windows-msvc/stage0-tools-bin/opt-dist windows-ci -- python x.py dist bootstrap --include-default-paths
               DIST_REQUIRE_ALL_TOOLS: 1
             os: windows-2019-8core-32gb
diff --git a/Cargo.lock b/Cargo.lock
index 3290741f128..16aed3dc49c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -2266,6 +2266,17 @@ name = "lld-wrapper"
 version = "0.1.0"
 
 [[package]]
+name = "llvm-bitcode-linker"
+version = "0.0.1"
+dependencies = [
+ "anyhow",
+ "clap",
+ "thiserror",
+ "tracing",
+ "tracing-subscriber",
+]
+
+[[package]]
 name = "lock_api"
 version = "0.4.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3298,6 +3309,9 @@ dependencies = [
 [[package]]
 name = "run_make_support"
 version = "0.0.0"
+dependencies = [
+ "wasmparser",
+]
 
 [[package]]
 name = "rust-demangler"
diff --git a/Cargo.toml b/Cargo.toml
index 5847a817e76..5dd315ef2f7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -34,6 +34,7 @@ members = [
   "src/tools/expand-yaml-anchors",
   "src/tools/jsondocck",
   "src/tools/jsondoclint",
+  "src/tools/llvm-bitcode-linker",
   "src/tools/html-checker",
   "src/tools/bump-stage0",
   "src/tools/replace-version-placeholder",
diff --git a/INSTALL.md b/INSTALL.md
index d7e0fd72044..03e7a3431a5 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -145,6 +145,15 @@ toolchain.
 
 1. Download the latest [MSYS2 installer][msys2] and go through the installer.
 
+2. Download and install [Git for Windows](https://git-scm.com/download/win).
+   Make sure that it's in your Windows PATH. To enable access to it from within
+   MSYS2, edit the relevant `mingw[32|64].ini` file in your MSYS2 installation
+   directory and uncomment the line `MSYS2_PATH_TYPE=inherit`.
+
+   You could install and use MSYS2's version of git instead with `pacman`,
+   however this is not recommended as it's excrutiatingly slow, and not frequently
+   tested for compatability.
+
 2. Start a MINGW64 or MINGW32 shell (depending on whether you want 32-bit
    or 64-bit Rust) either from your start menu, or by running `mingw64.exe`
    or `mingw32.exe` from your MSYS2 installation directory (e.g. `C:\msys64`).
@@ -160,8 +169,7 @@ toolchain.
    # Note that it is important that you do **not** use the 'python2', 'cmake',
    # and 'ninja' packages from the 'msys2' subsystem.
    # The build has historically been known to fail with these packages.
-   pacman -S git \
-               make \
+   pacman -S make \
                diffutils \
                tar \
                mingw-w64-x86_64-python \
@@ -176,11 +184,9 @@ toolchain.
    python x.py setup dist && python x.py build && python x.py install
    ```
 
-If you want to use the native versions of Git, Python, or CMake you can remove
-them from the above pacman command and install them from another source. Make
-sure that they're in your Windows PATH, and edit the relevant `mingw[32|64].ini`
-file in your MSYS2 installation directory by uncommenting the line
-`MSYS2_PATH_TYPE=inherit` to include them in your MSYS2 PATH.
+If you want to try the native Windows versions of Python or CMake, you can remove
+them from the above pacman command and install them from another source. Follow
+the instructions in step 2 to get them on PATH.
 
 Using Windows native Python can be helpful if you get errors when building LLVM.
 You may also want to use Git for Windows, as it is often *much* faster. Turning
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index 76744ae6264..6fd980ed3ca 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -1,10 +1,10 @@
 use rustc_errors::{
-    codes::*, AddToDiagnostic, Diag, DiagArgFromDisplay, EmissionGuarantee, SubdiagMessageOp,
+    codes::*, Diag, DiagArgFromDisplay, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic,
 };
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::{symbol::Ident, Span, Symbol};
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[diag(ast_lowering_generic_type_with_parentheses, code = E0214)]
 pub struct GenericTypeWithParentheses {
     #[primary_span]
@@ -14,7 +14,7 @@ pub struct GenericTypeWithParentheses {
     pub sub: Option<UseAngleBrackets>,
 }
 
-#[derive(Clone, Copy, Subdiagnostic)]
+#[derive(Subdiagnostic)]
 #[multipart_suggestion(ast_lowering_use_angle_brackets, applicability = "maybe-incorrect")]
 pub struct UseAngleBrackets {
     #[suggestion_part(code = "<")]
@@ -40,8 +40,8 @@ pub struct InvalidAbi {
 
 pub struct InvalidAbiReason(pub &'static str);
 
-impl AddToDiagnostic for InvalidAbiReason {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for InvalidAbiReason {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _: F,
@@ -63,7 +63,7 @@ pub struct InvalidAbiSuggestion {
     pub suggestion: String,
 }
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[diag(ast_lowering_assoc_ty_parentheses)]
 pub struct AssocTyParentheses {
     #[primary_span]
@@ -72,7 +72,7 @@ pub struct AssocTyParentheses {
     pub sub: AssocTyParenthesesSub,
 }
 
-#[derive(Clone, Copy, Subdiagnostic)]
+#[derive(Subdiagnostic)]
 pub enum AssocTyParenthesesSub {
     #[multipart_suggestion(ast_lowering_remove_parentheses)]
     Empty {
@@ -106,7 +106,7 @@ pub struct MisplacedAssocTyBinding {
     pub suggestion: Option<Span>,
 }
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[diag(ast_lowering_underscore_expr_lhs_assign)]
 pub struct UnderscoreExprLhsAssign {
     #[primary_span]
@@ -114,7 +114,7 @@ pub struct UnderscoreExprLhsAssign {
     pub span: Span,
 }
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[diag(ast_lowering_base_expression_double_dot, code = E0797)]
 pub struct BaseExpressionDoubleDot {
     #[primary_span]
@@ -122,7 +122,7 @@ pub struct BaseExpressionDoubleDot {
     pub span: Span,
 }
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[diag(ast_lowering_await_only_in_async_fn_and_blocks, code = E0728)]
 pub struct AwaitOnlyInAsyncFnAndBlocks {
     #[primary_span]
@@ -132,21 +132,21 @@ pub struct AwaitOnlyInAsyncFnAndBlocks {
     pub item_span: Option<Span>,
 }
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[diag(ast_lowering_coroutine_too_many_parameters, code = E0628)]
 pub struct CoroutineTooManyParameters {
     #[primary_span]
     pub fn_decl_span: Span,
 }
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[diag(ast_lowering_closure_cannot_be_static, code = E0697)]
 pub struct ClosureCannotBeStatic {
     #[primary_span]
     pub fn_decl_span: Span,
 }
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[diag(ast_lowering_functional_record_update_destructuring_assignment)]
 pub struct FunctionalRecordUpdateDestructuringAssignment {
     #[primary_span]
@@ -154,28 +154,28 @@ pub struct FunctionalRecordUpdateDestructuringAssignment {
     pub span: Span,
 }
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[diag(ast_lowering_async_coroutines_not_supported, code = E0727)]
 pub struct AsyncCoroutinesNotSupported {
     #[primary_span]
     pub span: Span,
 }
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[diag(ast_lowering_inline_asm_unsupported_target, code = E0472)]
 pub struct InlineAsmUnsupportedTarget {
     #[primary_span]
     pub span: Span,
 }
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[diag(ast_lowering_att_syntax_only_x86)]
 pub struct AttSyntaxOnlyX86 {
     #[primary_span]
     pub span: Span,
 }
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[diag(ast_lowering_abi_specified_multiple_times)]
 pub struct AbiSpecifiedMultipleTimes {
     #[primary_span]
@@ -187,7 +187,7 @@ pub struct AbiSpecifiedMultipleTimes {
     pub equivalent: Option<()>,
 }
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[diag(ast_lowering_clobber_abi_not_supported)]
 pub struct ClobberAbiNotSupported {
     #[primary_span]
@@ -203,7 +203,7 @@ pub struct InvalidAbiClobberAbi {
     pub supported_abis: String,
 }
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[diag(ast_lowering_invalid_register)]
 pub struct InvalidRegister<'a> {
     #[primary_span]
@@ -212,7 +212,7 @@ pub struct InvalidRegister<'a> {
     pub error: &'a str,
 }
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[diag(ast_lowering_invalid_register_class)]
 pub struct InvalidRegisterClass<'a> {
     #[primary_span]
@@ -241,7 +241,7 @@ pub enum InvalidAsmTemplateModifierRegClassSub {
     DoesNotSupportModifier { class_name: Symbol },
 }
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[diag(ast_lowering_invalid_asm_template_modifier_const)]
 pub struct InvalidAsmTemplateModifierConst {
     #[primary_span]
@@ -251,7 +251,7 @@ pub struct InvalidAsmTemplateModifierConst {
     pub op_span: Span,
 }
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[diag(ast_lowering_invalid_asm_template_modifier_sym)]
 pub struct InvalidAsmTemplateModifierSym {
     #[primary_span]
@@ -261,7 +261,7 @@ pub struct InvalidAsmTemplateModifierSym {
     pub op_span: Span,
 }
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[diag(ast_lowering_invalid_asm_template_modifier_label)]
 pub struct InvalidAsmTemplateModifierLabel {
     #[primary_span]
@@ -271,7 +271,7 @@ pub struct InvalidAsmTemplateModifierLabel {
     pub op_span: Span,
 }
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[diag(ast_lowering_register_class_only_clobber)]
 pub struct RegisterClassOnlyClobber {
     #[primary_span]
@@ -279,7 +279,7 @@ pub struct RegisterClassOnlyClobber {
     pub reg_class_name: Symbol,
 }
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[diag(ast_lowering_register_conflict)]
 pub struct RegisterConflict<'a> {
     #[primary_span]
@@ -293,7 +293,7 @@ pub struct RegisterConflict<'a> {
     pub in_out: Option<Span>,
 }
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[help]
 #[diag(ast_lowering_sub_tuple_binding)]
 pub struct SubTupleBinding<'a> {
@@ -311,7 +311,7 @@ pub struct SubTupleBinding<'a> {
     pub ctx: &'a str,
 }
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[diag(ast_lowering_extra_double_dot)]
 pub struct ExtraDoubleDot<'a> {
     #[primary_span]
@@ -322,7 +322,7 @@ pub struct ExtraDoubleDot<'a> {
     pub ctx: &'a str,
 }
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[note]
 #[diag(ast_lowering_misplaced_double_dot)]
 pub struct MisplacedDoubleDot {
@@ -330,7 +330,7 @@ pub struct MisplacedDoubleDot {
     pub span: Span,
 }
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[diag(ast_lowering_misplaced_relax_trait_bound)]
 pub struct MisplacedRelaxTraitBound {
     #[primary_span]
@@ -363,14 +363,14 @@ pub struct NeverPatternWithGuard {
     pub span: Span,
 }
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[diag(ast_lowering_arbitrary_expression_in_pattern)]
 pub struct ArbitraryExpressionInPattern {
     #[primary_span]
     pub span: Span,
 }
 
-#[derive(Diagnostic, Clone, Copy)]
+#[derive(Diagnostic)]
 #[diag(ast_lowering_inclusive_range_with_no_end)]
 pub struct InclusiveRangeWithNoEnd {
     #[primary_span]
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index e225401ea37..9e8c1d7f5fd 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -2,7 +2,7 @@
 
 use rustc_ast::ParamKindOrd;
 use rustc_errors::{
-    codes::*, AddToDiagnostic, Applicability, Diag, EmissionGuarantee, SubdiagMessageOp,
+    codes::*, Applicability, Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic,
 };
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::{symbol::Ident, Span, Symbol};
@@ -373,8 +373,8 @@ pub struct ArgsBeforeConstraint {
 pub struct EmptyLabelManySpans(pub Vec<Span>);
 
 // The derive for `Vec<Span>` does multiple calls to `span_label`, adding commas between each
-impl AddToDiagnostic for EmptyLabelManySpans {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for EmptyLabelManySpans {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _: F,
@@ -742,8 +742,8 @@ pub struct StableFeature {
     pub since: Symbol,
 }
 
-impl AddToDiagnostic for StableFeature {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for StableFeature {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _: F,
diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs
index f489cc87bc7..0ad7bd6e17e 100644
--- a/compiler/rustc_attr/src/session_diagnostics.rs
+++ b/compiler/rustc_attr/src/session_diagnostics.rs
@@ -1,9 +1,7 @@
 use std::num::IntErrorKind;
 
 use rustc_ast as ast;
-use rustc_errors::{
-    codes::*, Applicability, Diag, DiagCtxt, EmissionGuarantee, IntoDiagnostic, Level,
-};
+use rustc_errors::{codes::*, Applicability, Diag, DiagCtxt, Diagnostic, EmissionGuarantee, Level};
 use rustc_macros::Diagnostic;
 use rustc_span::{Span, Symbol};
 
@@ -50,8 +48,8 @@ pub(crate) struct UnknownMetaItem<'a> {
 }
 
 // Manual implementation to be able to format `expected` items correctly.
-impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnknownMetaItem<'_> {
-    fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
+impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for UnknownMetaItem<'_> {
+    fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
         let expected = self.expected.iter().map(|name| format!("`{name}`")).collect::<Vec<_>>();
         Diag::new(dcx, level, fluent::attr_unknown_meta_item)
             .with_span(self.span)
@@ -203,8 +201,8 @@ pub(crate) struct UnsupportedLiteral {
     pub start_point_span: Span,
 }
 
-impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UnsupportedLiteral {
-    fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
+impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for UnsupportedLiteral {
+    fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
         let mut diag = Diag::new(
             dcx,
             level,
diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs
index a58fe2b7447..31307ef1410 100644
--- a/compiler/rustc_borrowck/src/consumers.rs
+++ b/compiler/rustc_borrowck/src/consumers.rs
@@ -106,7 +106,7 @@ pub fn get_body_with_borrowck_facts(
     options: ConsumerOptions,
 ) -> BodyWithBorrowckFacts<'_> {
     let (input_body, promoted) = tcx.mir_promoted(def);
-    let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(def)).build();
+    let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::bind(tcx, def)).build();
     let input_body: &Body<'_> = &input_body.borrow();
     let promoted: &IndexSlice<_, _> = &promoted.borrow();
     *super::do_mir_borrowck(&infcx, input_body, promoted, Some(options)).1.unwrap()
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
index f6f33e10c20..08199068020 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs
@@ -191,9 +191,9 @@ impl Display for RegionName {
     }
 }
 
-impl rustc_errors::IntoDiagnosticArg for RegionName {
-    fn into_diagnostic_arg(self) -> rustc_errors::DiagArgValue {
-        self.to_string().into_diagnostic_arg()
+impl rustc_errors::IntoDiagArg for RegionName {
+    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
+        self.to_string().into_diag_arg()
     }
 }
 
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index 8dcfe014b65..415ba095a1b 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -126,10 +126,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def: LocalDefId) -> &BorrowCheckResult<'_> {
         return tcx.arena.alloc(result);
     }
 
-    let hir_owner = tcx.local_def_id_to_hir_id(def).owner;
-
-    let infcx =
-        tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::Bind(hir_owner.def_id)).build();
+    let infcx = tcx.infer_ctxt().with_opaque_type_inference(DefiningAnchor::bind(tcx, def)).build();
     let promoted: &IndexSlice<_, _> = &promoted.borrow();
     let opt_closure_req = do_mir_borrowck(&infcx, input_body, promoted, None).0;
     debug!("mir_borrowck done");
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
index 12b02c7fcfa..8a172233037 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs
@@ -311,13 +311,13 @@ fn check_opaque_type_well_formed<'tcx>(
         parent_def_id = tcx.local_parent(parent_def_id);
     }
 
-    // FIXME(-Znext-solver): We probably should use `DefiningAnchor::Error`
+    // FIXME(-Znext-solver): We probably should use `DefiningAnchor::Bind(&[])`
     // and prepopulate this `InferCtxt` with known opaque values, rather than
     // using the `Bind` anchor here. For now it's fine.
     let infcx = tcx
         .infer_ctxt()
         .with_next_trait_solver(next_trait_solver)
-        .with_opaque_type_inference(DefiningAnchor::Bind(parent_def_id))
+        .with_opaque_type_inference(DefiningAnchor::bind(tcx, parent_def_id))
         .build();
     let ocx = ObligationCtxt::new(&infcx);
     let identity_args = GenericArgs::identity_for_item(tcx, def_id);
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index 06302ae577a..377aff8fb6c 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -1,6 +1,6 @@
 use rustc_errors::{
-    codes::*, AddToDiagnostic, Diag, DiagCtxt, EmissionGuarantee, IntoDiagnostic, Level, MultiSpan,
-    SingleLabelManySpans, SubdiagMessageOp,
+    codes::*, Diag, DiagCtxt, Diagnostic, EmissionGuarantee, Level, MultiSpan,
+    SingleLabelManySpans, SubdiagMessageOp, Subdiagnostic,
 };
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::{symbol::Ident, Span, Symbol};
@@ -425,9 +425,9 @@ pub(crate) struct EnvNotDefinedWithUserMessage {
 }
 
 // Hand-written implementation to support custom user messages.
-impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for EnvNotDefinedWithUserMessage {
+impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for EnvNotDefinedWithUserMessage {
     #[track_caller]
-    fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
+    fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
         #[expect(
             rustc::untranslatable_diagnostic,
             reason = "cannot translate user-provided messages"
@@ -589,8 +589,8 @@ pub(crate) struct FormatUnusedArg {
 
 // Allow the singular form to be a subdiagnostic of the multiple-unused
 // form of diagnostic.
-impl AddToDiagnostic for FormatUnusedArg {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for FormatUnusedArg {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         f: F,
@@ -785,8 +785,8 @@ pub(crate) struct AsmClobberNoReg {
     pub(crate) clobbers: Vec<Span>,
 }
 
-impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for AsmClobberNoReg {
-    fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
+impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AsmClobberNoReg {
+    fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
         // eager translation as `span_labels` takes `AsRef<str>`
         let lbl1 = dcx.eagerly_translate_to_string(
             crate::fluent_generated::builtin_macros_asm_clobber_abi,
diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs
index 67a0d0dabea..39988cf64e5 100644
--- a/compiler/rustc_codegen_cranelift/example/mini_core.rs
+++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs
@@ -8,6 +8,7 @@
     rustc_attrs,
     transparent_unions,
     auto_traits,
+    freeze_impls,
     thread_local
 )]
 #![no_core]
diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs
index 6535c3a367b..1abfded8b11 100644
--- a/compiler/rustc_codegen_cranelift/src/main_shim.rs
+++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs
@@ -115,14 +115,12 @@ pub(crate) fn maybe_create_entry_wrapper(
                         termination_trait,
                     )
                     .unwrap();
-                let report = Instance::resolve(
+                let report = Instance::expect_resolve(
                     tcx,
                     ParamEnv::reveal_all(),
                     report.def_id,
                     tcx.mk_args(&[GenericArg::from(main_ret_ty)]),
                 )
-                .unwrap()
-                .unwrap()
                 .polymorphize(tcx);
 
                 let report_name = tcx.symbol_name(report).name;
@@ -142,14 +140,12 @@ pub(crate) fn maybe_create_entry_wrapper(
                 }
             } else if is_main_fn {
                 let start_def_id = tcx.require_lang_item(LangItem::Start, None);
-                let start_instance = Instance::resolve(
+                let start_instance = Instance::expect_resolve(
                     tcx,
                     ParamEnv::reveal_all(),
                     start_def_id,
                     tcx.mk_args(&[main_ret_ty.into()]),
                 )
-                .unwrap()
-                .unwrap()
                 .polymorphize(tcx);
                 let start_func_id = import_function(tcx, m, start_instance);
 
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/ci.yml b/compiler/rustc_codegen_gcc/.github/workflows/ci.yml
index 308bc55ead7..839f3ba4de3 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/ci.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/ci.yml
@@ -19,8 +19,8 @@ jobs:
       fail-fast: false
       matrix:
         libgccjit_version:
-          - { gcc: "libgccjit.so", artifacts_branch: "master" }
-          - { gcc: "libgccjit_without_int128.so", artifacts_branch: "master-without-128bit-integers" }
+          - { gcc: "gcc-13.deb" }
+          - { gcc: "gcc-13-without-int128.deb" }
         commands: [
           "--mini-tests",
           "--std-tests",
@@ -32,60 +32,39 @@ jobs:
           "--extended-regex-tests",
           "--test-successful-rustc --nb-parts 2 --current-part 0",
           "--test-successful-rustc --nb-parts 2 --current-part 1",
+          "--projects",
         ]
 
     steps:
     - uses: actions/checkout@v3
 
+    # `rustup show` installs from rust-toolchain.toml
+    - name: Setup rust toolchain
+      run: rustup show
+
+    - name: Setup rust cache
+      uses: Swatinem/rust-cache@v2
+
     - name: Install packages
       # `llvm-14-tools` is needed to install the `FileCheck` binary which is used for asm tests.
       run: sudo apt-get install ninja-build ripgrep llvm-14-tools
 
+    - name: Install rustfmt
+      run: rustup component add rustfmt
+
     - name: Download artifact
-      uses: dawidd6/action-download-artifact@v2
-      with:
-          workflow: main.yml
-          name: gcc-13
-          path: gcc-13
-          repo: antoyo/gcc
-          branch: ${{ matrix.libgccjit_version.artifacts_branch }}
-          event: push
-          search_artifacts: true # Because, instead, the action only check the last job ran and that won't work since we want multiple artifacts.
+      run: curl -LO https://github.com/antoyo/gcc/releases/latest/download/${{ matrix.libgccjit_version.gcc }}
 
     - name: Setup path to libgccjit
       run: |
-          sudo dpkg --force-overwrite -i gcc-13/gcc-13.deb
-          echo /usr/lib/ > gcc_path
+          sudo dpkg --force-overwrite -i ${{ matrix.libgccjit_version.gcc }}
+          echo 'gcc-path = "/usr/lib/"' > config.toml
 
     - name: Set env
       run: |
-        echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
-        echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
         echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
-
-    - name: Cache cargo installed crates
-      uses: actions/cache@v3
-      with:
-        path: ~/.cargo/bin
-        key: cargo-installed-crates2-ubuntu-latest
-
-    - name: Cache cargo registry
-      uses: actions/cache@v3
-      with:
-        path: ~/.cargo/registry
-        key: ${{ runner.os }}-cargo-registry2-${{ hashFiles('**/Cargo.lock') }}
-
-    - name: Cache cargo index
-      uses: actions/cache@v3
-      with:
-        path: ~/.cargo/git
-        key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
-
-    - name: Cache cargo target dir
-      uses: actions/cache@v3
-      with:
-        path: target
-        key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }}
+        echo "LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV
+        echo "LD_LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV
 
     #- name: Cache rust repository
       ## We only clone the rust repository for rustc tests
@@ -99,11 +78,9 @@ jobs:
     - name: Build
       run: |
         ./y.sh prepare --only-libcore
-        # TODO: remove --features master when it is back to the default.
-        ./y.sh build --features master
-        # TODO: remove --features master when it is back to the default.
-        cargo test --features master
-        ./clean_all.sh
+        ./y.sh build
+        cargo test
+        ./y.sh clean all
 
     - name: Prepare dependencies
       run: |
@@ -111,23 +88,27 @@ jobs:
         git config --global user.name "User"
         ./y.sh prepare
 
-    # Compile is a separate step, as the actions-rs/cargo action supports error annotations
-    - name: Compile
-      uses: actions-rs/cargo@v1.0.3
-      with:
-        command: build
-        args: --release
-
     - name: Add more failing tests because the sysroot is not compiled with LTO
-      run: cat failing-non-lto-tests.txt >> failing-ui-tests.txt
+      run: cat tests/failing-non-lto-tests.txt >> tests/failing-ui-tests.txt
 
     - name: Run tests
       run: |
-        # TODO: remove --features master when it is back to the default.
-        ./test.sh --features master --release --clean --build-sysroot ${{ matrix.commands }}
+        ./y.sh test --release --clean --build-sysroot ${{ matrix.commands }}
+
+    - name: Check formatting
+      run: cargo fmt -- --check
 
   duplicates:
     runs-on: ubuntu-latest
     steps:
       - uses: actions/checkout@v3
       - run: python tools/check_intrinsics_duplicates.py
+
+  build_system:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+      - name: Test build system
+        run: |
+          cd build_system
+          cargo test
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/failures.yml b/compiler/rustc_codegen_gcc/.github/workflows/failures.yml
index ae8de79b773..2bca694e832 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/failures.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/failures.yml
@@ -21,14 +21,11 @@ jobs:
         libgccjit_version:
           - gcc: "libgccjit.so"
             artifacts_branch: "master"
-            # TODO: switch back to --no-default-features in the case of libgccjit 12 when the default is to enable
-            # master again.
-            extra: "--features master"
           - gcc: "libgccjit_without_int128.so"
             artifacts_branch: "master-without-128bit-integers"
-            extra: "--features master"
           - gcc: "libgccjit12.so"
             artifacts_branch: "gcc12"
+            extra: "--no-default-features"
             # FIXME(antoyo): we need to set GCC_EXEC_PREFIX so that the linker can find the linker plugin.
             # Not sure why it's not found otherwise.
             env_extra: "TEST_FLAGS='-Cpanic=abort -Zpanic-abort-tests' GCC_EXEC_PREFIX=/usr/lib/gcc/"
@@ -36,6 +33,13 @@ jobs:
     steps:
     - uses: actions/checkout@v3
 
+    # `rustup show` installs from rust-toolchain.toml
+    - name: Setup rust toolchain
+      run: rustup show
+
+    - name: Setup rust cache
+      uses: Swatinem/rust-cache@v2
+
     - name: Install packages
       run: sudo apt-get install ninja-build ripgrep
 
@@ -45,56 +49,27 @@ jobs:
 
     - name: Setup path to libgccjit
       if: matrix.libgccjit_version.gcc == 'libgccjit12.so'
-      run: echo /usr/lib/gcc/x86_64-linux-gnu/12 > gcc_path
+      run: |
+          echo 'gcc-path = "/usr/lib/gcc/x86_64-linux-gnu/12"' > config.toml
+          echo "LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/12" >> $GITHUB_ENV
+          echo "LD_LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/12" >> $GITHUB_ENV
 
     - name: Download artifact
       if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
-      uses: dawidd6/action-download-artifact@v2
-      with:
-          workflow: main.yml
-          name: gcc-13
-          path: gcc-13
-          repo: antoyo/gcc
-          branch: ${{ matrix.libgccjit_version.artifacts_branch }}
-          event: push
-          search_artifacts: true # Because, instead, the action only check the last job ran and that won't work since we want multiple artifacts.
+      run: curl -LO https://github.com/antoyo/gcc/releases/latest/download/gcc-13.deb
 
     - name: Setup path to libgccjit
       if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
       run: |
-          sudo dpkg --force-overwrite -i gcc-13/gcc-13.deb
-          echo /usr/lib/ > gcc_path
+          sudo dpkg --force-overwrite -i gcc-13.deb
+          echo 'gcc-path = "/usr/lib"' > config.toml
+          echo "LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV
+          echo "LD_LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV
 
     - name: Set env
       run: |
-        echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
-        echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
         echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
 
-    - name: Cache cargo installed crates
-      uses: actions/cache@v3
-      with:
-        path: ~/.cargo/bin
-        key: cargo-installed-crates2-ubuntu-latest
-
-    - name: Cache cargo registry
-      uses: actions/cache@v3
-      with:
-        path: ~/.cargo/registry
-        key: ${{ runner.os }}-cargo-registry2-${{ hashFiles('**/Cargo.lock') }}
-
-    - name: Cache cargo index
-      uses: actions/cache@v3
-      with:
-        path: ~/.cargo/git
-        key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
-
-    - name: Cache cargo target dir
-      uses: actions/cache@v3
-      with:
-        path: target
-        key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }}
-
     #- name: Cache rust repository
       #uses: actions/cache@v3
       #id: cache-rust-repository
@@ -115,18 +90,11 @@ jobs:
       if: matrix.libgccjit_version.gcc != 'libgccjit12.so'
       run: ./y.sh prepare
 
-    # Compile is a separate step, as the actions-rs/cargo action supports error annotations
-    - name: Compile
-      uses: actions-rs/cargo@v1.0.3
-      with:
-        command: build
-        args: --release
-
     - name: Add more failing tests because the sysroot is not compiled with LTO
-      run: cat failing-non-lto-tests.txt >> failing-ui-tests.txt
+      run: cat tests/failing-non-lto-tests.txt >> tests/failing-ui-tests.txt
 
     - name: Run tests
       id: tests
       run: |
-        ${{ matrix.libgccjit_version.env_extra }} ./test.sh --release --clean --build-sysroot --test-failing-rustc ${{ matrix.libgccjit_version.extra }} | tee output_log
+        ${{ matrix.libgccjit_version.env_extra }} ./y.sh test --release --clean --build-sysroot --test-failing-rustc ${{ matrix.libgccjit_version.extra }} | tee output_log
         rg --text "test result" output_log >> $GITHUB_STEP_SUMMARY
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/gcc12.yml b/compiler/rustc_codegen_gcc/.github/workflows/gcc12.yml
index a0d363cf1fb..f7bb1560492 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/gcc12.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/gcc12.yml
@@ -28,9 +28,6 @@ jobs:
           # FIXME: re-enable asm tests when GCC can emit in the right syntax.
           # "--asm-tests",
           "--test-libcore",
-          "--extended-rand-tests",
-          "--extended-regex-example-tests",
-          "--extended-regex-tests",
           "--test-successful-rustc --nb-parts 2 --current-part 0",
           "--test-successful-rustc --nb-parts 2 --current-part 1",
         ]
@@ -38,42 +35,25 @@ jobs:
     steps:
     - uses: actions/checkout@v3
 
+    # `rustup show` installs from rust-toolchain.toml
+    - name: Setup rust toolchain
+      run: rustup show
+
+    - name: Setup rust cache
+      uses: Swatinem/rust-cache@v2
+
     - name: Install packages
       # `llvm-14-tools` is needed to install the `FileCheck` binary which is used for asm tests.
       run: sudo apt-get install ninja-build ripgrep llvm-14-tools libgccjit-12-dev
 
     - name: Setup path to libgccjit
-      run: echo /usr/lib/gcc/x86_64-linux-gnu/12 > gcc_path
+      run: echo 'gcc-path = "/usr/lib/gcc/x86_64-linux-gnu/12"' > config.toml
 
     - name: Set env
       run: |
-        echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
-        echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
         echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
-
-    - name: Cache cargo installed crates
-      uses: actions/cache@v3
-      with:
-        path: ~/.cargo/bin
-        key: cargo-installed-crates2-ubuntu-latest
-
-    - name: Cache cargo registry
-      uses: actions/cache@v3
-      with:
-        path: ~/.cargo/registry
-        key: ${{ runner.os }}-cargo-registry2-${{ hashFiles('**/Cargo.lock') }}
-
-    - name: Cache cargo index
-      uses: actions/cache@v3
-      with:
-        path: ~/.cargo/git
-        key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
-
-    - name: Cache cargo target dir
-      uses: actions/cache@v3
-      with:
-        path: target
-        key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }}
+        echo "LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/12" >> $GITHUB_ENV
+        echo "LD_LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/12" >> $GITHUB_ENV
 
     #- name: Cache rust repository
       ## We only clone the rust repository for rustc tests
@@ -89,7 +69,7 @@ jobs:
         ./y.sh prepare --only-libcore --libgccjit12-patches
         ./y.sh build --no-default-features --sysroot-panic-abort
         cargo test --no-default-features
-        ./clean_all.sh
+        ./y.sh clean all
 
     - name: Prepare dependencies
       run: |
@@ -97,19 +77,12 @@ jobs:
         git config --global user.name "User"
         ./y.sh prepare --libgccjit12-patches
 
-    # Compile is a separate step, as the actions-rs/cargo action supports error annotations
-    - name: Compile
-      uses: actions-rs/cargo@v1.0.3
-      with:
-        command: build
-        args: --release
-
     - name: Add more failing tests for GCC 12
-      run: cat failing-ui-tests12.txt >> failing-ui-tests.txt
+      run: cat tests/failing-ui-tests12.txt >> tests/failing-ui-tests.txt
 
     - name: Add more failing tests because the sysroot is not compiled with LTO
-      run: cat failing-non-lto-tests.txt >> failing-ui-tests.txt
+      run: cat tests/failing-non-lto-tests.txt >> tests/failing-ui-tests.txt
 
     - name: Run tests
       run: |
-        ./test.sh --release --clean --build-sysroot ${{ matrix.commands }} --no-default-features
+        ./y.sh test --release --clean --build-sysroot ${{ matrix.commands }} --no-default-features
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml b/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml
index 4d9d7e23dc2..a8c6b614ce8 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml
@@ -36,21 +36,22 @@ jobs:
         ]
 
     steps:
+    - uses: actions/checkout@v3
+
+    # `rustup show` installs from rust-toolchain.toml
+    - name: Setup rust toolchain
+      run: rustup show
+
+    - name: Setup rust cache
+      uses: Swatinem/rust-cache@v2
+
     - name: Install packages
       run: |
         sudo apt-get update
         sudo apt-get install qemu qemu-user-static
 
-    - uses: actions/checkout@v3
-
-    - name: Download GCC artifact
-      uses: dawidd6/action-download-artifact@v2
-      with:
-          workflow: m68k.yml
-          name: gcc-m68k-13
-          repo: cross-cg-gcc-tools/cross-gcc
-          branch: master
-          event: push
+    - name: Download artifact
+      run: curl -LO https://github.com/cross-cg-gcc-tools/cross-gcc/releases/latest/download/gcc-m68k-13.deb
 
     - name: Download VM artifact
       uses: dawidd6/action-download-artifact@v2
@@ -64,37 +65,13 @@ jobs:
     - name: Setup path to libgccjit
       run: |
           sudo dpkg -i gcc-m68k-13.deb
-          echo /usr/lib/ > gcc_path
+          echo 'gcc-path = "/usr/lib/"' > config.toml
 
     - name: Set env
       run: |
-        echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
-        echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
         echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
-
-    - name: Cache cargo installed crates
-      uses: actions/cache@v3
-      with:
-        path: ~/.cargo/bin
-        key: cargo-installed-crates2-ubuntu-latest
-
-    #- name: Cache cargo registry
-      #uses: actions/cache@v3
-      #with:
-        #path: ~/.cargo/registry
-        #key: ${{ runner.os }}-cargo-registry2-${{ hashFiles('**/Cargo.lock') }}
-
-    #- name: Cache cargo index
-      #uses: actions/cache@v3
-      #with:
-        #path: ~/.cargo/git
-        #key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
-
-    - name: Cache cargo target dir
-      uses: actions/cache@v3
-      with:
-        path: target
-        key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }}
+        echo "LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV
+        echo "LD_LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV
 
     #- name: Cache rust repository
       ## We only clone the rust repository for rustc tests
@@ -114,11 +91,9 @@ jobs:
     - name: Build
       run: |
         ./y.sh prepare --only-libcore --cross
-        # TODO: remove --features master when it is back to the default.
-        ./y.sh build --target-triple m68k-unknown-linux-gnu --features master
-        # TODO: remove --features master when it is back to the default.
-        CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu cargo test --features master
-        ./clean_all.sh
+        ./y.sh build --target-triple m68k-unknown-linux-gnu
+        CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu cargo test
+        ./y.sh clean all
 
     - name: Prepare dependencies
       run: |
@@ -126,17 +101,9 @@ jobs:
         git config --global user.name "User"
         ./y.sh prepare --cross
 
-    # Compile is a separate step, as the actions-rs/cargo action supports error annotations
-    - name: Compile
-      uses: actions-rs/cargo@v1.0.3
-      with:
-        command: build
-        args: --release
-
     - name: Add more failing tests because the sysroot is not compiled with LTO
-      run: cat failing-non-lto-tests.txt >> failing-ui-tests.txt
+      run: cat tests/failing-non-lto-tests.txt >> tests/failing-ui-tests.txt
 
     - name: Run tests
       run: |
-        # TODO: remove --features master when it is back to the default.
-        ./test.sh --release --features master --clean --build-sysroot ${{ matrix.commands }}
+        ./y.sh test --release --clean --build-sysroot ${{ matrix.commands }}
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/release.yml b/compiler/rustc_codegen_gcc/.github/workflows/release.yml
index 43b90fcec93..28336998ffc 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/release.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/release.yml
@@ -26,63 +26,36 @@ jobs:
     steps:
     - uses: actions/checkout@v3
 
+    # `rustup show` installs from rust-toolchain.toml
+    - name: Setup rust toolchain
+      run: rustup show
+
+    - name: Setup rust cache
+      uses: Swatinem/rust-cache@v2
+
     - name: Install packages
       run: sudo apt-get install ninja-build ripgrep
 
     - name: Download artifact
-      uses: dawidd6/action-download-artifact@v2
-      with:
-          workflow: main.yml
-          name: gcc-13
-          path: gcc-13
-          repo: antoyo/gcc
-          branch: "master"
-          event: push
-          search_artifacts: true # Because, instead, the action only check the last job ran and that won't work since we want multiple artifacts.
+      run: curl -LO https://github.com/antoyo/gcc/releases/latest/download/gcc-13.deb
 
     - name: Setup path to libgccjit
       run: |
-          sudo dpkg --force-overwrite -i gcc-13/gcc-13.deb
-          echo /usr/lib/ > gcc_path
+          sudo dpkg --force-overwrite -i gcc-13.deb
+          echo 'gcc-path = "/usr/lib/"' > config.toml
 
     - name: Set env
       run: |
-        echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
-        echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
         echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
-
-    - name: Cache cargo installed crates
-      uses: actions/cache@v3
-      with:
-        path: ~/.cargo/bin
-        key: cargo-installed-crates2-ubuntu-latest
-
-    - name: Cache cargo registry
-      uses: actions/cache@v3
-      with:
-        path: ~/.cargo/registry
-        key: ${{ runner.os }}-cargo-registry2-${{ hashFiles('**/Cargo.lock') }}
-
-    - name: Cache cargo index
-      uses: actions/cache@v3
-      with:
-        path: ~/.cargo/git
-        key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
-
-    - name: Cache cargo target dir
-      uses: actions/cache@v3
-      with:
-        path: target
-        key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }}
+        echo "LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV
+        echo "LD_LIBRARY_PATH=/usr/lib" >> $GITHUB_ENV
 
     - name: Build
       run: |
         ./y.sh prepare --only-libcore
-        # TODO: remove --features master when it is back to the default.
-        EMBED_LTO_BITCODE=1 ./y.sh build --release --release-sysroot --features master
-        # TODO: remove --features master when it is back to the default.
-        cargo test --features master
-        ./clean_all.sh
+        EMBED_LTO_BITCODE=1 ./y.sh build --release --release-sysroot
+        cargo test
+        ./y.sh clean all
 
     - name: Prepare dependencies
       run: |
@@ -92,17 +65,9 @@ jobs:
         # FIXME(antoyo): we cannot enable LTO for stdarch tests currently because of some failing LTO tests using proc-macros.
         echo -n 'lto = "fat"' >> build_sysroot/Cargo.toml
 
-    # Compile is a separate step, as the actions-rs/cargo action supports error annotations
-    - name: Compile
-      uses: actions-rs/cargo@v1.0.3
-      with:
-        command: build
-        args: --release
-
     - name: Add more failing tests because of undefined symbol errors (FIXME)
-      run: cat failing-lto-tests.txt >> failing-ui-tests.txt
+      run: cat tests/failing-lto-tests.txt >> tests/failing-ui-tests.txt
 
     - name: Run tests
       run: |
-        # TODO: remove --features master when it is back to the default.
-        EMBED_LTO_BITCODE=1 ./test.sh --release --clean --release-sysroot --build-sysroot ${{ matrix.commands }} --features master
+        EMBED_LTO_BITCODE=1 ./y.sh test --release --clean --release-sysroot --build-sysroot ${{ matrix.commands }}
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml b/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml
index 42109ba3e02..41a9318007f 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml
@@ -26,6 +26,13 @@ jobs:
     steps:
     - uses: actions/checkout@v3
 
+    # `rustup show` installs from rust-toolchain.toml
+    - name: Setup rust toolchain
+      run: rustup show
+
+    - name: Setup rust cache
+      uses: Swatinem/rust-cache@v2
+
     - name: Install packages
       run: sudo apt-get install ninja-build ripgrep
 
@@ -34,73 +41,39 @@ jobs:
       run: |
           mkdir intel-sde
           cd intel-sde
-          dir=sde-external-9.14.0-2022-10-25-lin
+          dir=sde-external-9.33.0-2024-01-07-lin
           file=$dir.tar.xz
-          wget https://downloadmirror.intel.com/751535/$file
+          wget https://downloadmirror.intel.com/813591/$file
           tar xvf $file
           sudo mkdir /usr/share/intel-sde
           sudo cp -r $dir/* /usr/share/intel-sde
           sudo ln -s /usr/share/intel-sde/sde /usr/bin/sde
           sudo ln -s /usr/share/intel-sde/sde64 /usr/bin/sde64
 
-    - name: Download artifact
-      uses: dawidd6/action-download-artifact@v2
-      with:
-          workflow: main.yml
-          name: gcc-13
-          path: gcc-13
-          repo: antoyo/gcc
-          branch: "master"
-          event: push
-          search_artifacts: true # Because, instead, the action only check the last job ran and that won't work since we want multiple artifacts.
-
-    - name: Setup path to libgccjit
-      run: |
-          sudo dpkg --force-overwrite -i gcc-13/gcc-13.deb
-          echo /usr/lib/ > gcc_path
-
     - name: Set env
       run: |
-        echo "LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
-        echo "LD_LIBRARY_PATH=$(cat gcc_path)" >> $GITHUB_ENV
         echo "workspace="$GITHUB_WORKSPACE >> $GITHUB_ENV
-
-    - name: Cache cargo installed crates
-      uses: actions/cache@v3
-      with:
-        path: ~/.cargo/bin
-        key: cargo-installed-crates2-ubuntu-latest
-
-    - name: Cache cargo registry
-      uses: actions/cache@v3
-      with:
-        path: ~/.cargo/registry
-        key: ${{ runner.os }}-cargo-registry2-${{ hashFiles('**/Cargo.lock') }}
-
-    - name: Cache cargo index
-      uses: actions/cache@v3
-      with:
-        path: ~/.cargo/git
-        key: ${{ runner.os }}-cargo-index-${{ hashFiles('**/Cargo.lock') }}
-
-    - name: Cache cargo target dir
-      uses: actions/cache@v3
-      with:
-        path: target
-        key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('rust-toolchain') }}
+        echo 'download-gccjit = true' > config.toml
 
     - name: Build
       run: |
         ./y.sh prepare --only-libcore
-        # TODO: remove `--features master` when it is back to the default.
-        ./y.sh build --release --release-sysroot --features master
-        # TODO: remove --features master when it is back to the default.
-        cargo test --features master
+        ./y.sh build --release --release-sysroot
+
+    - name: Set env (part 2)
+      run: |
+        # Set the `LD_LIBRARY_PATH` and `LIBRARY_PATH` env variables...
+        echo "LD_LIBRARY_PATH="$(./y.sh info | grep -v Using) >> $GITHUB_ENV
+        echo "LIBRARY_PATH="$(./y.sh info | grep -v Using) >> $GITHUB_ENV
+
+    - name: Build (part 2)
+      run: |
+        cargo test
 
     - name: Clean
       if: ${{ !matrix.cargo_runner }}
       run: |
-        ./clean_all.sh
+        ./y.sh clean all
 
     - name: Prepare dependencies
       run: |
@@ -108,29 +81,20 @@ jobs:
         git config --global user.name "User"
         ./y.sh prepare
 
-    # Compile is a separate step, as the actions-rs/cargo action supports error annotations
-    - name: Compile
-      uses: actions-rs/cargo@v1.0.3
-      with:
-        command: build
-        # TODO: remove `--features master` when it is back to the default.
-        args: --release --features master
-
     - name: Run tests
       if: ${{ !matrix.cargo_runner }}
       run: |
-        # TODO: remove `--features master` when it is back to the default.
-        ./test.sh --release --clean --release-sysroot --build-sysroot --mini-tests --std-tests --test-libcore --features master
+        ./y.sh test --release --clean --release-sysroot --build-sysroot --mini-tests --std-tests --test-libcore
 
     - name: Run stdarch tests
       if: ${{ !matrix.cargo_runner }}
       run: |
         cd build_sysroot/sysroot_src/library/stdarch/
-        CHANNEL=release TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ../../../../cargo.sh test
+        CHANNEL=release TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ../../../../y.sh cargo test
 
     - name: Run stdarch tests
       if: ${{ matrix.cargo_runner }}
       run: |
         cd build_sysroot/sysroot_src/library/stdarch/
         # FIXME: these tests fail when the sysroot is compiled with LTO because of a missing symbol in proc-macro.
-        STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ../../../../cargo.sh test -- --skip rtm --skip tbm --skip sse4a
+        STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ../../../../y.sh cargo test -- --skip rtm --skip tbm --skip sse4a
diff --git a/compiler/rustc_codegen_gcc/.gitignore b/compiler/rustc_codegen_gcc/.gitignore
index b44d1aa78c2..bf975f92014 100644
--- a/compiler/rustc_codegen_gcc/.gitignore
+++ b/compiler/rustc_codegen_gcc/.gitignore
@@ -10,15 +10,11 @@ perf.data.old
 /build_sysroot/sysroot_src
 /build_sysroot/Cargo.lock
 /build_sysroot/test_target/Cargo.lock
-/rust
-/simple-raytracer
-/regex
-/rand
 gimple*
 *asm
 res
 test-backend
-gcc_path
+projects
 benchmarks
 tools/llvm-project
 tools/llvmint
@@ -26,3 +22,5 @@ tools/llvmint-2
 # The `llvm` folder is generated by the `tools/generate_intrinsics.py` script to update intrinsics.
 llvm
 build_system/target
+config.toml
+build
\ No newline at end of file
diff --git a/compiler/rustc_codegen_gcc/.ignore b/compiler/rustc_codegen_gcc/.ignore
index d8d189e5c7c..702dd9e2a23 100644
--- a/compiler/rustc_codegen_gcc/.ignore
+++ b/compiler/rustc_codegen_gcc/.ignore
@@ -8,3 +8,4 @@
 !*gimple*
 !*asm*
 !.github
+!config.toml
diff --git a/compiler/rustc_codegen_gcc/.rustfmt.toml b/compiler/rustc_codegen_gcc/.rustfmt.toml
index c7ad93bafe3..2a35f0230c6 100644
--- a/compiler/rustc_codegen_gcc/.rustfmt.toml
+++ b/compiler/rustc_codegen_gcc/.rustfmt.toml
@@ -1 +1 @@
-disable_all_formatting = true
+use_small_heuristics = "Max"
diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock
index ddfce5d59bd..ab2c7ca8a47 100644
--- a/compiler/rustc_codegen_gcc/Cargo.lock
+++ b/compiler/rustc_codegen_gcc/Cargo.lock
@@ -24,6 +24,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635"
 
 [[package]]
+name = "boml"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85fdb93f04c73bff54305fa437ffea5449c41edcaadfe882f35836206b166ac5"
+
+[[package]]
 name = "cc"
 version = "1.0.79"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -64,9 +70,9 @@ checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
 
 [[package]]
 name = "fm"
-version = "0.1.4"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68fda3cff2cce84c19e5dfa5179a4b35d2c0f18b893f108002b8a6a54984acca"
+checksum = "21bcf4db620a804cf7e9d84fbcb5d4ac83a8c43396203b2507d62ea31814dfd4"
 dependencies = [
  "regex",
 ]
@@ -74,7 +80,7 @@ dependencies = [
 [[package]]
 name = "gccjit"
 version = "1.0.0"
-source = "git+https://github.com/antoyo/gccjit.rs#6e290f25b1d1edab5ae9ace486fd2dc8c08d6421"
+source = "git+https://github.com/antoyo/gccjit.rs#9f8f67edc006d543b17529a001803ffece48349e"
 dependencies = [
  "gccjit_sys",
 ]
@@ -82,7 +88,7 @@ dependencies = [
 [[package]]
 name = "gccjit_sys"
 version = "0.0.1"
-source = "git+https://github.com/antoyo/gccjit.rs#6e290f25b1d1edab5ae9ace486fd2dc8c08d6421"
+source = "git+https://github.com/antoyo/gccjit.rs#9f8f67edc006d543b17529a001803ffece48349e"
 dependencies = [
  "libc",
 ]
@@ -104,9 +110,9 @@ checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
 
 [[package]]
 name = "lang_tester"
-version = "0.3.13"
+version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96bd995a092cac79868250589869b5a5d656b02a02bd74c8ebdc566dc7203090"
+checksum = "9af8149dbb3ed7d8e529fcb141fe033b1c26ed54cbffc6762d3a86483c485d23"
 dependencies = [
  "fm",
  "getopts",
@@ -185,6 +191,7 @@ checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
 name = "rustc_codegen_gcc"
 version = "0.1.0"
 dependencies = [
+ "boml",
  "gccjit",
  "lang_tester",
  "object",
diff --git a/compiler/rustc_codegen_gcc/Cargo.toml b/compiler/rustc_codegen_gcc/Cargo.toml
index b0b3aeecdbd..100c10ef1d7 100644
--- a/compiler/rustc_codegen_gcc/Cargo.toml
+++ b/compiler/rustc_codegen_gcc/Cargo.toml
@@ -19,6 +19,7 @@ harness = false
 
 [features]
 master = ["gccjit/master"]
+default = ["master"]
 
 [dependencies]
 gccjit = { git = "https://github.com/antoyo/gccjit.rs" }
@@ -35,8 +36,9 @@ smallvec = { version = "1.6.1", features = ["union", "may_dangle"] }
 tempfile = "3.7.1"
 
 [dev-dependencies]
-lang_tester = "0.3.9"
+lang_tester = "0.8.0"
 tempfile = "3.1.0"
+boml = "0.3.1"
 
 [profile.dev]
 # By compiling dependencies with optimizations, performing tests gets much faster.
@@ -55,3 +57,6 @@ debug = false
 [profile.release.build-override]
 opt-level = 0
 debug = false
+
+[package.metadata.rust-analyzer]
+rustc_private = true
diff --git a/compiler/rustc_codegen_gcc/Readme.md b/compiler/rustc_codegen_gcc/Readme.md
index 95fc6374c09..da6e91587fd 100644
--- a/compiler/rustc_codegen_gcc/Readme.md
+++ b/compiler/rustc_codegen_gcc/Readme.md
@@ -17,6 +17,18 @@ A secondary goal is to check if using the gcc backend will provide any run-time
 **This requires a patched libgccjit in order to work.
 You need to use my [fork of gcc](https://github.com/antoyo/gcc) which already includes these patches.**
 
+```bash
+$ cp config.example.toml config.toml
+```
+
+If don't need to test GCC patches you wrote in our GCC fork, then the default configuration should
+be all you need. You can update the `rustc_codegen_gcc` without worrying about GCC.
+
+### Building with your own GCC version
+
+If you wrote a patch for GCC and want to test it without this backend, you will need
+to do a few more things.
+
 To build it (most of these instructions come from [here](https://gcc.gnu.org/onlinedocs/jit/internals/index.html), so don't hesitate to take a look there if you encounter an issue):
 
 ```bash
@@ -49,23 +61,32 @@ $ make check-jit
 $ make check-jit RUNTESTFLAGS="-v -v -v jit.exp=jit.dg/test-asm.cc"
 ```
 
-**Put the path to your custom build of libgccjit in the file `gcc_path`.**
+**Put the path to your custom build of libgccjit in the file `config.toml`.**
+
+You now need to set the `gcc-path` value in `config.toml` with the result of this command:
 
 ```bash
-$ dirname $(readlink -f `find . -name libgccjit.so`) > gcc_path
+$ dirname $(readlink -f `find . -name libgccjit.so`)
+```
+
+and to comment the `download-gccjit` setting:
+
+```toml
+gcc-path = "[MY PATH]"
+# download-gccjit = true
 ```
 
 Then you can run commands like this:
 
 ```bash
 $ ./y.sh prepare # download and patch sysroot src and install hyperfine for benchmarking
-$ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) ./y.sh build --release
+$ ./y.sh build --release
 ```
 
 To run the tests:
 
 ```bash
-$ ./test.sh --release
+$ ./y.sh test --release
 ```
 
 ## Usage
@@ -79,10 +100,10 @@ export CG_GCCJIT_DIR=[the full path to rustc_codegen_gcc]
 ### Cargo
 
 ```bash
-$ CHANNEL="release" $CG_GCCJIT_DIR/cargo.sh run
+$ CHANNEL="release" $CG_GCCJIT_DIR/y.sh cargo run
 ```
 
-If you compiled cg_gccjit in debug mode (aka you didn't pass `--release` to `./test.sh`) you should use `CHANNEL="debug"` instead or omit `CHANNEL="release"` completely.
+If you compiled cg_gccjit in debug mode (aka you didn't pass `--release` to `./y.sh test`) you should use `CHANNEL="debug"` instead or omit `CHANNEL="release"` completely.
 
 ### LTO
 
@@ -100,7 +121,7 @@ error: failed to copy bitcode to object file: No such file or directory (os erro
 > You should prefer using the Cargo method.
 
 ```bash
-$ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) rustc +$(cat $CG_GCCJIT_DIR/rust-toolchain | grep 'channel' | cut -d '=' -f 2 | sed 's/"//g' | sed 's/ //g') -Cpanic=abort -Zcodegen-backend=$CG_GCCJIT_DIR/target/release/librustc_codegen_gcc.so --sysroot $CG_GCCJIT_DIR/build_sysroot/sysroot my_crate.rs
+$ LIBRARY_PATH="[gcc-path value]" LD_LIBRARY_PATH="[gcc-path value]" rustc +$(cat $CG_GCCJIT_DIR/rust-toolchain | grep 'channel' | cut -d '=' -f 2 | sed 's/"//g' | sed 's/ //g') -Cpanic=abort -Zcodegen-backend=$CG_GCCJIT_DIR/target/release/librustc_codegen_gcc.so --sysroot $CG_GCCJIT_DIR/build_sysroot/sysroot my_crate.rs
 ```
 
 ## Env vars
@@ -118,221 +139,19 @@ $ LIBRARY_PATH=$(cat gcc_path) LD_LIBRARY_PATH=$(cat gcc_path) rustc +$(cat $CG_
     <dd>Dump a C-like representation to /tmp/gccjit_dumps and enable debug info in order to debug this C-like representation.</dd>
 </dl>
 
-## Licensing
-
-While this crate is licensed under a dual Apache/MIT license, it links to `libgccjit` which is under the GPLv3+ and thus, the resulting toolchain (rustc + GCC codegen) will need to be released under the GPL license.
-
-However, programs compiled with `rustc_codegen_gcc` do not need to be released under a GPL license.
-
-## Debugging
-
-Sometimes, libgccjit will crash and output an error like this:
-
-```
-during RTL pass: expand
-libgccjit.so: error: in expmed_mode_index, at expmed.h:249
-0x7f0da2e61a35 expmed_mode_index
-	../../../gcc/gcc/expmed.h:249
-0x7f0da2e61aa4 expmed_op_cost_ptr
-	../../../gcc/gcc/expmed.h:271
-0x7f0da2e620dc sdiv_cost_ptr
-	../../../gcc/gcc/expmed.h:540
-0x7f0da2e62129 sdiv_cost
-	../../../gcc/gcc/expmed.h:558
-0x7f0da2e73c12 expand_divmod(int, tree_code, machine_mode, rtx_def*, rtx_def*, rtx_def*, int)
-	../../../gcc/gcc/expmed.c:4335
-0x7f0da2ea1423 expand_expr_real_2(separate_ops*, rtx_def*, machine_mode, expand_modifier)
-	../../../gcc/gcc/expr.c:9240
-0x7f0da2cd1a1e expand_gimple_stmt_1
-	../../../gcc/gcc/cfgexpand.c:3796
-0x7f0da2cd1c30 expand_gimple_stmt
-	../../../gcc/gcc/cfgexpand.c:3857
-0x7f0da2cd90a9 expand_gimple_basic_block
-	../../../gcc/gcc/cfgexpand.c:5898
-0x7f0da2cdade8 execute
-	../../../gcc/gcc/cfgexpand.c:6582
-```
-
-To see the code which causes this error, call the following function:
-
-```c
-gcc_jit_context_dump_to_file(ctxt, "/tmp/output.c", 1 /* update_locations */)
-```
-
-This will create a C-like file and add the locations into the IR pointing to this C file.
-Then, rerun the program and it will output the location in the second line:
-
-```
-libgccjit.so: /tmp/something.c:61322:0: error: in expmed_mode_index, at expmed.h:249
-```
-
-Or add a breakpoint to `add_error` in gdb and print the line number using:
-
-```
-p loc->m_line
-p loc->m_filename->m_buffer
-```
-
-To print a debug representation of a tree:
-
-```c
-debug_tree(expr);
-```
-
-(defined in print-tree.h)
-
-To print a debug reprensentation of a gimple struct:
-
-```c
-debug_gimple_stmt(gimple_struct)
-```
+## Extra documentation
 
-To get the `rustc` command to run in `gdb`, add the `--verbose` flag to `cargo build`.
+More specific documentation is available in the [`doc`](./doc) folder:
 
-To have the correct file paths in `gdb` instead of `/usr/src/debug/gcc/libstdc++-v3/libsupc++/eh_personality.cc`:
-
-Maybe by calling the following at the beginning of gdb:
-
-```
-set substitute-path /usr/src/debug/gcc /path/to/gcc-repo/gcc
-```
-
-TODO(antoyo): but that's not what I remember I was doing.
-
-### `failed to build archive` error
-
-When you get this error:
-
-```
-error: failed to build archive: failed to open object file: No such file or directory (os error 2)
-```
-
-That can be caused by the fact that you try to compile with `lto = "fat"`, but you didn't compile the sysroot with LTO.
-(Not sure if that's the reason since I cannot reproduce anymore. Maybe it happened when forgetting setting `FAT_LTO`.)
-
-### ld: cannot find crtbegin.o
-
-When compiling an executable with libgccijt, if setting the `*LIBRARY_PATH` variables to the install directory, you will get the following errors:
-
-```
-ld: cannot find crtbegin.o: No such file or directory
-ld: cannot find -lgcc: No such file or directory
-ld: cannot find -lgcc: No such file or directory
-libgccjit.so: error: error invoking gcc driver
-```
+ * [Common errors](./doc/errors.md)
+ * [Debugging GCC LTO](./doc/debugging-gcc-lto.md)
+ * [Debugging libgccjit](./doc/debugging-libgccjit.md)
+ * [Git subtree sync](./doc/subtree.md)
+ * [List of useful commands](./doc/tips.md)
+ * [Send a patch to GCC](./doc/sending-gcc-patch.md)
 
-To fix this, set the variables to `gcc-build/build/gcc`.
-
-### How to debug GCC LTO
-
-Run do the command with `-v -save-temps` and then extract the `lto1` line from the output and run that under the debugger.
-
-### How to send arguments to the GCC linker
-
-```
-CG_RUSTFLAGS="-Clink-args=-save-temps -v" ../cargo.sh build
-```
-
-### How to see the personality functions in the asm dump
-
-```
-CG_RUSTFLAGS="-Clink-arg=-save-temps -v -Clink-arg=-dA" ../cargo.sh build
-```
-
-### How to see the LLVM IR for a sysroot crate
-
-```
-cargo build -v --target x86_64-unknown-linux-gnu -Zbuild-std
-# Take the command from the output and add --emit=llvm-ir
-```
-
-### To prevent the linker from unmangling symbols
-
-Run with:
-
-```
-COLLECT_NO_DEMANGLE=1
-```
-
-### How to use a custom-build rustc
-
- * Build the stage2 compiler (`rustup toolchain link debug-current build/x86_64-unknown-linux-gnu/stage2`).
- * Clean and rebuild the codegen with `debug-current` in the file `rust-toolchain`.
-
-### How to install a forked git-subtree
-
-Using git-subtree with `rustc` requires a patched git to make it work.
-The PR that is needed is [here](https://github.com/gitgitgadget/git/pull/493).
-Use the following instructions to install it:
-
-```bash
-git clone git@github.com:tqc/git.git
-cd git
-git checkout tqc/subtree
-make
-make install
-cd contrib/subtree
-make
-cp git-subtree ~/bin
-```
-
-Then, do a sync with this command:
-
-```bash
-PATH="$HOME/bin:$PATH" ~/bin/git-subtree push -P compiler/rustc_codegen_gcc/ ../rustc_codegen_gcc/ sync_branch_name
-cd ../rustc_codegen_gcc
-git checkout master
-git pull
-git checkout sync_branch_name
-git merge master
-```
-
-To send the changes to the rust repo:
-
-```bash
-cd ../rust
-git pull origin master
-git checkout -b subtree-update_cg_gcc_YYYY-MM-DD
-PATH="$HOME/bin:$PATH" ~/bin/git-subtree pull --prefix=compiler/rustc_codegen_gcc/ https://github.com/rust-lang/rustc_codegen_gcc.git master
-git push
-```
-
-TODO: write a script that does the above.
-
-https://rust-lang.zulipchat.com/#narrow/stream/301329-t-devtools/topic/subtree.20madness/near/258877725
-
-### How to use [mem-trace](https://github.com/antoyo/mem-trace)
-
-`rustc` needs to be built without `jemalloc` so that `mem-trace` can overload `malloc` since `jemalloc` is linked statically, so a `LD_PRELOAD`-ed library won't a chance to intercept the calls to `malloc`.
-
-### How to generate GIMPLE
-
-If you need to check what gccjit is generating (GIMPLE), then take a look at how to
-generate it in [gimple.md](./doc/gimple.md).
-
-### How to build a cross-compiling libgccjit
-
-#### Building libgccjit
-
- * Follow the instructions on [this repo](https://github.com/cross-cg-gcc-tools/cross-gcc).
-
-#### Configuring rustc_codegen_gcc
-
- * Run `./y.sh prepare --cross` so that the sysroot is patched for the cross-compiling case.
- * Set the path to the cross-compiling libgccjit in `gcc_path`.
- * Make sure you have the linker for your target (for instance `m68k-unknown-linux-gnu-gcc`) in your `$PATH`. Currently, the linker name is hardcoded as being `$TARGET-gcc`. Specify the target when building the sysroot: `./y.sh build --target-triple m68k-unknown-linux-gnu`.
- * Build your project by specifying the target: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../cargo.sh build --target m68k-unknown-linux-gnu`.
-
-If the target is not yet supported by the Rust compiler, create a [target specification file](https://docs.rust-embedded.org/embedonomicon/custom-target.html) (note that the `arch` specified in this file must be supported by the rust compiler).
-Then, you can use it the following way:
-
- * Add the target specification file using `--target` as an **absolute** path to build the sysroot: `./y.sh build --target-triple m68k-unknown-linux-gnu --target $(pwd)/m68k-unknown-linux-gnu.json`
- * Build your project by specifying the target specification file: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../cargo.sh build --target path/to/m68k-unknown-linux-gnu.json`.
-
-If you get the following error:
+## Licensing
 
-```
-/usr/bin/ld: unrecognised emulation mode: m68kelf
-```
+While this crate is licensed under a dual Apache/MIT license, it links to `libgccjit` which is under the GPLv3+ and thus, the resulting toolchain (rustc + GCC codegen) will need to be released under the GPL license.
 
-Make sure you set `gcc_path` to the install directory.
+However, programs compiled with `rustc_codegen_gcc` do not need to be released under a GPL license.
diff --git a/compiler/rustc_codegen_gcc/build.rs b/compiler/rustc_codegen_gcc/build.rs
new file mode 100644
index 00000000000..b93c17793bf
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/build.rs
@@ -0,0 +1,6 @@
+// TODO: remove this file and deps/libLLVM-18-rust-1.78.0-nightly.so when
+// https://github.com/rust-lang/rust/pull/121967 is merged.
+fn main() {
+    println!("cargo:rerun-if-changed=deps/libLLVM-18-rust-1.78.0-nightly.so");
+    println!("cargo:rustc-link-search=deps");
+}
diff --git a/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh b/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh
deleted file mode 100755
index ebc7dc375b1..00000000000
--- a/compiler/rustc_codegen_gcc/build_sysroot/build_sysroot.sh
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/usr/bin/env bash
-
-# Requires the CHANNEL env var to be set to `debug` or `release.`
-
-set -e
-cd $(dirname "$0")
-
-pushd ../
-source ./config.sh
-popd
-
-# Cleanup for previous run
-#     v Clean target dir except for build scripts and incremental cache
-rm -r target/*/{debug,release}/{build,deps,examples,libsysroot*,native} 2>/dev/null || true
-rm Cargo.lock test_target/Cargo.lock 2>/dev/null || true
-rm -r sysroot/ 2>/dev/null || true
-
-# Build libs
-export RUSTFLAGS="$RUSTFLAGS -Z force-unstable-if-unmarked"
-if [[ "$1" == "--release" ]]; then
-    sysroot_channel='release'
-    RUSTFLAGS="$RUSTFLAGS -Zmir-opt-level=3" cargo build --target $TARGET_TRIPLE --release
-else
-    sysroot_channel='debug'
-    cargo build --target $TARGET_TRIPLE
-fi
-
-# Copy files to sysroot
-mkdir -p sysroot/lib/rustlib/$TARGET_TRIPLE/lib/
-cp -r target/$TARGET_TRIPLE/$sysroot_channel/deps/* sysroot/lib/rustlib/$TARGET_TRIPLE/lib/
-# Copy the source files to the sysroot (Rust for Linux needs this).
-source_dir=sysroot/lib/rustlib/src/rust
-mkdir -p $source_dir
-cp -r sysroot_src/library/ $source_dir
diff --git a/compiler/rustc_codegen_gcc/build_system/Cargo.lock b/compiler/rustc_codegen_gcc/build_system/Cargo.lock
index 86268e19160..e727561a2bf 100644
--- a/compiler/rustc_codegen_gcc/build_system/Cargo.lock
+++ b/compiler/rustc_codegen_gcc/build_system/Cargo.lock
@@ -3,5 +3,14 @@
 version = 3
 
 [[package]]
+name = "boml"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85fdb93f04c73bff54305fa437ffea5449c41edcaadfe882f35836206b166ac5"
+
+[[package]]
 name = "y"
 version = "0.1.0"
+dependencies = [
+ "boml",
+]
diff --git a/compiler/rustc_codegen_gcc/build_system/Cargo.toml b/compiler/rustc_codegen_gcc/build_system/Cargo.toml
index f36709ea036..d2600ed5a03 100644
--- a/compiler/rustc_codegen_gcc/build_system/Cargo.toml
+++ b/compiler/rustc_codegen_gcc/build_system/Cargo.toml
@@ -3,6 +3,9 @@ name = "y"
 version = "0.1.0"
 edition = "2021"
 
+[dependencies]
+boml = "0.3.1"
+
 [[bin]]
 name = "y"
 path = "src/main.rs"
diff --git a/compiler/rustc_codegen_gcc/build_system/src/build.rs b/compiler/rustc_codegen_gcc/build_system/src/build.rs
index f1c3701a946..c81b02e2183 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/build.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/build.rs
@@ -1,7 +1,5 @@
-use crate::config::{set_config, ConfigInfo};
-use crate::utils::{
-    get_gcc_path, run_command, run_command_with_output_and_env, walk_dir,
-};
+use crate::config::{Channel, ConfigInfo};
+use crate::utils::{run_command, run_command_with_output_and_env, walk_dir};
 use std::collections::HashMap;
 use std::ffi::OsStr;
 use std::fs;
@@ -9,33 +7,18 @@ use std::path::Path;
 
 #[derive(Default)]
 struct BuildArg {
-    codegen_release_channel: bool,
-    sysroot_release_channel: bool,
-    sysroot_panic_abort: bool,
     flags: Vec<String>,
-    gcc_path: String,
+    config_info: ConfigInfo,
 }
 
 impl BuildArg {
     fn new() -> Result<Option<Self>, String> {
-        let gcc_path = get_gcc_path()?;
-        let mut build_arg = Self {
-            gcc_path,
-            ..Default::default()
-        };
+        let mut build_arg = Self::default();
         // We skip binary name and the `build` command.
         let mut args = std::env::args().skip(2);
 
         while let Some(arg) = args.next() {
             match arg.as_str() {
-                "--release" => build_arg.codegen_release_channel = true,
-                "--release-sysroot" => build_arg.sysroot_release_channel = true,
-                "--no-default-features" => {
-                    build_arg.flags.push("--no-default-features".to_string());
-                }
-                "--sysroot-panic-abort" => {
-                    build_arg.sysroot_panic_abort = true;
-                },
                 "--features" => {
                     if let Some(arg) = args.next() {
                         build_arg.flags.push("--features".to_string());
@@ -50,25 +33,11 @@ impl BuildArg {
                     Self::usage();
                     return Ok(None);
                 }
-                "--target-triple" => {
-                    if args.next().is_some() {
-                        // Handled in config.rs.
-                    } else {
-                        return Err(
-                            "Expected a value after `--target-triple`, found nothing".to_string()
-                        );
-                    }
-                }
-                "--target" => {
-                    if args.next().is_some() {
-                        // Handled in config.rs.
-                    } else {
-                        return Err(
-                            "Expected a value after `--target`, found nothing".to_string()
-                        );
+                arg => {
+                    if !build_arg.config_info.parse_argument(arg, &mut args)? {
+                        return Err(format!("Unknown argument `{}`", arg));
                     }
                 }
-                arg => return Err(format!("Unknown argument `{}`", arg)),
             }
         }
         Ok(Some(build_arg))
@@ -79,29 +48,19 @@ impl BuildArg {
             r#"
 `build` command help:
 
-    --release              : Build codegen in release mode
-    --release-sysroot      : Build sysroot in release mode
-    --sysroot-panic-abort  : Build the sysroot without unwinding support.
-    --no-default-features  : Add `--no-default-features` flag
-    --features [arg]       : Add a new feature [arg]
-    --target-triple [arg]  : Set the target triple to [arg]
-    --help                 : Show this help
-"#
-        )
+    --features [arg]       : Add a new feature [arg]"#
+        );
+        ConfigInfo::show_usage();
+        println!("    --help                 : Show this help");
     }
 }
 
-fn build_sysroot(
-    env: &mut HashMap<String, String>,
-    args: &BuildArg,
-    config: &ConfigInfo,
-) -> Result<(), String> {
-    std::env::set_current_dir("build_sysroot")
-        .map_err(|error| format!("Failed to go to `build_sysroot` directory: {:?}", error))?;
+pub fn build_sysroot(env: &HashMap<String, String>, config: &ConfigInfo) -> Result<(), String> {
+    let start_dir = Path::new("build_sysroot");
     // Cleanup for previous run
     // Clean target dir except for build scripts and incremental cache
     let _ = walk_dir(
-        "target",
+        start_dir.join("target"),
         |dir: &Path| {
             for top in &["debug", "release"] {
                 let _ = fs::remove_dir_all(dir.join(top).join("build"));
@@ -138,92 +97,117 @@ fn build_sysroot(
         |_| Ok(()),
     );
 
-    let _ = fs::remove_file("Cargo.lock");
-    let _ = fs::remove_file("test_target/Cargo.lock");
-    let _ = fs::remove_dir_all("sysroot");
+    let _ = fs::remove_file(start_dir.join("Cargo.lock"));
+    let _ = fs::remove_file(start_dir.join("test_target/Cargo.lock"));
+    let _ = fs::remove_dir_all(start_dir.join("sysroot"));
 
     // Builds libs
-    let mut rustflags = env
-        .get("RUSTFLAGS")
-        .cloned()
-        .unwrap_or_default();
-    if args.sysroot_panic_abort {
+    let mut rustflags = env.get("RUSTFLAGS").cloned().unwrap_or_default();
+    if config.sysroot_panic_abort {
         rustflags.push_str(" -Cpanic=abort -Zpanic-abort-tests");
     }
-    env.insert(
-        "RUSTFLAGS".to_string(),
-        format!("{} -Zmir-opt-level=3", rustflags),
-    );
-    let channel = if args.sysroot_release_channel {
-        run_command_with_output_and_env(
-            &[
-                &"cargo",
-                &"build",
-                &"--target",
-                &config.target,
-                &"--release",
-            ],
-            None,
-            Some(&env),
-        )?;
+    rustflags.push_str(" -Z force-unstable-if-unmarked");
+    if config.no_default_features {
+        rustflags.push_str(" -Csymbol-mangling-version=v0");
+    }
+    let mut env = env.clone();
+
+    let mut args: Vec<&dyn AsRef<OsStr>> = vec![&"cargo", &"build", &"--target", &config.target];
+
+    if config.no_default_features {
+        rustflags.push_str(" -Csymbol-mangling-version=v0");
+        args.push(&"--no-default-features");
+    }
+
+    let channel = if config.sysroot_release_channel {
+        rustflags.push_str(" -Zmir-opt-level=3");
+        args.push(&"--release");
         "release"
     } else {
-        run_command_with_output_and_env(
-            &[
-                &"cargo",
-                &"build",
-                &"--target",
-                &config.target,
-            ],
-            None,
-            Some(env),
-        )?;
         "debug"
     };
 
+    env.insert("RUSTFLAGS".to_string(), rustflags);
+    run_command_with_output_and_env(&args, Some(start_dir), Some(&env))?;
+
     // Copy files to sysroot
-    let sysroot_path = format!("sysroot/lib/rustlib/{}/lib/", config.target_triple);
-    fs::create_dir_all(&sysroot_path)
-        .map_err(|error| format!("Failed to create directory `{}`: {:?}", sysroot_path, error))?;
+    let sysroot_path = start_dir.join(format!("sysroot/lib/rustlib/{}/lib/", config.target_triple));
+    fs::create_dir_all(&sysroot_path).map_err(|error| {
+        format!(
+            "Failed to create directory `{}`: {:?}",
+            sysroot_path.display(),
+            error
+        )
+    })?;
     let copier = |dir_to_copy: &Path| {
+        // FIXME: should not use shell command!
         run_command(&[&"cp", &"-r", &dir_to_copy, &sysroot_path], None).map(|_| ())
     };
     walk_dir(
-        &format!("target/{}/{}/deps", config.target_triple, channel),
+        start_dir.join(&format!("target/{}/{}/deps", config.target_triple, channel)),
         copier,
         copier,
     )?;
 
     // Copy the source files to the sysroot (Rust for Linux needs this).
-    let sysroot_src_path = "sysroot/lib/rustlib/src/rust";
-    fs::create_dir_all(&sysroot_src_path)
-        .map_err(|error| format!("Failed to create directory `{}`: {:?}", sysroot_src_path, error))?;
-    run_command(&[&"cp", &"-r", &"sysroot_src/library/", &sysroot_src_path], None)?;
+    let sysroot_src_path = start_dir.join("sysroot/lib/rustlib/src/rust");
+    fs::create_dir_all(&sysroot_src_path).map_err(|error| {
+        format!(
+            "Failed to create directory `{}`: {:?}",
+            sysroot_src_path.display(),
+            error
+        )
+    })?;
+    run_command(
+        &[
+            &"cp",
+            &"-r",
+            &start_dir.join("sysroot_src/library/"),
+            &sysroot_src_path,
+        ],
+        None,
+    )?;
 
     Ok(())
 }
 
-fn build_codegen(args: &BuildArg) -> Result<(), String> {
+fn build_codegen(args: &mut BuildArg) -> Result<(), String> {
     let mut env = HashMap::new();
 
-    env.insert("LD_LIBRARY_PATH".to_string(), args.gcc_path.clone());
-    env.insert("LIBRARY_PATH".to_string(), args.gcc_path.clone());
+    env.insert(
+        "LD_LIBRARY_PATH".to_string(),
+        args.config_info.gcc_path.clone(),
+    );
+    env.insert(
+        "LIBRARY_PATH".to_string(),
+        args.config_info.gcc_path.clone(),
+    );
+
+    if args.config_info.no_default_features {
+        env.insert(
+            "RUSTFLAGS".to_string(),
+            "-Csymbol-mangling-version=v0".to_string(),
+        );
+    }
 
     let mut command: Vec<&dyn AsRef<OsStr>> = vec![&"cargo", &"rustc"];
-    if args.codegen_release_channel {
+    if args.config_info.channel == Channel::Release {
         command.push(&"--release");
         env.insert("CHANNEL".to_string(), "release".to_string());
         env.insert("CARGO_INCREMENTAL".to_string(), "1".to_string());
     } else {
         env.insert("CHANNEL".to_string(), "debug".to_string());
     }
+    if args.config_info.no_default_features {
+        command.push(&"--no-default-features");
+    }
     let flags = args.flags.iter().map(|s| s.as_str()).collect::<Vec<_>>();
     for flag in &flags {
         command.push(flag);
     }
     run_command_with_output_and_env(&command, None, Some(&env))?;
 
-    let config = set_config(&mut env, &[], Some(&args.gcc_path))?;
+    args.config_info.setup(&mut env, false)?;
 
     // We voluntarily ignore the error.
     let _ = fs::remove_dir_all("target/out");
@@ -236,19 +220,16 @@ fn build_codegen(args: &BuildArg) -> Result<(), String> {
     })?;
 
     println!("[BUILD] sysroot");
-    build_sysroot(
-        &mut env,
-        args,
-        &config,
-    )?;
+    build_sysroot(&env, &args.config_info)?;
     Ok(())
 }
 
 pub fn run() -> Result<(), String> {
-    let args = match BuildArg::new()? {
+    let mut args = match BuildArg::new()? {
         Some(args) => args,
         None => return Ok(()),
     };
-    build_codegen(&args)?;
+    args.config_info.setup_gcc_path()?;
+    build_codegen(&mut args)?;
     Ok(())
 }
diff --git a/compiler/rustc_codegen_gcc/build_system/src/cargo.rs b/compiler/rustc_codegen_gcc/build_system/src/cargo.rs
new file mode 100644
index 00000000000..1cfcdba6b1c
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/build_system/src/cargo.rs
@@ -0,0 +1,114 @@
+use crate::config::ConfigInfo;
+use crate::utils::{
+    get_toolchain, run_command_with_output_and_env_no_err, rustc_toolchain_version_info,
+    rustc_version_info,
+};
+
+use std::collections::HashMap;
+use std::ffi::OsStr;
+use std::path::PathBuf;
+
+fn args() -> Result<Option<Vec<String>>, String> {
+    // We skip the binary and the "cargo" option.
+    if let Some("--help") = std::env::args().skip(2).next().as_deref() {
+        usage();
+        return Ok(None);
+    }
+    let args = std::env::args().skip(2).collect::<Vec<_>>();
+    if args.is_empty() {
+        return Err(
+            "Expected at least one argument for `cargo` subcommand, found none".to_string(),
+        );
+    }
+    Ok(Some(args))
+}
+
+fn usage() {
+    println!(
+        r#"
+`cargo` command help:
+
+    [args]     : Arguments to be passed to the cargo command
+    --help     : Show this help
+"#
+    )
+}
+
+pub fn run() -> Result<(), String> {
+    let args = match args()? {
+        Some(a) => a,
+        None => return Ok(()),
+    };
+
+    // We first need to go to the original location to ensure that the config setup will go as
+    // expected.
+    let current_dir = std::env::current_dir()
+        .and_then(|path| path.canonicalize())
+        .map_err(|error| format!("Failed to get current directory path: {:?}", error))?;
+    let current_exe = std::env::current_exe()
+        .and_then(|path| path.canonicalize())
+        .map_err(|error| format!("Failed to get current exe path: {:?}", error))?;
+    let mut parent_dir = current_exe
+        .components()
+        .map(|comp| comp.as_os_str())
+        .collect::<Vec<_>>();
+    // We run this script from "build_system/target/release/y", so we need to remove these elements.
+    for to_remove in &["y", "release", "target", "build_system"] {
+        if parent_dir
+            .last()
+            .map(|part| part == to_remove)
+            .unwrap_or(false)
+        {
+            parent_dir.pop();
+        } else {
+            return Err(format!(
+                "Build script not executed from `build_system/target/release/y` (in path {})",
+                current_exe.display(),
+            ));
+        }
+    }
+    let parent_dir = PathBuf::from(parent_dir.join(&OsStr::new("/")));
+    std::env::set_current_dir(&parent_dir).map_err(|error| {
+        format!(
+            "Failed to go to `{}` folder: {:?}",
+            parent_dir.display(),
+            error
+        )
+    })?;
+
+    let mut env: HashMap<String, String> = std::env::vars().collect();
+    ConfigInfo::default().setup(&mut env, false)?;
+    let toolchain = get_toolchain()?;
+
+    let toolchain_version = rustc_toolchain_version_info(&toolchain)?;
+    let default_version = rustc_version_info(None)?;
+    if toolchain_version != default_version {
+        println!(
+            "rustc_codegen_gcc is built for {} but the default rustc version is {}.",
+            toolchain_version.short, default_version.short,
+        );
+        println!("Using {}.", toolchain_version.short);
+    }
+
+    // We go back to the original folder since we now have set up everything we needed.
+    std::env::set_current_dir(&current_dir).map_err(|error| {
+        format!(
+            "Failed to go back to `{}` folder: {:?}",
+            current_dir.display(),
+            error
+        )
+    })?;
+
+    let rustflags = env.get("RUSTFLAGS").cloned().unwrap_or_default();
+    env.insert("RUSTDOCFLAGS".to_string(), rustflags);
+    let toolchain = format!("+{}", toolchain);
+    let mut command: Vec<&dyn AsRef<OsStr>> = vec![&"cargo", &toolchain];
+    for arg in &args {
+        command.push(arg);
+    }
+    if run_command_with_output_and_env_no_err(&command, None, Some(&env)).is_err() {
+        std::process::exit(1);
+    }
+
+    Ok(())
+}
diff --git a/compiler/rustc_codegen_gcc/build_system/src/clean.rs b/compiler/rustc_codegen_gcc/build_system/src/clean.rs
new file mode 100644
index 00000000000..cd8e691a0ed
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/build_system/src/clean.rs
@@ -0,0 +1,82 @@
+use crate::utils::{remove_file, run_command};
+
+use std::fs::remove_dir_all;
+use std::path::Path;
+
+#[derive(Default)]
+enum CleanArg {
+    /// `clean all`
+    All,
+    /// `clean ui-tests`
+    UiTests,
+    /// `clean --help`
+    #[default]
+    Help,
+}
+
+impl CleanArg {
+    fn new() -> Result<Self, String> {
+        // We skip the binary and the "clean" option.
+        for arg in std::env::args().skip(2) {
+            return match arg.as_str() {
+                "all" => Ok(Self::All),
+                "ui-tests" => Ok(Self::UiTests),
+                "--help" => Ok(Self::Help),
+                a => Err(format!("Unknown argument `{}`", a)),
+            };
+        }
+        Ok(Self::default())
+    }
+}
+
+fn usage() {
+    println!(
+        r#"
+`clean` command help:
+
+    all                      : Clean all data
+    ui-tests                 : Clean ui tests
+    --help                   : Show this help
+"#
+    )
+}
+
+fn clean_all() -> Result<(), String> {
+    let dirs_to_remove = [
+        "target",
+        "build_sysroot/sysroot",
+        "build_sysroot/sysroot_src",
+        "build_sysroot/target",
+    ];
+    for dir in dirs_to_remove {
+        let _ = remove_dir_all(dir);
+    }
+    let dirs_to_remove = ["regex", "rand", "simple-raytracer"];
+    for dir in dirs_to_remove {
+        let _ = remove_dir_all(Path::new(crate::BUILD_DIR).join(dir));
+    }
+
+    let files_to_remove = ["build_sysroot/Cargo.lock", "perf.data", "perf.data.old"];
+
+    for file in files_to_remove {
+        let _ = remove_file(file);
+    }
+
+    println!("Successfully ran `clean all`");
+    Ok(())
+}
+
+fn clean_ui_tests() -> Result<(), String> {
+    let path = Path::new(crate::BUILD_DIR).join("rust/build/x86_64-unknown-linux-gnu/test/ui/");
+    run_command(&[&"find", &path, &"-name", &"stamp", &"-delete"], None)?;
+    Ok(())
+}
+
+pub fn run() -> Result<(), String> {
+    match CleanArg::new()? {
+        CleanArg::All => clean_all()?,
+        CleanArg::UiTests => clean_ui_tests()?,
+        CleanArg::Help => usage(),
+    }
+    Ok(())
+}
diff --git a/compiler/rustc_codegen_gcc/build_system/src/clone_gcc.rs b/compiler/rustc_codegen_gcc/build_system/src/clone_gcc.rs
new file mode 100644
index 00000000000..aee46afaeb0
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/build_system/src/clone_gcc.rs
@@ -0,0 +1,79 @@
+use crate::config::ConfigInfo;
+use crate::utils::{git_clone, run_command_with_output};
+
+use std::path::{Path, PathBuf};
+
+fn show_usage() {
+    println!(
+        r#"
+`clone-gcc` command help:
+
+    --out-path         : Location where the GCC repository will be cloned (default: `./gcc`)"#
+    );
+    ConfigInfo::show_usage();
+    println!("    --help                 : Show this help");
+}
+
+#[derive(Default)]
+struct Args {
+    out_path: PathBuf,
+    config_info: ConfigInfo,
+}
+
+impl Args {
+    fn new() -> Result<Option<Self>, String> {
+        let mut command_args = Self::default();
+
+        let mut out_path = None;
+
+        // We skip binary name and the `clone-gcc` command.
+        let mut args = std::env::args().skip(2);
+
+        while let Some(arg) = args.next() {
+            match arg.as_str() {
+                "--out-path" => match args.next() {
+                    Some(path) if !path.is_empty() => out_path = Some(path),
+                    _ => {
+                        return Err("Expected an argument after `--out-path`, found nothing".into())
+                    }
+                },
+                "--help" => {
+                    show_usage();
+                    return Ok(None);
+                }
+                arg => {
+                    if !command_args.config_info.parse_argument(arg, &mut args)? {
+                        return Err(format!("Unknown option {}", arg));
+                    }
+                }
+            }
+        }
+        command_args.out_path = match out_path {
+            Some(p) => p.into(),
+            None => PathBuf::from("./gcc"),
+        };
+        return Ok(Some(command_args));
+    }
+}
+
+pub fn run() -> Result<(), String> {
+    let Some(args) = Args::new()? else {
+        return Ok(());
+    };
+
+    let result = git_clone("https://github.com/antoyo/gcc", Some(&args.out_path), false)?;
+    if result.ran_clone {
+        let gcc_commit = args.config_info.get_gcc_commit()?;
+        println!("Checking out GCC commit `{}`...", gcc_commit);
+        run_command_with_output(
+            &[&"git", &"checkout", &gcc_commit],
+            Some(Path::new(&result.repo_dir)),
+        )?;
+    } else {
+        println!(
+            "There is already a GCC folder in `{}`, leaving things as is...",
+            args.out_path.display()
+        );
+    }
+    Ok(())
+}
diff --git a/compiler/rustc_codegen_gcc/build_system/src/config.rs b/compiler/rustc_codegen_gcc/build_system/src/config.rs
index 64d9bd73e01..34c92a3485e 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/config.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/config.rs
@@ -1,149 +1,551 @@
-use crate::utils::{get_gcc_path, get_os_name, get_rustc_host_triple};
+use crate::utils::{
+    create_symlink, get_os_name, run_command_with_output, rustc_version_info, split_args,
+};
 use std::collections::HashMap;
 use std::env as std_env;
+use std::ffi::OsStr;
+use std::fs;
+use std::path::{Path, PathBuf};
 
+use boml::{types::TomlValue, Toml};
+
+#[derive(Default, PartialEq, Eq, Clone, Copy, Debug)]
+pub enum Channel {
+    #[default]
+    Debug,
+    Release,
+}
+
+impl Channel {
+    pub fn as_str(self) -> &'static str {
+        match self {
+            Self::Debug => "debug",
+            Self::Release => "release",
+        }
+    }
+}
+
+fn failed_config_parsing(config_file: &Path, err: &str) -> Result<ConfigFile, String> {
+    Err(format!(
+        "Failed to parse `{}`: {}",
+        config_file.display(),
+        err
+    ))
+}
+
+#[derive(Default)]
+pub struct ConfigFile {
+    gcc_path: Option<String>,
+    download_gccjit: Option<bool>,
+}
+
+impl ConfigFile {
+    pub fn new(config_file: &Path) -> Result<Self, String> {
+        let content = fs::read_to_string(config_file).map_err(|_| {
+            format!(
+                "Failed to read `{}`. Take a look at `Readme.md` to see how to set up the project",
+                config_file.display(),
+            )
+        })?;
+        let toml = Toml::parse(&content).map_err(|err| {
+            format!(
+                "Error occurred around `{}`: {:?}",
+                &content[err.start..=err.end],
+                err.kind
+            )
+        })?;
+        let mut config = Self::default();
+        for (key, value) in toml.iter() {
+            match (key, value) {
+                ("gcc-path", TomlValue::String(value)) => {
+                    config.gcc_path = Some(value.as_str().to_string())
+                }
+                ("gcc-path", _) => {
+                    return failed_config_parsing(config_file, "Expected a string for `gcc-path`")
+                }
+                ("download-gccjit", TomlValue::Boolean(value)) => {
+                    config.download_gccjit = Some(*value)
+                }
+                ("download-gccjit", _) => {
+                    return failed_config_parsing(
+                        config_file,
+                        "Expected a boolean for `download-gccjit`",
+                    )
+                }
+                _ => return failed_config_parsing(config_file, &format!("Unknown key `{}`", key)),
+            }
+        }
+        match (config.gcc_path.as_mut(), config.download_gccjit) {
+            (None, None | Some(false)) => {
+                return failed_config_parsing(
+                    config_file,
+                    "At least one of `gcc-path` or `download-gccjit` value must be set",
+                )
+            }
+            (Some(_), Some(true)) => {
+                println!(
+                    "WARNING: both `gcc-path` and `download-gccjit` arguments are used, \
+                    ignoring `gcc-path`"
+                );
+            }
+            (Some(gcc_path), _) => {
+                let path = Path::new(gcc_path);
+                *gcc_path = path
+                    .canonicalize()
+                    .map_err(|err| {
+                        format!("Failed to get absolute path of `{}`: {:?}", gcc_path, err)
+                    })?
+                    .display()
+                    .to_string();
+            }
+            _ => {}
+        }
+        Ok(config)
+    }
+}
+
+#[derive(Default, Debug)]
 pub struct ConfigInfo {
     pub target: String,
     pub target_triple: String,
+    pub host_triple: String,
     pub rustc_command: Vec<String>,
+    pub run_in_vm: bool,
+    pub cargo_target_dir: String,
+    pub dylib_ext: String,
+    pub sysroot_release_channel: bool,
+    pub channel: Channel,
+    pub sysroot_panic_abort: bool,
+    pub cg_backend_path: String,
+    pub sysroot_path: String,
+    pub gcc_path: String,
+    config_file: Option<String>,
+    // This is used in particular in rust compiler bootstrap because it doesn't run at the root
+    // of the `cg_gcc` folder, making it complicated for us to get access to local files we need
+    // like `libgccjit.version` or `config.toml`.
+    cg_gcc_path: Option<PathBuf>,
+    // Needed for the `info` command which doesn't want to actually download the lib if needed,
+    // just to set the `gcc_path` field to display it.
+    pub no_download: bool,
+    pub no_default_features: bool,
+    pub backend: Option<String>,
 }
 
-// Returns the beginning for the command line of rustc.
-pub fn set_config(
-    env: &mut HashMap<String, String>,
-    test_flags: &[String],
-    gcc_path: Option<&str>,
-) -> Result<ConfigInfo, String> {
-    env.insert("CARGO_INCREMENTAL".to_string(), "0".to_string());
-
-    let gcc_path = match gcc_path {
-        Some(path) => path.to_string(),
-        None => get_gcc_path()?,
-    };
-    env.insert("GCC_PATH".to_string(), gcc_path.clone());
-
-    let os_name = get_os_name()?;
-    let dylib_ext = match os_name.as_str() {
-        "Linux" => "so",
-        "Darwin" => "dylib",
-        os => return Err(format!("unsupported OS `{}`", os)),
-    };
-    let host_triple = get_rustc_host_triple()?;
-    let mut linker = None;
-    let mut target_triple = host_triple.clone();
-    let mut target = target_triple.clone();
-
-    // We skip binary name and the command.
-    let mut args = std::env::args().skip(2);
-
-    let mut set_target_triple = false;
-    let mut set_target = false;
-    while let Some(arg) = args.next() {
-        match arg.as_str() {
-            "--target-triple" => {
+impl ConfigInfo {
+    /// Returns `true` if the argument was taken into account.
+    pub fn parse_argument(
+        &mut self,
+        arg: &str,
+        args: &mut impl Iterator<Item = String>,
+    ) -> Result<bool, String> {
+        match arg {
+            "--target" => {
                 if let Some(arg) = args.next() {
-                    target_triple = arg;
-                    set_target_triple = true;
+                    self.target = arg;
                 } else {
+                    return Err("Expected a value after `--target`, found nothing".to_string());
+                }
+            }
+            "--target-triple" => match args.next() {
+                Some(arg) if !arg.is_empty() => self.target_triple = arg.to_string(),
+                _ => {
                     return Err(
                         "Expected a value after `--target-triple`, found nothing".to_string()
-                    );
+                    )
                 }
             },
-            "--target" => {
-                if let Some(arg) = args.next() {
-                    target = arg;
-                    set_target = true;
-                } else {
+            "--out-dir" => match args.next() {
+                Some(arg) if !arg.is_empty() => {
+                    self.cargo_target_dir = arg.to_string();
+                }
+                _ => return Err("Expected a value after `--out-dir`, found nothing".to_string()),
+            },
+            "--config-file" => match args.next() {
+                Some(arg) if !arg.is_empty() => {
+                    self.config_file = Some(arg.to_string());
+                }
+                _ => {
+                    return Err("Expected a value after `--config-file`, found nothing".to_string())
+                }
+            },
+            "--release-sysroot" => self.sysroot_release_channel = true,
+            "--release" => self.channel = Channel::Release,
+            "--sysroot-panic-abort" => self.sysroot_panic_abort = true,
+            "--cg_gcc-path" => match args.next() {
+                Some(arg) if !arg.is_empty() => {
+                    self.cg_gcc_path = Some(arg.into());
+                }
+                _ => {
+                    return Err("Expected a value after `--cg_gcc-path`, found nothing".to_string())
+                }
+            },
+            "--use-backend" => match args.next() {
+                Some(backend) if !backend.is_empty() => self.backend = Some(backend),
+                _ => {
                     return Err(
-                        "Expected a value after `--target`, found nothing".to_string()
-                    );
+                        "Expected an argument after `--use-backend`, found nothing".into()
+                    )
                 }
             },
-            _ => (),
+            "--no-default-features" => self.no_default_features = true,
+            _ => return Ok(false),
         }
+        Ok(true)
     }
 
-    if set_target_triple && !set_target {
-        target = target_triple.clone();
+    pub fn rustc_command_vec(&self) -> Vec<&dyn AsRef<OsStr>> {
+        let mut command: Vec<&dyn AsRef<OsStr>> = Vec::with_capacity(self.rustc_command.len());
+        for arg in self.rustc_command.iter() {
+            command.push(arg);
+        }
+        command
     }
 
-    if host_triple != target_triple {
-        linker = Some(format!("-Clinker={}-gcc", target_triple));
+    pub fn get_gcc_commit(&self) -> Result<String, String> {
+        let commit_hash_file = self.compute_path("libgccjit.version");
+        let content = fs::read_to_string(&commit_hash_file).map_err(|_| {
+            format!(
+                "Failed to read `{}`. Take a look at `Readme.md` to see how to set up the project",
+                commit_hash_file.display(),
+            )
+        })?;
+        let commit = content.trim();
+        // This is a very simple check to ensure this is not a path. For the rest, it'll just fail
+        // when trying to download the file so we should be fine.
+        if commit.contains('/') || commit.contains('\\') {
+            return Err(format!(
+                "{}: invalid commit hash `{}`",
+                commit_hash_file.display(),
+                commit,
+            ));
+        }
+        Ok(commit.to_string())
     }
-    let current_dir =
-        std_env::current_dir().map_err(|error| format!("`current_dir` failed: {:?}", error))?;
-    let channel = if let Some(channel) = env.get("CHANNEL") {
-        channel.as_str()
-    } else {
-        "debug"
-    };
-    let cg_backend_path = current_dir
-        .join("target")
-        .join(channel)
-        .join(&format!("librustc_codegen_gcc.{}", dylib_ext));
-    let sysroot_path = current_dir.join("build_sysroot/sysroot");
-    let mut rustflags = Vec::new();
-    if let Some(cg_rustflags) = env.get("CG_RUSTFLAGS") {
-        rustflags.push(cg_rustflags.clone());
+
+    fn download_gccjit_if_needed(&mut self) -> Result<(), String> {
+        let output_dir = Path::new(crate::BUILD_DIR).join("libgccjit");
+        let commit = self.get_gcc_commit()?;
+
+        let output_dir = output_dir.join(&commit);
+        if !output_dir.is_dir() {
+            std::fs::create_dir_all(&output_dir).map_err(|err| {
+                format!(
+                    "failed to create folder `{}`: {:?}",
+                    output_dir.display(),
+                    err,
+                )
+            })?;
+        }
+        let output_dir = output_dir.canonicalize().map_err(|err| {
+            format!(
+                "Failed to get absolute path of `{}`: {:?}",
+                output_dir.display(),
+                err
+            )
+        })?;
+
+        let libgccjit_so_name = "libgccjit.so";
+        let libgccjit_so = output_dir.join(libgccjit_so_name);
+        if !libgccjit_so.is_file() && !self.no_download {
+            // Download time!
+            let tempfile_name = format!("{}.download", libgccjit_so_name);
+            let tempfile = output_dir.join(&tempfile_name);
+            let is_in_ci = std::env::var("GITHUB_ACTIONS").is_ok();
+
+            let url = format!(
+                "https://github.com/antoyo/gcc/releases/download/master-{}/libgccjit.so",
+                commit,
+            );
+
+            println!("Downloading `{}`...", url);
+            download_gccjit(url, &output_dir, tempfile_name, !is_in_ci)?;
+
+            let libgccjit_so = output_dir.join(libgccjit_so_name);
+            // If we reach this point, it means the file was correctly downloaded, so let's
+            // rename it!
+            std::fs::rename(&tempfile, &libgccjit_so).map_err(|err| {
+                format!(
+                    "Failed to rename `{}` into `{}`: {:?}",
+                    tempfile.display(),
+                    libgccjit_so.display(),
+                    err,
+                )
+            })?;
+
+            println!("Downloaded libgccjit.so version {} successfully!", commit);
+            // We need to create a link named `libgccjit.so.0` because that's what the linker is
+            // looking for.
+            create_symlink(
+                &libgccjit_so,
+                output_dir.join(&format!("{}.0", libgccjit_so_name)),
+            )?;
+        }
+
+        self.gcc_path = output_dir.display().to_string();
+        println!("Using `{}` as path for libgccjit", self.gcc_path);
+        Ok(())
     }
-    if let Some(linker) = linker {
-        rustflags.push(linker.to_string());
+
+    pub fn compute_path<P: AsRef<Path>>(&self, other: P) -> PathBuf {
+        match self.cg_gcc_path {
+            Some(ref path) => path.join(other),
+            None => PathBuf::new().join(other),
+        }
     }
-    rustflags.extend_from_slice(&[
-        "-Csymbol-mangling-version=v0".to_string(),
-        "-Cdebuginfo=2".to_string(),
-        format!("-Zcodegen-backend={}", cg_backend_path.display()),
-        "--sysroot".to_string(),
-        sysroot_path.display().to_string(),
-    ]);
-
-    // Since we don't support ThinLTO, disable LTO completely when not trying to do LTO.
-    // TODO(antoyo): remove when we can handle ThinLTO.
-    if !env.contains_key(&"FAT_LTO".to_string()) {
-        rustflags.push("-Clto=off".to_string());
+
+    pub fn setup_gcc_path(&mut self) -> Result<(), String> {
+        let config_file = match self.config_file.as_deref() {
+            Some(config_file) => config_file.into(),
+            None => self.compute_path("config.toml"),
+        };
+        let ConfigFile {
+            gcc_path,
+            download_gccjit,
+        } = ConfigFile::new(&config_file)?;
+
+        if let Some(true) = download_gccjit {
+            self.download_gccjit_if_needed()?;
+            return Ok(());
+        }
+        self.gcc_path = match gcc_path {
+            Some(path) => path,
+            None => {
+                return Err(format!(
+                    "missing `gcc-path` value from `{}`",
+                    config_file.display(),
+                ))
+            }
+        };
+        Ok(())
     }
-    rustflags.extend_from_slice(test_flags);
-    // FIXME(antoyo): remove once the atomic shim is gone
-    if os_name == "Darwin" {
-        rustflags.extend_from_slice(&[
-            "-Clink-arg=-undefined".to_string(),
-            "-Clink-arg=dynamic_lookup".to_string(),
+
+    pub fn setup(
+        &mut self,
+        env: &mut HashMap<String, String>,
+        use_system_gcc: bool,
+    ) -> Result<(), String> {
+        env.insert("CARGO_INCREMENTAL".to_string(), "0".to_string());
+
+        if self.gcc_path.is_empty() && !use_system_gcc {
+            self.setup_gcc_path()?;
+        }
+        env.insert("GCC_PATH".to_string(), self.gcc_path.clone());
+
+        if self.cargo_target_dir.is_empty() {
+            match env.get("CARGO_TARGET_DIR").filter(|dir| !dir.is_empty()) {
+                Some(cargo_target_dir) => self.cargo_target_dir = cargo_target_dir.clone(),
+                None => self.cargo_target_dir = "target/out".to_string(),
+            }
+        }
+
+        let os_name = get_os_name()?;
+        self.dylib_ext = match os_name.as_str() {
+            "Linux" => "so",
+            "Darwin" => "dylib",
+            os => return Err(format!("unsupported OS `{}`", os)),
+        }
+        .to_string();
+        let rustc = match env.get("RUSTC") {
+            Some(r) if !r.is_empty() => r.to_string(),
+            _ => "rustc".to_string(),
+        };
+        self.host_triple = match rustc_version_info(Some(&rustc))?.host {
+            Some(host) => host,
+            None => return Err("no host found".to_string()),
+        };
+
+        if self.target_triple.is_empty() {
+            if let Some(overwrite) = env.get("OVERWRITE_TARGET_TRIPLE") {
+                self.target_triple = overwrite.clone();
+            }
+        }
+        if self.target_triple.is_empty() {
+            self.target_triple = self.host_triple.clone();
+        }
+        if self.target.is_empty() && !self.target_triple.is_empty() {
+            self.target = self.target_triple.clone();
+        }
+
+        let mut linker = None;
+
+        if self.host_triple != self.target_triple {
+            if self.target_triple.is_empty() {
+                return Err("Unknown non-native platform".to_string());
+            }
+            linker = Some(format!("-Clinker={}-gcc", self.target_triple));
+            self.run_in_vm = true;
+        }
+
+        let current_dir =
+            std_env::current_dir().map_err(|error| format!("`current_dir` failed: {:?}", error))?;
+        let channel = if self.channel == Channel::Release {
+            "release"
+        } else if let Some(channel) = env.get("CHANNEL") {
+            channel.as_str()
+        } else {
+            "debug"
+        };
+
+        let mut rustflags = Vec::new();
+        self.cg_backend_path = current_dir
+            .join("target")
+            .join(channel)
+            .join(&format!("librustc_codegen_gcc.{}", self.dylib_ext))
+            .display()
+            .to_string();
+        self.sysroot_path = current_dir
+            .join("build_sysroot/sysroot")
+            .display()
+            .to_string();
+        if let Some(backend) = &self.backend {
+            rustflags.push(format!("-Zcodegen-backend={}", backend));
+        } else {
+            rustflags.extend_from_slice(&[
+                "--sysroot".to_string(), self.sysroot_path.clone(),
+                format!("-Zcodegen-backend={}", self.cg_backend_path),
+            ]);
+        }
+
+        // This environment variable is useful in case we want to change options of rustc commands.
+        if let Some(cg_rustflags) = env.get("CG_RUSTFLAGS") {
+            rustflags.extend_from_slice(&split_args(&cg_rustflags)?);
+        }
+        if let Some(test_flags) = env.get("TEST_FLAGS") {
+            rustflags.extend_from_slice(&split_args(&test_flags)?);
+        }
+
+        if let Some(linker) = linker {
+            rustflags.push(linker.to_string());
+        }
+
+        if self.no_default_features {
+            rustflags.push("-Csymbol-mangling-version=v0".to_string());
+        }
+
+        rustflags.push("-Cdebuginfo=2".to_string());
+
+        // Since we don't support ThinLTO, disable LTO completely when not trying to do LTO.
+        // TODO(antoyo): remove when we can handle ThinLTO.
+        if !env.contains_key(&"FAT_LTO".to_string()) {
+            rustflags.push("-Clto=off".to_string());
+        }
+        // FIXME(antoyo): remove once the atomic shim is gone
+        if os_name == "Darwin" {
+            rustflags.extend_from_slice(&[
+                "-Clink-arg=-undefined".to_string(),
+                "-Clink-arg=dynamic_lookup".to_string(),
+            ]);
+        }
+        env.insert("RUSTFLAGS".to_string(), rustflags.join(" "));
+        // display metadata load errors
+        env.insert("RUSTC_LOG".to_string(), "warn".to_string());
+
+        let sysroot = current_dir.join(&format!(
+            "build_sysroot/sysroot/lib/rustlib/{}/lib",
+            self.target_triple,
+        ));
+        let ld_library_path = format!(
+            "{target}:{sysroot}:{gcc_path}",
+            target = self.cargo_target_dir,
+            sysroot = sysroot.display(),
+            gcc_path = self.gcc_path,
+        );
+        env.insert("LIBRARY_PATH".to_string(), ld_library_path.clone());
+        env.insert("LD_LIBRARY_PATH".to_string(), ld_library_path.clone());
+        env.insert("DYLD_LIBRARY_PATH".to_string(), ld_library_path);
+
+        // NOTE: To avoid the -fno-inline errors, use /opt/gcc/bin/gcc instead of cc.
+        // To do so, add a symlink for cc to /opt/gcc/bin/gcc in our PATH.
+        // Another option would be to add the following Rust flag: -Clinker=/opt/gcc/bin/gcc
+        let path = std::env::var("PATH").unwrap_or_default();
+        env.insert(
+            "PATH".to_string(),
+            format!(
+                "/opt/gcc/bin:/opt/m68k-unknown-linux-gnu/bin{}{}",
+                if path.is_empty() { "" } else { ":" },
+                path
+            ),
+        );
+
+        self.rustc_command = vec![rustc];
+        self.rustc_command.extend_from_slice(&rustflags);
+        self.rustc_command.extend_from_slice(&[
+            "-L".to_string(),
+            format!("crate={}", self.cargo_target_dir),
+            "--out-dir".to_string(),
+            self.cargo_target_dir.clone(),
         ]);
+
+        if !env.contains_key("RUSTC_LOG") {
+            env.insert("RUSTC_LOG".to_string(), "warn".to_string());
+        }
+        Ok(())
     }
-    env.insert("RUSTFLAGS".to_string(), rustflags.join(" "));
-    // display metadata load errors
-    env.insert("RUSTC_LOG".to_string(), "warn".to_string());
-
-    let sysroot = current_dir.join(&format!(
-        "build_sysroot/sysroot/lib/rustlib/{}/lib",
-        target_triple
-    ));
-    let ld_library_path = format!(
-        "{target}:{sysroot}:{gcc_path}",
-        target = current_dir.join("target/out").display(),
-        sysroot = sysroot.display(),
+
+    pub fn show_usage() {
+        println!(
+            "\
+    --target-triple [arg]  : Set the target triple to [arg]
+    --target [arg]         : Set the target to [arg]
+    --out-dir              : Location where the files will be generated
+    --release              : Build in release mode
+    --release-sysroot      : Build sysroot in release mode
+    --sysroot-panic-abort  : Build the sysroot without unwinding support
+    --config-file          : Location of the config file to be used
+    --cg_gcc-path          : Location of the rustc_codegen_gcc root folder (used
+                             when ran from another directory)
+    --no-default-features  : Add `--no-default-features` flag to cargo commands
+    --use-backend          : Useful only for rustc testsuite"
+        );
+    }
+}
+
+fn download_gccjit(
+    url: String,
+    output_dir: &Path,
+    tempfile_name: String,
+    with_progress_bar: bool,
+) -> Result<(), String> {
+    // Try curl. If that fails and we are on windows, fallback to PowerShell.
+    let mut ret = run_command_with_output(
+        &[
+            &"curl",
+            &"--speed-time",
+            &"30",
+            &"--speed-limit",
+            &"10", // timeout if speed is < 10 bytes/sec for > 30 seconds
+            &"--connect-timeout",
+            &"30", // timeout if cannot connect within 30 seconds
+            &"-o",
+            &tempfile_name,
+            &"--retry",
+            &"3",
+            &"-SRfL",
+            if with_progress_bar {
+                &"--progress-bar"
+            } else {
+                &"-s"
+            },
+            &url.as_str(),
+        ],
+        Some(&output_dir),
     );
-    env.insert("LD_LIBRARY_PATH".to_string(), ld_library_path.clone());
-    env.insert("DYLD_LIBRARY_PATH".to_string(), ld_library_path);
-
-    // NOTE: To avoid the -fno-inline errors, use /opt/gcc/bin/gcc instead of cc.
-    // To do so, add a symlink for cc to /opt/gcc/bin/gcc in our PATH.
-    // Another option would be to add the following Rust flag: -Clinker=/opt/gcc/bin/gcc
-    let path = std::env::var("PATH").unwrap_or_default();
-    env.insert("PATH".to_string(), format!("/opt/gcc/bin:{}", path));
-
-    let mut rustc_command = vec!["rustc".to_string()];
-    rustc_command.extend_from_slice(&rustflags);
-    rustc_command.extend_from_slice(&[
-        "-L".to_string(),
-        "crate=target/out".to_string(),
-        "--out-dir".to_string(),
-        "target/out".to_string(),
-    ]);
-    Ok(ConfigInfo {
-        target,
-        target_triple,
-        rustc_command,
-    })
+    if ret.is_err() && cfg!(windows) {
+        eprintln!("Fallback to PowerShell");
+        ret = run_command_with_output(
+            &[
+                &"PowerShell.exe",
+                &"/nologo",
+                &"-Command",
+                &"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12;",
+                &format!(
+                    "(New-Object System.Net.WebClient).DownloadFile('{}', '{}')",
+                    url, tempfile_name,
+                )
+                .as_str(),
+            ],
+            Some(&output_dir),
+        );
+    }
+    ret
 }
diff --git a/compiler/rustc_codegen_gcc/build_system/src/info.rs b/compiler/rustc_codegen_gcc/build_system/src/info.rs
new file mode 100644
index 00000000000..ea38791d38c
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/build_system/src/info.rs
@@ -0,0 +1,19 @@
+use crate::config::ConfigInfo;
+
+pub fn run() -> Result<(), String> {
+    let mut config = ConfigInfo::default();
+
+    // We skip binary name and the `info` command.
+    let mut args = std::env::args().skip(2);
+    while let Some(arg) = args.next() {
+        if arg == "--help" {
+            println!("Display the path where the libgccjit will be located");
+            return Ok(());
+        }
+        config.parse_argument(&arg, &mut args)?;
+    }
+    config.no_download = true;
+    config.setup_gcc_path()?;
+    println!("{}", config.gcc_path);
+    Ok(())
+}
diff --git a/compiler/rustc_codegen_gcc/build_system/src/main.rs b/compiler/rustc_codegen_gcc/build_system/src/main.rs
index bff82b6e3e5..48ffbc7a907 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/main.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/main.rs
@@ -2,12 +2,18 @@ use std::env;
 use std::process;
 
 mod build;
+mod cargo;
+mod clean;
+mod clone_gcc;
 mod config;
+mod info;
 mod prepare;
 mod rustc_info;
 mod test;
 mod utils;
 
+const BUILD_DIR: &str = "build";
+
 macro_rules! arg_error {
     ($($err:tt)*) => {{
         eprintln!($($err)*);
@@ -22,17 +28,25 @@ fn usage() {
         "\
 Available commands for build_system:
 
-    prepare  : Run prepare command
-    build    : Run build command
-    test     : Run test command
-    --help   : Show this message"
+    cargo     : Run cargo command
+    clean     : Run clean command
+    prepare   : Run prepare command
+    build     : Run build command
+    test      : Run test command
+    info      : Run info command
+    clone-gcc : Run clone-gcc command
+    --help    : Show this message"
     );
 }
 
 pub enum Command {
+    Cargo,
+    Clean,
+    CloneGcc,
     Prepare,
     Build,
     Test,
+    Info,
 }
 
 fn main() {
@@ -41,9 +55,13 @@ fn main() {
     }
 
     let command = match env::args().nth(1).as_deref() {
+        Some("cargo") => Command::Cargo,
+        Some("clean") => Command::Clean,
         Some("prepare") => Command::Prepare,
         Some("build") => Command::Build,
         Some("test") => Command::Test,
+        Some("info") => Command::Info,
+        Some("clone-gcc") => Command::CloneGcc,
         Some("--help") => {
             usage();
             process::exit(0);
@@ -57,11 +75,15 @@ fn main() {
     };
 
     if let Err(e) = match command {
+        Command::Cargo => cargo::run(),
+        Command::Clean => clean::run(),
         Command::Prepare => prepare::run(),
         Command::Build => build::run(),
         Command::Test => test::run(),
+        Command::Info => info::run(),
+        Command::CloneGcc => clone_gcc::run(),
     } {
-        eprintln!("Command failed to run: {e:?}");
+        eprintln!("Command failed to run: {e}");
         process::exit(1);
     }
 }
diff --git a/compiler/rustc_codegen_gcc/build_system/src/prepare.rs b/compiler/rustc_codegen_gcc/build_system/src/prepare.rs
index 6c7c8586834..821c793c7e5 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/prepare.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/prepare.rs
@@ -1,10 +1,16 @@
 use crate::rustc_info::get_rustc_path;
-use crate::utils::{cargo_install, git_clone, run_command, run_command_with_output, walk_dir};
+use crate::utils::{
+    cargo_install, git_clone_root_dir, remove_file, run_command, run_command_with_output, walk_dir,
+};
 
 use std::fs;
 use std::path::Path;
 
-fn prepare_libcore(sysroot_path: &Path, libgccjit12_patches: bool, cross_compile: bool) -> Result<(), String> {
+fn prepare_libcore(
+    sysroot_path: &Path,
+    libgccjit12_patches: bool,
+    cross_compile: bool,
+) -> Result<(), String> {
     let rustc_path = match get_rustc_path() {
         Some(path) => path,
         None => return Err("`rustc` path not found".to_string()),
@@ -88,10 +94,14 @@ fn prepare_libcore(sysroot_path: &Path, libgccjit12_patches: bool, cross_compile
         },
     )?;
     if cross_compile {
-        walk_dir("cross_patches", |_| Ok(()), |file_path: &Path| {
-            patches.push(file_path.to_path_buf());
-            Ok(())
-        })?;
+        walk_dir(
+            "patches/cross_patches",
+            |_| Ok(()),
+            |file_path: &Path| {
+                patches.push(file_path.to_path_buf());
+                Ok(())
+            },
+        )?;
     }
     if libgccjit12_patches {
         walk_dir(
@@ -121,6 +131,30 @@ fn prepare_libcore(sysroot_path: &Path, libgccjit12_patches: bool, cross_compile
         )?;
     }
     println!("Successfully prepared libcore for building");
+
+    Ok(())
+}
+
+// TODO: remove when we can ignore warnings in rustdoc tests.
+fn prepare_rand() -> Result<(), String> {
+    // Apply patch for the rand crate.
+    let file_path = "patches/crates/0001-Remove-deny-warnings.patch";
+    let rand_dir = Path::new("build/rand");
+    println!("[GIT] apply `{}`", file_path);
+    let path = Path::new("../..").join(file_path);
+    run_command_with_output(&[&"git", &"apply", &path], Some(rand_dir))?;
+    run_command_with_output(&[&"git", &"add", &"-A"], Some(rand_dir))?;
+    run_command_with_output(
+        &[
+            &"git",
+            &"commit",
+            &"--no-gpg-sign",
+            &"-m",
+            &format!("Patch {}", path.display()),
+        ],
+        Some(rand_dir),
+    )?;
+
     Ok(())
 }
 
@@ -129,8 +163,7 @@ fn build_raytracer(repo_dir: &Path) -> Result<(), String> {
     run_command(&[&"cargo", &"build"], Some(repo_dir))?;
     let mv_target = repo_dir.join("raytracer_cg_llvm");
     if mv_target.is_file() {
-        std::fs::remove_file(&mv_target)
-            .map_err(|e| format!("Failed to remove file `{}`: {e:?}", mv_target.display()))?;
+        remove_file(&mv_target)?;
     }
     run_command(
         &[&"mv", &"target/debug/main", &"raytracer_cg_llvm"],
@@ -143,28 +176,13 @@ fn clone_and_setup<F>(repo_url: &str, checkout_commit: &str, extra: Option<F>) -
 where
     F: Fn(&Path) -> Result<(), String>,
 {
-    let clone_result = git_clone(repo_url, None)?;
+    let clone_result = git_clone_root_dir(repo_url, &Path::new(crate::BUILD_DIR), false)?;
     if !clone_result.ran_clone {
         println!("`{}` has already been cloned", clone_result.repo_name);
     }
-    let repo_path = Path::new(&clone_result.repo_name);
+    let repo_path = Path::new(crate::BUILD_DIR).join(&clone_result.repo_name);
     run_command(&[&"git", &"checkout", &"--", &"."], Some(&repo_path))?;
     run_command(&[&"git", &"checkout", &checkout_commit], Some(&repo_path))?;
-    let filter = format!("-{}-", clone_result.repo_name);
-    walk_dir(
-        "crate_patches",
-        |_| Ok(()),
-        |file_path| {
-            let patch = file_path.as_os_str().to_str().unwrap();
-            if patch.contains(&filter) && patch.ends_with(".patch") {
-                run_command_with_output(
-                    &[&"git", &"am", &file_path.canonicalize().unwrap()],
-                    Some(&repo_path),
-                )?;
-            }
-            Ok(())
-        },
-    )?;
     if let Some(extra) = extra {
         extra(&repo_path)?;
     }
@@ -210,8 +228,7 @@ impl PrepareArg {
     --only-libcore           : Only setup libcore and don't clone other repositories
     --cross                  : Apply the patches needed to do cross-compilation
     --libgccjit12-patches    : Apply patches needed for libgccjit12
-    --help                   : Show this help
-"#
+    --help                   : Show this help"#
         )
     }
 }
@@ -230,7 +247,7 @@ pub fn run() -> Result<(), String> {
         let to_clone = &[
             (
                 "https://github.com/rust-random/rand.git",
-                "0f933f9c7176e53b2a3c7952ded484e1783f0bf1",
+                "1f4507a8e1cf8050e4ceef95eeda8f64645b6719",
                 None,
             ),
             (
@@ -248,6 +265,8 @@ pub fn run() -> Result<(), String> {
         for (repo_url, checkout_commit, cb) in to_clone {
             clone_and_setup(repo_url, checkout_commit, *cb)?;
         }
+
+        prepare_rand()?;
     }
 
     println!("Successfully ran `prepare`");
diff --git a/compiler/rustc_codegen_gcc/build_system/src/test.rs b/compiler/rustc_codegen_gcc/build_system/src/test.rs
index 4c8c63e59ab..0895dc6bff7 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/test.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/test.rs
@@ -1,15 +1,1212 @@
-use crate::utils::run_command_with_output;
+use crate::build;
+use crate::config::{Channel, ConfigInfo};
+use crate::utils::{
+    get_toolchain, git_clone, git_clone_root_dir, remove_file, run_command, run_command_with_env,
+    run_command_with_output_and_env, rustc_version_info, split_args, walk_dir,
+};
 
-fn get_args<'a>(args: &mut Vec<&'a dyn AsRef<std::ffi::OsStr>>, extra_args: &'a Vec<String>) {
-    for extra_arg in extra_args {
-        args.push(extra_arg);
+use std::collections::{BTreeSet, HashMap};
+use std::ffi::OsStr;
+use std::fs::{create_dir_all, remove_dir_all, File};
+use std::io::{BufRead, BufReader};
+use std::path::{Path, PathBuf};
+use std::str::FromStr;
+
+type Env = HashMap<String, String>;
+type Runner = fn(&Env, &TestArg) -> Result<(), String>;
+type Runners = HashMap<&'static str, (&'static str, Runner)>;
+
+fn get_runners() -> Runners {
+    let mut runners = HashMap::new();
+
+    runners.insert(
+        "--test-rustc",
+        ("Run all rustc tests", test_rustc as Runner),
+    );
+    runners.insert(
+        "--test-successful-rustc",
+        ("Run successful rustc tests", test_successful_rustc),
+    );
+    runners.insert(
+        "--test-failing-rustc",
+        ("Run failing rustc tests", test_failing_rustc),
+    );
+    runners.insert(
+        "--projects",
+        ("Run the tests of popular crates", test_projects),
+    );
+    runners.insert("--test-libcore", ("Run libcore tests", test_libcore));
+    runners.insert("--clean", ("Empty cargo target directory", clean));
+    runners.insert("--build-sysroot", ("Build sysroot", build_sysroot));
+    runners.insert("--std-tests", ("Run std tests", std_tests));
+    runners.insert("--asm-tests", ("Run asm tests", asm_tests));
+    runners.insert(
+        "--extended-tests",
+        ("Run extended sysroot tests", extended_sysroot_tests),
+    );
+    runners.insert(
+        "--extended-rand-tests",
+        ("Run extended rand tests", extended_rand_tests),
+    );
+    runners.insert(
+        "--extended-regex-example-tests",
+        (
+            "Run extended regex example tests",
+            extended_regex_example_tests,
+        ),
+    );
+    runners.insert(
+        "--extended-regex-tests",
+        ("Run extended regex tests", extended_regex_tests),
+    );
+    runners.insert("--mini-tests", ("Run mini tests", mini_tests));
+
+    runners
+}
+
+fn get_number_after_arg(
+    args: &mut impl Iterator<Item = String>,
+    option: &str,
+) -> Result<usize, String> {
+    match args.next() {
+        Some(nb) if !nb.is_empty() => match usize::from_str(&nb) {
+            Ok(nb) => Ok(nb),
+            Err(_) => Err(format!(
+                "Expected a number after `{}`, found `{}`",
+                option, nb
+            )),
+        },
+        _ => Err(format!(
+            "Expected a number after `{}`, found nothing",
+            option
+        )),
+    }
+}
+
+fn show_usage() {
+    println!(
+        r#"
+`test` command help:
+
+    --release              : Build codegen in release mode
+    --sysroot-panic-abort  : Build the sysroot without unwinding support.
+    --features [arg]       : Add a new feature [arg]
+    --use-system-gcc       : Use system installed libgccjit
+    --build-only           : Only build rustc_codegen_gcc then exits
+    --nb-parts             : Used to split rustc_tests (for CI needs)
+    --current-part         : Used with `--nb-parts`, allows you to specify which parts to test"#
+    );
+    ConfigInfo::show_usage();
+    for (option, (doc, _)) in get_runners() {
+        // FIXME: Instead of using the hard-coded `23` value, better to compute it instead.
+        let needed_spaces = 23_usize.saturating_sub(option.len());
+        let spaces: String = std::iter::repeat(' ').take(needed_spaces).collect();
+        println!("    {}{}: {}", option, spaces, doc);
+    }
+    println!("    --help                 : Show this help");
+}
+
+#[derive(Default, Debug)]
+struct TestArg {
+    build_only: bool,
+    use_system_gcc: bool,
+    runners: BTreeSet<String>,
+    flags: Vec<String>,
+    nb_parts: Option<usize>,
+    current_part: Option<usize>,
+    sysroot_panic_abort: bool,
+    config_info: ConfigInfo,
+}
+
+impl TestArg {
+    fn new() -> Result<Option<Self>, String> {
+        let mut test_arg = Self::default();
+
+        // We skip binary name and the `test` command.
+        let mut args = std::env::args().skip(2);
+        let runners = get_runners();
+
+        while let Some(arg) = args.next() {
+            match arg.as_str() {
+                "--features" => match args.next() {
+                    Some(feature) if !feature.is_empty() => {
+                        test_arg
+                            .flags
+                            .extend_from_slice(&["--features".into(), feature]);
+                    }
+                    _ => {
+                        return Err("Expected an argument after `--features`, found nothing".into())
+                    }
+                },
+                "--use-system-gcc" => {
+                    println!("Using system GCC");
+                    test_arg.use_system_gcc = true;
+                }
+                "--build-only" => test_arg.build_only = true,
+                "--nb-parts" => {
+                    test_arg.nb_parts = Some(get_number_after_arg(&mut args, "--nb-parts")?);
+                }
+                "--current-part" => {
+                    test_arg.current_part =
+                        Some(get_number_after_arg(&mut args, "--current-part")?);
+                }
+                "--sysroot-panic-abort" => {
+                    test_arg.sysroot_panic_abort = true;
+                }
+                "--help" => {
+                    show_usage();
+                    return Ok(None);
+                }
+                x if runners.contains_key(x) => {
+                    test_arg.runners.insert(x.into());
+                }
+                arg => {
+                    if !test_arg.config_info.parse_argument(arg, &mut args)? {
+                        return Err(format!("Unknown option {}", arg));
+                    }
+                }
+            }
+        }
+        match (test_arg.current_part, test_arg.nb_parts) {
+            (Some(_), Some(_)) | (None, None) => {}
+            _ => {
+                return Err(
+                    "If either `--current-part` or `--nb-parts` is specified, the other one \
+                            needs to be specified as well!"
+                        .to_string(),
+                );
+            }
+        }
+        if test_arg.config_info.no_default_features {
+            test_arg.flags.push("--no-default-features".into());
+        }
+        Ok(Some(test_arg))
+    }
+
+    pub fn is_using_gcc_master_branch(&self) -> bool {
+        !self.config_info.no_default_features
+    }
+}
+
+fn build_if_no_backend(env: &Env, args: &TestArg) -> Result<(), String> {
+    if args.config_info.backend.is_some() {
+        return Ok(());
+    }
+    let mut command: Vec<&dyn AsRef<OsStr>> = vec![&"cargo", &"rustc"];
+    let mut tmp_env;
+    let env = if args.config_info.channel == Channel::Release {
+        tmp_env = env.clone();
+        tmp_env.insert("CARGO_INCREMENTAL".to_string(), "1".to_string());
+        command.push(&"--release");
+        &tmp_env
+    } else {
+        &env
+    };
+    for flag in args.flags.iter() {
+        command.push(flag);
+    }
+    run_command_with_output_and_env(&command, None, Some(env))
+}
+
+fn clean(_env: &Env, args: &TestArg) -> Result<(), String> {
+    let _ = std::fs::remove_dir_all(&args.config_info.cargo_target_dir);
+    let path = Path::new(&args.config_info.cargo_target_dir).join("gccjit");
+    std::fs::create_dir_all(&path)
+        .map_err(|error| format!("failed to create folder `{}`: {:?}", path.display(), error))
+}
+
+fn mini_tests(env: &Env, args: &TestArg) -> Result<(), String> {
+    // FIXME: create a function "display_if_not_quiet" or something along the line.
+    println!("[BUILD] mini_core");
+    let crate_types = if args.config_info.host_triple != args.config_info.target_triple {
+        "lib"
+    } else {
+        "lib,dylib"
+    }
+    .to_string();
+    let mut command = args.config_info.rustc_command_vec();
+    command.extend_from_slice(&[
+        &"example/mini_core.rs",
+        &"--crate-name",
+        &"mini_core",
+        &"--crate-type",
+        &crate_types,
+        &"--target",
+        &args.config_info.target_triple,
+    ]);
+    run_command_with_output_and_env(&command, None, Some(&env))?;
+
+    // FIXME: create a function "display_if_not_quiet" or something along the line.
+    println!("[BUILD] example");
+    let mut command = args.config_info.rustc_command_vec();
+    command.extend_from_slice(&[
+        &"example/example.rs",
+        &"--crate-type",
+        &"lib",
+        &"--target",
+        &args.config_info.target_triple,
+    ]);
+    run_command_with_output_and_env(&command, None, Some(&env))?;
+
+    // FIXME: create a function "display_if_not_quiet" or something along the line.
+    println!("[AOT] mini_core_hello_world");
+    let mut command = args.config_info.rustc_command_vec();
+    command.extend_from_slice(&[
+        &"example/mini_core_hello_world.rs",
+        &"--crate-name",
+        &"mini_core_hello_world",
+        &"--crate-type",
+        &"bin",
+        &"-g",
+        &"--target",
+        &args.config_info.target_triple,
+    ]);
+    run_command_with_output_and_env(&command, None, Some(&env))?;
+
+    let command: &[&dyn AsRef<OsStr>] = &[
+        &Path::new(&args.config_info.cargo_target_dir).join("mini_core_hello_world"),
+        &"abc",
+        &"bcd",
+    ];
+    maybe_run_command_in_vm(&command, env, args)?;
+    Ok(())
+}
+
+fn build_sysroot(env: &Env, args: &TestArg) -> Result<(), String> {
+    // FIXME: create a function "display_if_not_quiet" or something along the line.
+    println!("[BUILD] sysroot");
+    build::build_sysroot(env, &args.config_info)?;
+    Ok(())
+}
+
+// TODO(GuillaumeGomez): when rewriting in Rust, refactor with the code in tests/lang_tests_common.rs if possible.
+fn maybe_run_command_in_vm(
+    command: &[&dyn AsRef<OsStr>],
+    env: &Env,
+    args: &TestArg,
+) -> Result<(), String> {
+    if !args.config_info.run_in_vm {
+        run_command_with_output_and_env(command, None, Some(env))?;
+        return Ok(());
+    }
+    let vm_parent_dir = match env.get("CG_GCC_VM_DIR") {
+        Some(dir) if !dir.is_empty() => PathBuf::from(dir.clone()),
+        _ => std::env::current_dir().unwrap(),
+    };
+    let vm_dir = "vm";
+    let exe_to_run = command.first().unwrap();
+    let exe = Path::new(&exe_to_run);
+    let exe_filename = exe.file_name().unwrap();
+    let vm_home_dir = vm_parent_dir.join(vm_dir).join("home");
+    let vm_exe_path = vm_home_dir.join(exe_filename);
+    let inside_vm_exe_path = Path::new("/home").join(exe_filename);
+
+    let sudo_command: &[&dyn AsRef<OsStr>] = &[&"sudo", &"cp", &exe, &vm_exe_path];
+    run_command_with_env(sudo_command, None, Some(env))?;
+
+    let mut vm_command: Vec<&dyn AsRef<OsStr>> = vec![
+        &"sudo",
+        &"chroot",
+        &vm_dir,
+        &"qemu-m68k-static",
+        &inside_vm_exe_path,
+    ];
+    vm_command.extend_from_slice(command);
+    run_command_with_output_and_env(&vm_command, Some(&vm_parent_dir), Some(env))?;
+    Ok(())
+}
+
+fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> {
+    let cargo_target_dir = Path::new(&args.config_info.cargo_target_dir);
+    // FIXME: create a function "display_if_not_quiet" or something along the line.
+    println!("[AOT] arbitrary_self_types_pointers_and_wrappers");
+    let mut command = args.config_info.rustc_command_vec();
+    command.extend_from_slice(&[
+        &"example/arbitrary_self_types_pointers_and_wrappers.rs",
+        &"--crate-name",
+        &"arbitrary_self_types_pointers_and_wrappers",
+        &"--crate-type",
+        &"bin",
+        &"--target",
+        &args.config_info.target_triple,
+    ]);
+    run_command_with_env(&command, None, Some(env))?;
+    maybe_run_command_in_vm(
+        &[&cargo_target_dir.join("arbitrary_self_types_pointers_and_wrappers")],
+        env,
+        args,
+    )?;
+
+    // FIXME: create a function "display_if_not_quiet" or something along the line.
+    println!("[AOT] alloc_system");
+    let mut command = args.config_info.rustc_command_vec();
+    command.extend_from_slice(&[
+        &"example/alloc_system.rs",
+        &"--crate-type",
+        &"lib",
+        &"--target",
+        &args.config_info.target_triple,
+    ]);
+    if args.is_using_gcc_master_branch() {
+        command.extend_from_slice(&[&"--cfg", &"feature=\"master\""]);
+    }
+    run_command_with_env(&command, None, Some(env))?;
+
+    // FIXME: doesn't work on m68k.
+    if args.config_info.host_triple == args.config_info.target_triple {
+        // FIXME: create a function "display_if_not_quiet" or something along the line.
+        println!("[AOT] alloc_example");
+        let mut command = args.config_info.rustc_command_vec();
+        command.extend_from_slice(&[
+            &"example/alloc_example.rs",
+            &"--crate-type",
+            &"bin",
+            &"--target",
+            &args.config_info.target_triple,
+        ]);
+        run_command_with_env(&command, None, Some(env))?;
+        maybe_run_command_in_vm(&[&cargo_target_dir.join("alloc_example")], env, args)?;
+    }
+
+    // FIXME: create a function "display_if_not_quiet" or something along the line.
+    println!("[AOT] dst_field_align");
+    // FIXME(antoyo): Re-add -Zmir-opt-level=2 once rust-lang/rust#67529 is fixed.
+    let mut command = args.config_info.rustc_command_vec();
+    command.extend_from_slice(&[
+        &"example/dst-field-align.rs",
+        &"--crate-name",
+        &"dst_field_align",
+        &"--crate-type",
+        &"bin",
+        &"--target",
+        &args.config_info.target_triple,
+    ]);
+    run_command_with_env(&command, None, Some(env))?;
+    maybe_run_command_in_vm(&[&cargo_target_dir.join("dst_field_align")], env, args)?;
+
+    // FIXME: create a function "display_if_not_quiet" or something along the line.
+    println!("[AOT] std_example");
+    let mut command = args.config_info.rustc_command_vec();
+    command.extend_from_slice(&[
+        &"example/std_example.rs",
+        &"--crate-type",
+        &"bin",
+        &"--target",
+        &args.config_info.target_triple,
+    ]);
+    if args.is_using_gcc_master_branch() {
+        command.extend_from_slice(&[&"--cfg", &"feature=\"master\""]);
+    }
+    run_command_with_env(&command, None, Some(env))?;
+    maybe_run_command_in_vm(
+        &[
+            &cargo_target_dir.join("std_example"),
+            &"--target",
+            &args.config_info.target_triple,
+        ],
+        env,
+        args,
+    )?;
+
+    let test_flags = if let Some(test_flags) = env.get("TEST_FLAGS") {
+        split_args(test_flags)?
+    } else {
+        Vec::new()
+    };
+    // FIXME: create a function "display_if_not_quiet" or something along the line.
+    println!("[AOT] subslice-patterns-const-eval");
+    let mut command = args.config_info.rustc_command_vec();
+    command.extend_from_slice(&[
+        &"example/subslice-patterns-const-eval.rs",
+        &"--crate-type",
+        &"bin",
+        &"--target",
+        &args.config_info.target_triple,
+    ]);
+    for test_flag in &test_flags {
+        command.push(test_flag);
+    }
+    run_command_with_env(&command, None, Some(env))?;
+    maybe_run_command_in_vm(
+        &[&cargo_target_dir.join("subslice-patterns-const-eval")],
+        env,
+        args,
+    )?;
+
+    // FIXME: create a function "display_if_not_quiet" or something along the line.
+    println!("[AOT] track-caller-attribute");
+    let mut command = args.config_info.rustc_command_vec();
+    command.extend_from_slice(&[
+        &"example/track-caller-attribute.rs",
+        &"--crate-type",
+        &"bin",
+        &"--target",
+        &args.config_info.target_triple,
+    ]);
+    for test_flag in &test_flags {
+        command.push(test_flag);
+    }
+    run_command_with_env(&command, None, Some(env))?;
+    maybe_run_command_in_vm(
+        &[&cargo_target_dir.join("track-caller-attribute")],
+        env,
+        args,
+    )?;
+
+    // FIXME: create a function "display_if_not_quiet" or something along the line.
+    println!("[AOT] mod_bench");
+    let mut command = args.config_info.rustc_command_vec();
+    command.extend_from_slice(&[
+        &"example/mod_bench.rs",
+        &"--crate-type",
+        &"bin",
+        &"--target",
+        &args.config_info.target_triple,
+    ]);
+    run_command_with_env(&command, None, Some(env))?;
+    // FIXME: the compiled binary is not run.
+
+    Ok(())
+}
+
+fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<PathBuf, String> {
+    let toolchain = format!(
+        "+{channel}-{host}",
+        channel = get_toolchain()?, // May also include date
+        host = args.config_info.host_triple
+    );
+    let rust_dir_path = Path::new(crate::BUILD_DIR).join("rust");
+    // If the repository was already cloned, command will fail, so doesn't matter.
+    let _ = git_clone(
+        "https://github.com/rust-lang/rust.git",
+        Some(&rust_dir_path),
+        false,
+    );
+    let rust_dir: Option<&Path> = Some(&rust_dir_path);
+    run_command(&[&"git", &"checkout", &"--", &"tests/"], rust_dir)?;
+    run_command_with_output_and_env(&[&"git", &"fetch"], rust_dir, Some(env))?;
+    let rustc_commit = match rustc_version_info(env.get("RUSTC").map(|s| s.as_str()))?.commit_hash {
+        Some(commit_hash) => commit_hash,
+        None => return Err("Couldn't retrieve rustc commit hash".to_string()),
+    };
+    if rustc_commit != "unknown" {
+        run_command_with_output_and_env(
+            &[&"git", &"checkout", &rustc_commit],
+            rust_dir,
+            Some(env),
+        )?;
+    } else {
+        run_command_with_output_and_env(&[&"git", &"checkout"], rust_dir, Some(env))?;
+    }
+    let cargo = String::from_utf8(
+        run_command_with_env(&[&"rustup", &"which", &"cargo"], rust_dir, Some(env))?.stdout,
+    )
+    .map_err(|error| format!("Failed to retrieve cargo path: {:?}", error))
+    .and_then(|cargo| {
+        let cargo = cargo.trim().to_owned();
+        if cargo.is_empty() {
+            Err(format!("`cargo` path is empty"))
+        } else {
+            Ok(cargo)
+        }
+    })?;
+    let rustc = String::from_utf8(
+        run_command_with_env(
+            &[&"rustup", &toolchain, &"which", &"rustc"],
+            rust_dir,
+            Some(env),
+        )?
+        .stdout,
+    )
+    .map_err(|error| format!("Failed to retrieve rustc path: {:?}", error))
+    .and_then(|rustc| {
+        let rustc = rustc.trim().to_owned();
+        if rustc.is_empty() {
+            Err(format!("`rustc` path is empty"))
+        } else {
+            Ok(rustc)
+        }
+    })?;
+    let llvm_filecheck = match run_command_with_env(
+        &[
+            &"bash",
+            &"-c",
+            &"which FileCheck-10 || \
+          which FileCheck-11 || \
+          which FileCheck-12 || \
+          which FileCheck-13 || \
+          which FileCheck-14",
+        ],
+        rust_dir,
+        Some(env),
+    ) {
+        Ok(cmd) => String::from_utf8_lossy(&cmd.stdout).to_string(),
+        Err(_) => {
+            eprintln!("Failed to retrieve LLVM FileCheck, ignoring...");
+            String::new()
+        }
+    };
+    let file_path = rust_dir_path.join("config.toml");
+    std::fs::write(
+        &file_path,
+        &format!(
+            r#"change-id = 115898
+
+[rust]
+codegen-backends = []
+deny-warnings = false
+verbose-tests = true
+
+[build]
+cargo = "{cargo}"
+local-rebuild = true
+rustc = "{rustc}"
+
+[target.x86_64-unknown-linux-gnu]
+llvm-filecheck = "{llvm_filecheck}"
+
+[llvm]
+download-ci-llvm = false
+"#,
+            cargo = cargo,
+            rustc = rustc,
+            llvm_filecheck = llvm_filecheck.trim(),
+        ),
+    )
+    .map_err(|error| {
+        format!(
+            "Failed to write into `{}`: {:?}",
+            file_path.display(),
+            error
+        )
+    })?;
+    Ok(rust_dir_path)
+}
+
+fn asm_tests(env: &Env, args: &TestArg) -> Result<(), String> {
+    let mut env = env.clone();
+    let rust_dir = setup_rustc(&mut env, args)?;
+    // FIXME: create a function "display_if_not_quiet" or something along the line.
+    println!("[TEST] rustc asm test suite");
+
+    env.insert("COMPILETEST_FORCE_STAGE0".to_string(), "1".to_string());
+
+    let extra = if args.is_using_gcc_master_branch() {
+        ""
+    } else {
+        " -Csymbol-mangling-version=v0"
+    };
+
+    let rustc_args = &format!(
+        r#"-Zpanic-abort-tests \
+            -Zcodegen-backend="{pwd}/target/{channel}/librustc_codegen_gcc.{dylib_ext}" \
+            --sysroot "{pwd}/build_sysroot/sysroot" -Cpanic=abort{extra}"#,
+        pwd = std::env::current_dir()
+            .map_err(|error| format!("`current_dir` failed: {:?}", error))?
+            .display(),
+        channel = args.config_info.channel.as_str(),
+        dylib_ext = args.config_info.dylib_ext,
+        extra = extra,
+    );
+
+    run_command_with_env(
+        &[
+            &"./x.py",
+            &"test",
+            &"--run",
+            &"always",
+            &"--stage",
+            &"0",
+            &"tests/assembly/asm",
+            &"--rustc-args",
+            &rustc_args,
+        ],
+        Some(&rust_dir),
+        Some(&env),
+    )?;
+    Ok(())
+}
+
+fn run_cargo_command(
+    command: &[&dyn AsRef<OsStr>],
+    cwd: Option<&Path>,
+    env: &Env,
+    args: &TestArg,
+) -> Result<(), String> {
+    run_cargo_command_with_callback(command, cwd, env, args, |cargo_command, cwd, env| {
+        run_command_with_output_and_env(cargo_command, cwd, Some(env))?;
+        Ok(())
+    })
+}
+
+fn run_cargo_command_with_callback<F>(
+    command: &[&dyn AsRef<OsStr>],
+    cwd: Option<&Path>,
+    env: &Env,
+    args: &TestArg,
+    callback: F,
+) -> Result<(), String>
+where
+    F: Fn(&[&dyn AsRef<OsStr>], Option<&Path>, &Env) -> Result<(), String>,
+{
+    let toolchain = get_toolchain()?;
+    let toolchain_arg = format!("+{}", toolchain);
+    let rustc_version = String::from_utf8(
+        run_command_with_env(&[&args.config_info.rustc_command[0], &"-V"], cwd, Some(env))?.stdout,
+    )
+    .map_err(|error| format!("Failed to retrieve rustc version: {:?}", error))?;
+    let rustc_toolchain_version = String::from_utf8(
+        run_command_with_env(
+            &[&args.config_info.rustc_command[0], &toolchain_arg, &"-V"],
+            cwd,
+            Some(env),
+        )?
+        .stdout,
+    )
+    .map_err(|error| format!("Failed to retrieve rustc +toolchain version: {:?}", error))?;
+
+    if rustc_version != rustc_toolchain_version {
+        eprintln!(
+            "rustc_codegen_gcc is built for `{}` but the default rustc version is `{}`.",
+            rustc_toolchain_version, rustc_version,
+        );
+        eprintln!("Using `{}`.", rustc_toolchain_version);
+    }
+    let mut env = env.clone();
+    let rustflags = env.get("RUSTFLAGS").cloned().unwrap_or_default();
+    env.insert("RUSTDOCFLAGS".to_string(), rustflags);
+    let mut cargo_command: Vec<&dyn AsRef<OsStr>> = vec![&"cargo", &toolchain_arg];
+    cargo_command.extend_from_slice(&command);
+    callback(&cargo_command, cwd, &env)
+}
+
+// FIXME(antoyo): linker gives multiple definitions error on Linux
+// echo "[BUILD] sysroot in release mode"
+// ./build_sysroot/build_sysroot.sh --release
+
+fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> {
+    let projects = [
+        //"https://gitlab.gnome.org/GNOME/librsvg", // FIXME: doesn't compile in the CI since the
+        // version of cairo and other libraries is too old.
+        "https://github.com/rust-random/getrandom",
+        "https://github.com/BurntSushi/memchr",
+        "https://github.com/dtolnay/itoa",
+        "https://github.com/rust-lang/cfg-if",
+        "https://github.com/rust-lang-nursery/lazy-static.rs",
+        //"https://github.com/marshallpierce/rust-base64", // FIXME: one test is OOM-killed.
+        // TODO: ignore the base64 test that is OOM-killed.
+        "https://github.com/time-rs/time",
+        "https://github.com/rust-lang/log",
+        "https://github.com/bitflags/bitflags",
+        //"https://github.com/serde-rs/serde", // FIXME: one test fails.
+        //"https://github.com/rayon-rs/rayon", // TODO: very slow, only run on master?
+        //"https://github.com/rust-lang/cargo", // TODO: very slow, only run on master?
+    ];
+
+    let run_tests = |projects_path, iter: &mut dyn Iterator<Item = &&str>| -> Result<(), String> {
+        for project in iter {
+            let clone_result = git_clone_root_dir(project, projects_path, true)?;
+            let repo_path = Path::new(&clone_result.repo_dir);
+            run_cargo_command(&[&"build", &"--release"], Some(repo_path), env, args)?;
+            run_cargo_command(&[&"test"], Some(repo_path), env, args)?;
+        }
+
+        Ok(())
+    };
+
+    let projects_path = Path::new("projects");
+    create_dir_all(projects_path)
+        .map_err(|err| format!("Failed to create directory `projects`: {}", err))?;
+
+    let nb_parts = args.nb_parts.unwrap_or(0);
+    if nb_parts > 0 {
+        // We increment the number of tests by one because if this is an odd number, we would skip
+        // one test.
+        let count = projects.len() / nb_parts + 1;
+        let current_part = args.current_part.unwrap();
+        let start = current_part * count;
+        // We remove the projects we don't want to test.
+        run_tests(projects_path, &mut projects.iter().skip(start).take(count))?;
+    } else {
+        run_tests(projects_path, &mut projects.iter())?;
     }
+
+    Ok(())
+}
+
+fn test_libcore(env: &Env, args: &TestArg) -> Result<(), String> {
+    // FIXME: create a function "display_if_not_quiet" or something along the line.
+    println!("[TEST] libcore");
+    let path = Path::new("build_sysroot/sysroot_src/library/core/tests");
+    let _ = remove_dir_all(path.join("target"));
+    run_cargo_command(&[&"test"], Some(path), env, args)?;
+    Ok(())
+}
+
+// echo "[BENCH COMPILE] mod_bench"
+//
+// COMPILE_MOD_BENCH_INLINE="$RUSTC example/mod_bench.rs --crate-type bin -Zmir-opt-level=3 -O --crate-name mod_bench_inline"
+// COMPILE_MOD_BENCH_LLVM_0="rustc example/mod_bench.rs --crate-type bin -Copt-level=0 -o $cargo_target_dir/mod_bench_llvm_0 -Cpanic=abort"
+// COMPILE_MOD_BENCH_LLVM_1="rustc example/mod_bench.rs --crate-type bin -Copt-level=1 -o $cargo_target_dir/mod_bench_llvm_1 -Cpanic=abort"
+// COMPILE_MOD_BENCH_LLVM_2="rustc example/mod_bench.rs --crate-type bin -Copt-level=2 -o $cargo_target_dir/mod_bench_llvm_2 -Cpanic=abort"
+// COMPILE_MOD_BENCH_LLVM_3="rustc example/mod_bench.rs --crate-type bin -Copt-level=3 -o $cargo_target_dir/mod_bench_llvm_3 -Cpanic=abort"
+//
+// Use 100 runs, because a single compilations doesn't take more than ~150ms, so it isn't very slow
+// hyperfine --runs ${COMPILE_RUNS:-100} "$COMPILE_MOD_BENCH_INLINE" "$COMPILE_MOD_BENCH_LLVM_0" "$COMPILE_MOD_BENCH_LLVM_1" "$COMPILE_MOD_BENCH_LLVM_2" "$COMPILE_MOD_BENCH_LLVM_3"
+// echo "[BENCH RUN] mod_bench"
+// hyperfine --runs ${RUN_RUNS:-10} $cargo_target_dir/mod_bench{,_inline} $cargo_target_dir/mod_bench_llvm_*
+
+fn extended_rand_tests(env: &Env, args: &TestArg) -> Result<(), String> {
+    if !args.is_using_gcc_master_branch() {
+        println!("Not using GCC master branch. Skipping `extended_rand_tests`.");
+        return Ok(());
+    }
+    let mut env = env.clone();
+    // newer aho_corasick versions throw a deprecation warning
+    let rustflags = format!(
+        "{} --cap-lints warn",
+        env.get("RUSTFLAGS").cloned().unwrap_or_default()
+    );
+    env.insert("RUSTFLAGS".to_string(), rustflags);
+
+    let path = Path::new(crate::BUILD_DIR).join("rand");
+    run_cargo_command(&[&"clean"], Some(&path), &env, args)?;
+    // FIXME: create a function "display_if_not_quiet" or something along the line.
+    println!("[TEST] rust-random/rand");
+    run_cargo_command(&[&"test", &"--workspace"], Some(&path), &env, args)?;
+    Ok(())
+}
+
+fn extended_regex_example_tests(env: &Env, args: &TestArg) -> Result<(), String> {
+    if !args.is_using_gcc_master_branch() {
+        println!("Not using GCC master branch. Skipping `extended_regex_example_tests`.");
+        return Ok(());
+    }
+    let path = Path::new(crate::BUILD_DIR).join("regex");
+    run_cargo_command(&[&"clean"], Some(&path), env, args)?;
+    // FIXME: create a function "display_if_not_quiet" or something along the line.
+    println!("[TEST] rust-lang/regex example shootout-regex-dna");
+    let mut env = env.clone();
+    // newer aho_corasick versions throw a deprecation warning
+    let rustflags = format!(
+        "{} --cap-lints warn",
+        env.get("RUSTFLAGS").cloned().unwrap_or_default()
+    );
+    env.insert("RUSTFLAGS".to_string(), rustflags);
+    // Make sure `[codegen mono items] start` doesn't poison the diff
+    run_cargo_command(
+        &[&"build", &"--example", &"shootout-regex-dna"],
+        Some(&path),
+        &env,
+        args,
+    )?;
+
+    run_cargo_command_with_callback(
+        &[&"run", &"--example", &"shootout-regex-dna"],
+        Some(&path),
+        &env,
+        args,
+        |cargo_command, cwd, env| {
+            // FIXME: rewrite this with `child.stdin.write_all()` because
+            // `examples/regexdna-input.txt` is very small.
+            let mut command: Vec<&dyn AsRef<OsStr>> = vec![&"bash", &"-c"];
+            let cargo_args = cargo_command
+                .iter()
+                .map(|s| s.as_ref().to_str().unwrap())
+                .collect::<Vec<_>>();
+            let bash_command = format!(
+                "cat examples/regexdna-input.txt | {} | grep -v 'Spawned thread' > res.txt",
+                cargo_args.join(" "),
+            );
+            command.push(&bash_command);
+            run_command_with_output_and_env(&command, cwd, Some(env))?;
+            run_command_with_output_and_env(
+                &[&"diff", &"-u", &"res.txt", &"examples/regexdna-output.txt"],
+                cwd,
+                Some(env),
+            )?;
+            Ok(())
+        },
+    )?;
+
+    Ok(())
+}
+
+fn extended_regex_tests(env: &Env, args: &TestArg) -> Result<(), String> {
+    if !args.is_using_gcc_master_branch() {
+        println!("Not using GCC master branch. Skipping `extended_regex_tests`.");
+        return Ok(());
+    }
+    // FIXME: create a function "display_if_not_quiet" or something along the line.
+    println!("[TEST] rust-lang/regex tests");
+    let mut env = env.clone();
+    // newer aho_corasick versions throw a deprecation warning
+    let rustflags = format!(
+        "{} --cap-lints warn",
+        env.get("RUSTFLAGS").cloned().unwrap_or_default()
+    );
+    env.insert("RUSTFLAGS".to_string(), rustflags);
+    let path = Path::new(crate::BUILD_DIR).join("regex");
+    run_cargo_command(
+        &[
+            &"test",
+            &"--tests",
+            &"--",
+            // FIXME: try removing `--exclude-should-panic` argument
+            &"--exclude-should-panic",
+            &"--test-threads",
+            &"1",
+            &"-Zunstable-options",
+            &"-q",
+        ],
+        Some(&path),
+        &env,
+        args,
+    )?;
+    Ok(())
+}
+
+fn extended_sysroot_tests(env: &Env, args: &TestArg) -> Result<(), String> {
+    // pushd simple-raytracer
+    // echo "[BENCH COMPILE] ebobby/simple-raytracer"
+    // hyperfine --runs "${RUN_RUNS:-10}" --warmup 1 --prepare "cargo clean" \
+    // "RUSTC=rustc RUSTFLAGS='' cargo build" \
+    // "../y.sh cargo build"
+
+    // echo "[BENCH RUN] ebobby/simple-raytracer"
+    // cp ./target/debug/main ./raytracer_cg_gcc
+    // hyperfine --runs "${RUN_RUNS:-10}" ./raytracer_cg_llvm ./raytracer_cg_gcc
+    // popd
+    extended_rand_tests(env, args)?;
+    extended_regex_example_tests(env, args)?;
+    extended_regex_tests(env, args)?;
+
+    Ok(())
+}
+
+fn should_not_remove_test(file: &str) -> bool {
+    // contains //~ERROR, but shouldn't be removed
+    [
+        "issues/auxiliary/issue-3136-a.rs",
+        "type-alias-impl-trait/auxiliary/cross_crate_ice.rs",
+        "type-alias-impl-trait/auxiliary/cross_crate_ice2.rs",
+        "macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs",
+        "imports/ambiguous-1.rs",
+        "imports/ambiguous-4-extern.rs",
+        "entry-point/auxiliary/bad_main_functions.rs",
+    ]
+    .iter()
+    .any(|to_ignore| file.ends_with(to_ignore))
+}
+
+fn should_remove_test(file_path: &Path) -> Result<bool, String> {
+    // Tests generating errors.
+    let file = File::open(file_path)
+        .map_err(|error| format!("Failed to read `{}`: {:?}", file_path.display(), error))?;
+    for line in BufReader::new(file).lines().filter_map(|line| line.ok()) {
+        let line = line.trim();
+        if line.is_empty() {
+            continue;
+        }
+        if [
+            "//@ error-pattern:",
+            "//@ build-fail",
+            "//@ run-fail",
+            "-Cllvm-args",
+            "//~",
+            "thread",
+        ]
+        .iter()
+        .any(|check| line.contains(check))
+        {
+            return Ok(true);
+        }
+        if line.contains("//[") && line.contains("]~") {
+            return Ok(true);
+        }
+    }
+    if file_path
+        .display()
+        .to_string()
+        .contains("ambiguous-4-extern.rs")
+    {
+        eprintln!("nothing found for {file_path:?}");
+    }
+    Ok(false)
+}
+
+fn test_rustc_inner<F>(env: &Env, args: &TestArg, prepare_files_callback: F) -> Result<(), String>
+where
+    F: Fn(&Path) -> Result<bool, String>,
+{
+    // FIXME: create a function "display_if_not_quiet" or something along the line.
+    println!("[TEST] rust-lang/rust");
+    let mut env = env.clone();
+    let rust_path = setup_rustc(&mut env, args)?;
+
+    walk_dir(
+        rust_path.join("tests/ui"),
+        |dir| {
+            let dir_name = dir.file_name().and_then(|name| name.to_str()).unwrap_or("");
+            if [
+                "abi",
+                "extern",
+                "unsized-locals",
+                "proc-macro",
+                "threads-sendsync",
+                "borrowck",
+                "test-attrs",
+            ]
+            .iter()
+            .any(|name| *name == dir_name)
+            {
+                std::fs::remove_dir_all(dir).map_err(|error| {
+                    format!("Failed to remove folder `{}`: {:?}", dir.display(), error)
+                })?;
+            }
+            Ok(())
+        },
+        |_| Ok(()),
+    )?;
+
+    // These two functions are used to remove files that are known to not be working currently
+    // with the GCC backend to reduce noise.
+    fn dir_handling(dir: &Path) -> Result<(), String> {
+        if dir
+            .file_name()
+            .map(|name| name == "auxiliary")
+            .unwrap_or(true)
+        {
+            return Ok(());
+        }
+        walk_dir(dir, dir_handling, file_handling)
+    }
+    fn file_handling(file_path: &Path) -> Result<(), String> {
+        if !file_path
+            .extension()
+            .map(|extension| extension == "rs")
+            .unwrap_or(false)
+        {
+            return Ok(());
+        }
+        let path_str = file_path.display().to_string().replace("\\", "/");
+        if should_not_remove_test(&path_str) {
+            return Ok(());
+        } else if should_remove_test(file_path)? {
+            return remove_file(&file_path);
+        }
+        Ok(())
+    }
+
+    remove_file(&rust_path.join("tests/ui/consts/const_cmp_type_id.rs"))?;
+    remove_file(&rust_path.join("tests/ui/consts/issue-73976-monomorphic.rs"))?;
+    // this test is oom-killed in the CI.
+    remove_file(&rust_path.join("tests/ui/consts/issue-miri-1910.rs"))?;
+    // Tests generating errors.
+    remove_file(&rust_path.join("tests/ui/consts/issue-94675.rs"))?;
+    remove_file(&rust_path.join("tests/ui/mir/mir_heavy_promoted.rs"))?;
+    remove_file(&rust_path.join("tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop-fail.rs"))?;
+    remove_file(&rust_path.join("tests/ui/rfcs/rfc-2632-const-trait-impl/const-drop.rs"))?;
+
+    walk_dir(rust_path.join("tests/ui"), dir_handling, file_handling)?;
+
+    if !prepare_files_callback(&rust_path)? {
+        // FIXME: create a function "display_if_not_quiet" or something along the line.
+        println!("Keeping all UI tests");
+    }
+
+    let nb_parts = args.nb_parts.unwrap_or(0);
+    if nb_parts > 0 {
+        let current_part = args.current_part.unwrap();
+        // FIXME: create a function "display_if_not_quiet" or something along the line.
+        println!(
+            "Splitting ui_test into {} parts (and running part {})",
+            nb_parts, current_part
+        );
+        let out = String::from_utf8(
+            run_command(
+                &[
+                    &"find",
+                    &"tests/ui",
+                    &"-type",
+                    &"f",
+                    &"-name",
+                    &"*.rs",
+                    &"-not",
+                    &"-path",
+                    &"*/auxiliary/*",
+                ],
+                Some(&rust_path),
+            )?
+            .stdout,
+        )
+        .map_err(|error| format!("Failed to retrieve output of find command: {:?}", error))?;
+        let mut files = out
+            .split('\n')
+            .map(|line| line.trim())
+            .filter(|line| !line.is_empty())
+            .collect::<Vec<_>>();
+        // To ensure it'll be always the same sub files, we sort the content.
+        files.sort();
+        // We increment the number of tests by one because if this is an odd number, we would skip
+        // one test.
+        let count = files.len() / nb_parts + 1;
+        let start = current_part * count;
+        // We remove the files we don't want to test.
+        for path in files.iter().skip(start).take(count) {
+            remove_file(&rust_path.join(path))?;
+        }
+    }
+
+    // FIXME: create a function "display_if_not_quiet" or something along the line.
+    println!("[TEST] rustc test suite");
+    env.insert("COMPILETEST_FORCE_STAGE0".to_string(), "1".to_string());
+
+    let extra = if args.is_using_gcc_master_branch() {
+        ""
+    } else {
+        " -Csymbol-mangling-version=v0"
+    };
+
+    let rustc_args = format!(
+        "{} -Zcodegen-backend={} --sysroot {}{}",
+        env.get("TEST_FLAGS").unwrap_or(&String::new()),
+        args.config_info.cg_backend_path,
+        args.config_info.sysroot_path,
+        extra,
+    );
+
+    env.get_mut("RUSTFLAGS").unwrap().clear();
+    run_command_with_output_and_env(
+        &[
+            &"./x.py",
+            &"test",
+            &"--run",
+            &"always",
+            &"--stage",
+            &"0",
+            &"tests/ui",
+            &"--rustc-args",
+            &rustc_args,
+        ],
+        Some(&rust_path),
+        Some(&env),
+    )?;
+    Ok(())
+}
+
+fn test_rustc(env: &Env, args: &TestArg) -> Result<(), String> {
+    test_rustc_inner(env, args, |_| Ok(false))
+}
+
+fn test_failing_rustc(env: &Env, args: &TestArg) -> Result<(), String> {
+    test_rustc_inner(env, args, |rust_path| {
+        // Removing all tests.
+        run_command(
+            &[
+                &"find",
+                &"tests/ui",
+                &"-type",
+                &"f",
+                &"-name",
+                &"*.rs",
+                &"-not",
+                &"-path",
+                &"*/auxiliary/*",
+                &"-delete",
+            ],
+            Some(rust_path),
+        )?;
+        // Putting back only the failing ones.
+        let path = "tests/failing-ui-tests.txt";
+        if let Ok(files) = std::fs::read_to_string(path) {
+            for file in files
+                .split('\n')
+                .map(|line| line.trim())
+                .filter(|line| !line.is_empty())
+            {
+                run_command(&[&"git", &"checkout", &"--", &file], Some(&rust_path))?;
+            }
+        } else {
+            println!(
+                "Failed to read `{}`, not putting back failing ui tests",
+                path
+            );
+        }
+        Ok(true)
+    })
+}
+
+fn test_successful_rustc(env: &Env, args: &TestArg) -> Result<(), String> {
+    test_rustc_inner(env, args, |rust_path| {
+        // Removing the failing tests.
+        let path = "tests/failing-ui-tests.txt";
+        if let Ok(files) = std::fs::read_to_string(path) {
+            for file in files
+                .split('\n')
+                .map(|line| line.trim())
+                .filter(|line| !line.is_empty())
+            {
+                let path = rust_path.join(file);
+                remove_file(&path)?;
+            }
+        } else {
+            println!(
+                "Failed to read `{}`, not putting back failing ui tests",
+                path
+            );
+        }
+        Ok(true)
+    })
+}
+
+fn run_all(env: &Env, args: &TestArg) -> Result<(), String> {
+    clean(env, args)?;
+    mini_tests(env, args)?;
+    build_sysroot(env, args)?;
+    std_tests(env, args)?;
+    // asm_tests(env, args)?;
+    test_libcore(env, args)?;
+    extended_sysroot_tests(env, args)?;
+    test_rustc(env, args)?;
+    Ok(())
 }
 
 pub fn run() -> Result<(), String> {
-    let mut args: Vec<&dyn AsRef<std::ffi::OsStr>> = vec![&"bash", &"test.sh"];
-    let extra_args = std::env::args().skip(2).collect::<Vec<_>>();
-    get_args(&mut args, &extra_args);
-    let current_dir = std::env::current_dir().map_err(|error| format!("`current_dir` failed: {:?}", error))?;
-    run_command_with_output(args.as_slice(), Some(&current_dir))
+    let mut args = match TestArg::new()? {
+        Some(args) => args,
+        None => return Ok(()),
+    };
+    let mut env: HashMap<String, String> = std::env::vars().collect();
+
+    if !args.use_system_gcc {
+        args.config_info.setup_gcc_path()?;
+        env.insert(
+            "LIBRARY_PATH".to_string(),
+            args.config_info.gcc_path.clone(),
+        );
+        env.insert(
+            "LD_LIBRARY_PATH".to_string(),
+            args.config_info.gcc_path.clone(),
+        );
+    }
+
+    build_if_no_backend(&env, &args)?;
+    if args.build_only {
+        println!("Since it's build only, exiting...");
+        return Ok(());
+    }
+
+    args.config_info.setup(&mut env, args.use_system_gcc)?;
+
+    if args.runners.is_empty() {
+        run_all(&env, &args)?;
+    } else {
+        let runners = get_runners();
+        for runner in args.runners.iter() {
+            runners.get(runner.as_str()).unwrap().1(&env, &args)?;
+        }
+    }
+
+    Ok(())
 }
diff --git a/compiler/rustc_codegen_gcc/build_system/src/utils.rs b/compiler/rustc_codegen_gcc/build_system/src/utils.rs
index 536f33a8029..d9c13fd143d 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/utils.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/utils.rs
@@ -2,7 +2,7 @@ use std::collections::HashMap;
 use std::ffi::OsStr;
 use std::fmt::Debug;
 use std::fs;
-use std::path::Path;
+use std::path::{Path, PathBuf};
 use std::process::{Command, ExitStatus, Output};
 
 fn get_command_inner(
@@ -29,22 +29,40 @@ fn check_exit_status(
     input: &[&dyn AsRef<OsStr>],
     cwd: Option<&Path>,
     exit_status: ExitStatus,
+    output: Option<&Output>,
+    show_err: bool,
 ) -> Result<(), String> {
     if exit_status.success() {
-        Ok(())
-    } else {
-        Err(format!(
-            "Command `{}`{} exited with status {:?}",
-            input
-                .iter()
-                .map(|s| s.as_ref().to_str().unwrap())
-                .collect::<Vec<_>>()
-                .join(" "),
-            cwd.map(|cwd| format!(" (running in folder `{}`)", cwd.display()))
-                .unwrap_or_default(),
-            exit_status.code(),
-        ))
+        return Ok(());
     }
+    let mut error = format!(
+        "Command `{}`{} exited with status {:?}",
+        input
+            .iter()
+            .map(|s| s.as_ref().to_str().unwrap())
+            .collect::<Vec<_>>()
+            .join(" "),
+        cwd.map(|cwd| format!(" (running in folder `{}`)", cwd.display()))
+            .unwrap_or_default(),
+        exit_status.code()
+    );
+    let input = input.iter().map(|i| i.as_ref()).collect::<Vec<&OsStr>>();
+    if show_err {
+        eprintln!("Command `{:?}` failed", input);
+    }
+    if let Some(output) = output {
+        let stdout = String::from_utf8_lossy(&output.stdout);
+        if !stdout.is_empty() {
+            error.push_str("\n==== STDOUT ====\n");
+            error.push_str(&*stdout);
+        }
+        let stderr = String::from_utf8_lossy(&output.stderr);
+        if !stderr.is_empty() {
+            error.push_str("\n==== STDERR ====\n");
+            error.push_str(&*stderr);
+        }
+    }
+    Err(error)
 }
 
 fn command_error<D: Debug>(input: &[&dyn AsRef<OsStr>], cwd: &Option<&Path>, error: D) -> String {
@@ -73,7 +91,7 @@ pub fn run_command_with_env(
     let output = get_command_inner(input, cwd, env)
         .output()
         .map_err(|e| command_error(input, &cwd, e))?;
-    check_exit_status(input, cwd, output.status)?;
+    check_exit_status(input, cwd, output.status, Some(&output), true)?;
     Ok(output)
 }
 
@@ -86,7 +104,7 @@ pub fn run_command_with_output(
         .map_err(|e| command_error(input, &cwd, e))?
         .wait()
         .map_err(|e| command_error(input, &cwd, e))?;
-    check_exit_status(input, cwd, exit_status)?;
+    check_exit_status(input, cwd, exit_status, None, true)?;
     Ok(())
 }
 
@@ -100,7 +118,21 @@ pub fn run_command_with_output_and_env(
         .map_err(|e| command_error(input, &cwd, e))?
         .wait()
         .map_err(|e| command_error(input, &cwd, e))?;
-    check_exit_status(input, cwd, exit_status)?;
+    check_exit_status(input, cwd, exit_status, None, true)?;
+    Ok(())
+}
+
+pub fn run_command_with_output_and_env_no_err(
+    input: &[&dyn AsRef<OsStr>],
+    cwd: Option<&Path>,
+    env: Option<&HashMap<String, String>>,
+) -> Result<(), String> {
+    let exit_status = get_command_inner(input, cwd, env)
+        .spawn()
+        .map_err(|e| command_error(input, &cwd, e))?
+        .wait()
+        .map_err(|e| command_error(input, &cwd, e))?;
+    check_exit_status(input, cwd, exit_status, None, false)?;
     Ok(())
 }
 
@@ -143,80 +175,157 @@ pub fn get_os_name() -> Result<String, String> {
     }
 }
 
-pub fn get_rustc_host_triple() -> Result<String, String> {
-    let output = run_command(&[&"rustc", &"-vV"], None)?;
+#[derive(Default, PartialEq)]
+pub struct RustcVersionInfo {
+    pub short: String,
+    pub version: String,
+    pub host: Option<String>,
+    pub commit_hash: Option<String>,
+    pub commit_date: Option<String>,
+}
+
+pub fn rustc_toolchain_version_info(toolchain: &str) -> Result<RustcVersionInfo, String> {
+    rustc_version_info_inner(None, Some(toolchain))
+}
+
+pub fn rustc_version_info(rustc: Option<&str>) -> Result<RustcVersionInfo, String> {
+    rustc_version_info_inner(rustc, None)
+}
+
+fn rustc_version_info_inner(
+    rustc: Option<&str>,
+    toolchain: Option<&str>,
+) -> Result<RustcVersionInfo, String> {
+    let output = if let Some(toolchain) = toolchain {
+        run_command(&[&rustc.unwrap_or("rustc"), &toolchain, &"-vV"], None)
+    } else {
+        run_command(&[&rustc.unwrap_or("rustc"), &"-vV"], None)
+    }?;
     let content = std::str::from_utf8(&output.stdout).unwrap_or("");
 
-    for line in content.split('\n').map(|line| line.trim()) {
-        if !line.starts_with("host:") {
-            continue;
+    let mut info = RustcVersionInfo::default();
+    let mut lines = content.split('\n');
+    info.short = match lines.next() {
+        Some(s) => s.to_string(),
+        None => return Err("failed to retrieve rustc version".to_string()),
+    };
+
+    for line in lines.map(|line| line.trim()) {
+        match line.split_once(':') {
+            Some(("host", data)) => info.host = Some(data.trim().to_string()),
+            Some(("release", data)) => info.version = data.trim().to_string(),
+            Some(("commit-hash", data)) => info.commit_hash = Some(data.trim().to_string()),
+            Some(("commit-date", data)) => info.commit_date = Some(data.trim().to_string()),
+            _ => {}
         }
-        return Ok(line.split(':').nth(1).unwrap().trim().to_string());
     }
-    Err("Cannot find host triple".to_string())
+    if info.version.is_empty() {
+        Err("failed to retrieve rustc version".to_string())
+    } else {
+        Ok(info)
+    }
 }
 
-pub fn get_gcc_path() -> Result<String, String> {
-    let content = match fs::read_to_string("gcc_path") {
+pub fn get_toolchain() -> Result<String, String> {
+    let content = match fs::read_to_string("rust-toolchain") {
         Ok(content) => content,
-        Err(_) => {
-            return Err(
-                "Please put the path to your custom build of libgccjit in the file \
-                   `gcc_path`, see Readme.md for details"
-                    .into(),
-            )
-        }
+        Err(_) => return Err("No `rust-toolchain` file found".to_string()),
     };
     match content
         .split('\n')
         .map(|line| line.trim())
         .filter(|line| !line.is_empty())
+        .filter_map(|line| {
+            if !line.starts_with("channel") {
+                return None;
+            }
+            line.split('"').skip(1).next()
+        })
         .next()
     {
-        Some(gcc_path) => {
-            let path = Path::new(gcc_path);
-            if !path.exists() {
-                Err(format!(
-                    "Path `{}` contained in the `gcc_path` file doesn't exist",
-                    gcc_path,
-                ))
-            } else {
-                Ok(gcc_path.into())
-            }
-        }
-        None => Err("No path found in `gcc_path` file".into()),
+        Some(toolchain) => Ok(toolchain.to_string()),
+        None => Err("Couldn't find `channel` in `rust-toolchain` file".to_string()),
     }
 }
 
 pub struct CloneResult {
     pub ran_clone: bool,
     pub repo_name: String,
+    pub repo_dir: String,
 }
 
-pub fn git_clone(to_clone: &str, dest: Option<&Path>) -> Result<CloneResult, String> {
-    let repo_name = to_clone.split('/').last().unwrap();
-    let repo_name = match repo_name.strip_suffix(".git") {
-        Some(n) => n.to_string(),
-        None => repo_name.to_string(),
-    };
-
-    let dest = dest
-        .map(|dest| dest.join(&repo_name))
-        .unwrap_or_else(|| Path::new(&repo_name).into());
+fn git_clone_inner(
+    to_clone: &str,
+    dest: &Path,
+    shallow_clone: bool,
+    repo_name: String,
+) -> Result<CloneResult, String> {
     if dest.is_dir() {
         return Ok(CloneResult {
             ran_clone: false,
             repo_name,
+            repo_dir: dest.display().to_string(),
         });
     }
 
-    run_command_with_output(&[&"git", &"clone", &to_clone, &dest], None)?;
+    let mut command: Vec<&dyn AsRef<OsStr>> = vec![&"git", &"clone", &to_clone, &dest];
+    if shallow_clone {
+        command.push(&"--depth");
+        command.push(&"1");
+    }
+    run_command_with_output(&command, None)?;
     Ok(CloneResult {
         ran_clone: true,
         repo_name,
+        repo_dir: dest.display().to_string(),
     })
 }
 
+fn get_repo_name(url: &str) -> String {
+    let repo_name = url.split('/').last().unwrap();
+    match repo_name.strip_suffix(".git") {
+        Some(n) => n.to_string(),
+        None => repo_name.to_string(),
+    }
+}
+
+pub fn git_clone(
+    to_clone: &str,
+    dest: Option<&Path>,
+    shallow_clone: bool,
+) -> Result<CloneResult, String> {
+    let repo_name = get_repo_name(to_clone);
+    let tmp: PathBuf;
+
+    let dest = match dest {
+        Some(dest) => dest,
+        None => {
+            tmp = repo_name.clone().into();
+            &tmp
+        }
+    };
+    git_clone_inner(to_clone, dest, shallow_clone, repo_name)
+}
+
+/// This function differs from `git_clone` in how it handles *where* the repository will be cloned.
+/// In `git_clone`, it is cloned in the provided path. In this function, the path you provide is
+/// the parent folder. So if you pass "a" as folder and try to clone "b.git", it will be cloned into
+/// `a/b`.
+pub fn git_clone_root_dir(
+    to_clone: &str,
+    dest_parent_dir: &Path,
+    shallow_clone: bool,
+) -> Result<CloneResult, String> {
+    let repo_name = get_repo_name(to_clone);
+
+    git_clone_inner(
+        to_clone,
+        &dest_parent_dir.join(&repo_name),
+        shallow_clone,
+        repo_name,
+    )
+}
+
 pub fn walk_dir<P, D, F>(dir: P, mut dir_cb: D, mut file_cb: F) -> Result<(), String>
 where
     P: AsRef<Path>,
@@ -238,3 +347,105 @@ where
     }
     Ok(())
 }
+
+pub fn split_args(args: &str) -> Result<Vec<String>, String> {
+    let mut out = Vec::new();
+    let mut start = 0;
+    let args = args.trim();
+    let mut iter = args.char_indices().peekable();
+
+    while let Some((pos, c)) = iter.next() {
+        if c == ' ' {
+            out.push(args[start..pos].to_string());
+            let mut found_start = false;
+            while let Some((pos, c)) = iter.peek() {
+                if *c != ' ' {
+                    start = *pos;
+                    found_start = true;
+                    break;
+                } else {
+                    iter.next();
+                }
+            }
+            if !found_start {
+                return Ok(out);
+            }
+        } else if c == '"' || c == '\'' {
+            let end = c;
+            let mut found_end = false;
+            while let Some((_, c)) = iter.next() {
+                if c == end {
+                    found_end = true;
+                    break;
+                } else if c == '\\' {
+                    // We skip the escaped character.
+                    iter.next();
+                }
+            }
+            if !found_end {
+                return Err(format!(
+                    "Didn't find `{}` at the end of `{}`",
+                    end,
+                    &args[start..]
+                ));
+            }
+        } else if c == '\\' {
+            // We skip the escaped character.
+            iter.next();
+        }
+    }
+    let s = args[start..].trim();
+    if !s.is_empty() {
+        out.push(s.to_string());
+    }
+    Ok(out)
+}
+
+pub fn remove_file<P: AsRef<Path> + ?Sized>(file_path: &P) -> Result<(), String> {
+    std::fs::remove_file(file_path).map_err(|error| {
+        format!(
+            "Failed to remove `{}`: {:?}",
+            file_path.as_ref().display(),
+            error
+        )
+    })
+}
+
+pub fn create_symlink<P: AsRef<Path>, Q: AsRef<Path>>(original: P, link: Q) -> Result<(), String> {
+    #[cfg(windows)]
+    let symlink = std::os::windows::fs::symlink_file;
+    #[cfg(not(windows))]
+    let symlink = std::os::unix::fs::symlink;
+
+    symlink(&original, &link).map_err(|err| {
+        format!(
+            "failed to create a symlink `{}` to `{}`: {:?}",
+            original.as_ref().display(),
+            link.as_ref().display(),
+            err,
+        )
+    })
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn test_split_args() {
+        // Missing `"` at the end.
+        assert!(split_args("\"tada").is_err());
+        // Missing `'` at the end.
+        assert!(split_args("\'tada").is_err());
+
+        assert_eq!(
+            split_args("a \"b\" c"),
+            Ok(vec!["a".to_string(), "\"b\"".to_string(), "c".to_string()])
+        );
+        // Trailing whitespace characters.
+        assert_eq!(
+            split_args("    a    \"b\" c    "),
+            Ok(vec!["a".to_string(), "\"b\"".to_string(), "c".to_string()])
+        );
+    }
+}
diff --git a/compiler/rustc_codegen_gcc/cargo.sh b/compiler/rustc_codegen_gcc/cargo.sh
deleted file mode 100755
index b68a08ee88f..00000000000
--- a/compiler/rustc_codegen_gcc/cargo.sh
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/usr/bin/env bash
-
-if [ -z $CHANNEL ]; then
-export CHANNEL='debug'
-fi
-
-pushd $(dirname "$0") >/dev/null
-source config.sh
-
-# read nightly compiler from rust-toolchain file
-TOOLCHAIN=$(cat rust-toolchain | grep channel | sed 's/channel = "\(.*\)"/\1/')
-
-popd >/dev/null
-
-if [[ $(${RUSTC} -V) != $(${RUSTC} +${TOOLCHAIN} -V) ]]; then
-    echo "rustc_codegen_gcc is build for $(rustc +${TOOLCHAIN} -V) but the default rustc version is $(rustc -V)."
-    echo "Using $(rustc +${TOOLCHAIN} -V)."
-fi
-
-cmd=$1
-shift
-
-RUSTDOCFLAGS="$RUSTFLAGS" cargo +${TOOLCHAIN} $cmd $@
diff --git a/compiler/rustc_codegen_gcc/clean_all.sh b/compiler/rustc_codegen_gcc/clean_all.sh
deleted file mode 100755
index 782bd3e5058..00000000000
--- a/compiler/rustc_codegen_gcc/clean_all.sh
+++ /dev/null
@@ -1,6 +0,0 @@
-#!/usr/bin/env bash
-set -e
-set -v
-
-rm -rf target/ build_sysroot/{sysroot/,sysroot_src/,target/,Cargo.lock} perf.data{,.old}
-rm -rf regex/ simple-raytracer/
diff --git a/compiler/rustc_codegen_gcc/config.example.toml b/compiler/rustc_codegen_gcc/config.example.toml
new file mode 100644
index 00000000000..dcc414b7310
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/config.example.toml
@@ -0,0 +1,2 @@
+gcc-path = "gcc-build/gcc"
+# download-gccjit = true
diff --git a/compiler/rustc_codegen_gcc/config.sh b/compiler/rustc_codegen_gcc/config.sh
deleted file mode 100644
index 7ae2175d41d..00000000000
--- a/compiler/rustc_codegen_gcc/config.sh
+++ /dev/null
@@ -1,85 +0,0 @@
-set -e
-
-export CARGO_INCREMENTAL=0
-
-if [ -f ./gcc_path ]; then
-    export GCC_PATH=$(cat gcc_path)
-elif (( $use_system_gcc == 1 )); then
-    echo 'Using system GCC'
-else
-    echo 'Please put the path to your custom build of libgccjit in the file `gcc_path`, see Readme.md for details'
-    exit 1
-fi
-
-if [[ -z "$RUSTC" ]]; then
-    export RUSTC="rustc"
-fi
-
-unamestr=`uname`
-if [[ "$unamestr" == 'Linux' ]]; then
-    dylib_ext='so'
-elif [[ "$unamestr" == 'Darwin' ]]; then
-    dylib_ext='dylib'
-else
-    echo "Unsupported os"
-    exit 1
-fi
-
-HOST_TRIPLE=$($RUSTC -vV | grep host | cut -d: -f2 | tr -d " ")
-# TODO: remove $OVERWRITE_TARGET_TRIPLE when config.sh is removed.
-TARGET_TRIPLE="${OVERWRITE_TARGET_TRIPLE:-$HOST_TRIPLE}"
-
-linker=''
-RUN_WRAPPER=''
-if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then
-    RUN_WRAPPER=run_in_vm
-    if [[ "$TARGET_TRIPLE" == "m68k-unknown-linux-gnu" ]]; then
-        linker='-Clinker=m68k-unknown-linux-gnu-gcc'
-    elif [[ "$TARGET_TRIPLE" == "aarch64-unknown-linux-gnu" ]]; then
-        # We are cross-compiling for aarch64. Use the correct linker and run tests in qemu.
-        linker='-Clinker=aarch64-linux-gnu-gcc'
-    else
-        echo "Unknown non-native platform"
-    fi
-fi
-
-# Since we don't support ThinLTO, disable LTO completely when not trying to do LTO.
-# TODO(antoyo): remove when we can handle ThinLTO.
-disable_lto_flags=''
-if [[ ! -v FAT_LTO ]]; then
-    disable_lto_flags='-Clto=off'
-fi
-
-if [[ -z "$BUILTIN_BACKEND" ]]; then
-    export RUSTFLAGS="$CG_RUSTFLAGS $linker -Csymbol-mangling-version=v0 -Cdebuginfo=2 $disable_lto_flags -Zcodegen-backend=$(pwd)/target/${CHANNEL:-debug}/librustc_codegen_gcc.$dylib_ext --sysroot $(pwd)/build_sysroot/sysroot $TEST_FLAGS"
-else
-    export RUSTFLAGS="$CG_RUSTFLAGS $linker -Csymbol-mangling-version=v0 -Cdebuginfo=2 $disable_lto_flags -Zcodegen-backend=gcc $TEST_FLAGS -Cpanic=abort"
-
-    if [[ ! -z "$RUSTC_SYSROOT" ]]; then
-        export RUSTFLAGS="$RUSTFLAGS --sysroot $RUSTC_SYSROOT"
-    fi
-fi
-
-# FIXME(antoyo): remove once the atomic shim is gone
-if [[ unamestr == 'Darwin' ]]; then
-    export RUSTFLAGS="$RUSTFLAGS -Clink-arg=-undefined -Clink-arg=dynamic_lookup"
-fi
-
-if [[ -z "$cargo_target_dir" ]]; then
-    RUST_CMD="$RUSTC $RUSTFLAGS -L crate=target/out --out-dir target/out"
-    cargo_target_dir="target/out"
-else
-    RUST_CMD="$RUSTC $RUSTFLAGS -L crate=$cargo_target_dir --out-dir $cargo_target_dir"
-fi
-export RUSTC_LOG=warn # display metadata load errors
-
-export LD_LIBRARY_PATH="$(pwd)/target/out:$(pwd)/build_sysroot/sysroot/lib/rustlib/$TARGET_TRIPLE/lib"
-if [[ ! -z "$:$GCC_PATH" ]]; then
-    export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$GCC_PATH"
-fi
-
-export DYLD_LIBRARY_PATH=$LD_LIBRARY_PATH
-# NOTE: To avoid the -fno-inline errors, use /opt/gcc/bin/gcc instead of cc.
-# To do so, add a symlink for cc to /opt/gcc/bin/gcc in our PATH.
-# Another option would be to add the following Rust flag: -Clinker=/opt/gcc/bin/gcc
-export PATH="/opt/gcc/bin:/opt/m68k-unknown-linux-gnu/bin:$PATH"
diff --git a/compiler/rustc_codegen_gcc/crate_patches/0002-rand-Disable-failing-test.patch b/compiler/rustc_codegen_gcc/crate_patches/0002-rand-Disable-failing-test.patch
deleted file mode 100644
index 449ca5f6e29..00000000000
--- a/compiler/rustc_codegen_gcc/crate_patches/0002-rand-Disable-failing-test.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From a8fb97120d71252538b6b026695df40d02696bdb Mon Sep 17 00:00:00 2001
-From: bjorn3 <bjorn3@users.noreply.github.com>
-Date: Sat, 15 Aug 2020 20:04:38 +0200
-Subject: [PATCH] [rand] Disable failing test
-
----
- src/distributions/uniform.rs | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/src/distributions/uniform.rs b/src/distributions/uniform.rs
-index 480b859..c80bb6f 100644
---- a/src/distributions/uniform.rs
-+++ b/src/distributions/uniform.rs
-@@ -1085,7 +1085,7 @@ mod tests {
-             _ => panic!("`UniformDurationMode` was not serialized/deserialized correctly")
-         }
-     }
--    
-+
-     #[test]
-     #[cfg(feature = "serde1")]
-     fn test_uniform_serialization() {
-@@ -1314,6 +1314,7 @@ mod tests {
-         not(target_arch = "wasm32"),
-         not(target_arch = "asmjs")
-     ))]
-+    #[ignore] // FIXME
-     fn test_float_assertions() {
-         use super::SampleUniform;
-         use std::panic::catch_unwind;
--- 
-2.20.1
diff --git a/compiler/rustc_codegen_gcc/deps/libLLVM-18-rust-1.78.0-nightly.so b/compiler/rustc_codegen_gcc/deps/libLLVM-18-rust-1.78.0-nightly.so
new file mode 100644
index 00000000000..c44ca790b4f
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/deps/libLLVM-18-rust-1.78.0-nightly.so
@@ -0,0 +1 @@
+INPUT(libLLVM.so.18.1-rust-1.78.0-nightly)
diff --git a/compiler/rustc_codegen_gcc/doc/debugging-gcc-lto.md b/compiler/rustc_codegen_gcc/doc/debugging-gcc-lto.md
new file mode 100644
index 00000000000..93b150d7686
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/doc/debugging-gcc-lto.md
@@ -0,0 +1,3 @@
+# How to debug GCC LTO
+
+Run do the command with `-v -save-temps` and then extract the `lto1` line from the output and run that under the debugger.
diff --git a/compiler/rustc_codegen_gcc/doc/debugging-libgccjit.md b/compiler/rustc_codegen_gcc/doc/debugging-libgccjit.md
new file mode 100644
index 00000000000..be0ec83f7cd
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/doc/debugging-libgccjit.md
@@ -0,0 +1,74 @@
+# Debugging libgccjit
+
+Sometimes, libgccjit will crash and output an error like this:
+
+```
+during RTL pass: expand
+libgccjit.so: error: in expmed_mode_index, at expmed.h:249
+0x7f0da2e61a35 expmed_mode_index
+	../../../gcc/gcc/expmed.h:249
+0x7f0da2e61aa4 expmed_op_cost_ptr
+	../../../gcc/gcc/expmed.h:271
+0x7f0da2e620dc sdiv_cost_ptr
+	../../../gcc/gcc/expmed.h:540
+0x7f0da2e62129 sdiv_cost
+	../../../gcc/gcc/expmed.h:558
+0x7f0da2e73c12 expand_divmod(int, tree_code, machine_mode, rtx_def*, rtx_def*, rtx_def*, int)
+	../../../gcc/gcc/expmed.c:4335
+0x7f0da2ea1423 expand_expr_real_2(separate_ops*, rtx_def*, machine_mode, expand_modifier)
+	../../../gcc/gcc/expr.c:9240
+0x7f0da2cd1a1e expand_gimple_stmt_1
+	../../../gcc/gcc/cfgexpand.c:3796
+0x7f0da2cd1c30 expand_gimple_stmt
+	../../../gcc/gcc/cfgexpand.c:3857
+0x7f0da2cd90a9 expand_gimple_basic_block
+	../../../gcc/gcc/cfgexpand.c:5898
+0x7f0da2cdade8 execute
+	../../../gcc/gcc/cfgexpand.c:6582
+```
+
+To see the code which causes this error, call the following function:
+
+```c
+gcc_jit_context_dump_to_file(ctxt, "/tmp/output.c", 1 /* update_locations */)
+```
+
+This will create a C-like file and add the locations into the IR pointing to this C file.
+Then, rerun the program and it will output the location in the second line:
+
+```
+libgccjit.so: /tmp/something.c:61322:0: error: in expmed_mode_index, at expmed.h:249
+```
+
+Or add a breakpoint to `add_error` in gdb and print the line number using:
+
+```
+p loc->m_line
+p loc->m_filename->m_buffer
+```
+
+To print a debug representation of a tree:
+
+```c
+debug_tree(expr);
+```
+
+(defined in print-tree.h)
+
+To print a debug representation of a gimple struct:
+
+```c
+debug_gimple_stmt(gimple_struct)
+```
+
+To get the `rustc` command to run in `gdb`, add the `--verbose` flag to `cargo build`.
+
+To have the correct file paths in `gdb` instead of `/usr/src/debug/gcc/libstdc++-v3/libsupc++/eh_personality.cc`:
+
+Maybe by calling the following at the beginning of gdb:
+
+```
+set substitute-path /usr/src/debug/gcc /path/to/gcc-repo/gcc
+```
+
+TODO(antoyo): but that's not what I remember I was doing.
diff --git a/compiler/rustc_codegen_gcc/doc/errors.md b/compiler/rustc_codegen_gcc/doc/errors.md
new file mode 100644
index 00000000000..5727b0ff7c8
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/doc/errors.md
@@ -0,0 +1,27 @@
+# Common errors
+
+This file lists errors that were encountered and how to fix them.
+
+### `failed to build archive` error
+
+When you get this error:
+
+```
+error: failed to build archive: failed to open object file: No such file or directory (os error 2)
+```
+
+That can be caused by the fact that you try to compile with `lto = "fat"`, but you didn't compile the sysroot with LTO.
+(Not sure if that's the reason since I cannot reproduce anymore. Maybe it happened when forgetting setting `FAT_LTO`.)
+
+### ld: cannot find crtbegin.o
+
+When compiling an executable with libgccijt, if setting the `*LIBRARY_PATH` variables to the install directory, you will get the following errors:
+
+```
+ld: cannot find crtbegin.o: No such file or directory
+ld: cannot find -lgcc: No such file or directory
+ld: cannot find -lgcc: No such file or directory
+libgccjit.so: error: error invoking gcc driver
+```
+
+To fix this, set the variables to `gcc-build/build/gcc`.
diff --git a/compiler/rustc_codegen_gcc/doc/subtree.md b/compiler/rustc_codegen_gcc/doc/subtree.md
new file mode 100644
index 00000000000..5d7af2a066b
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/doc/subtree.md
@@ -0,0 +1,52 @@
+# git subtree sync
+
+`rustc_codegen_gcc` is a subtree of the rust compiler. As such, it needs to be
+sync from time to time to ensure changes that happened on their side are also
+included on our side.
+
+### How to install a forked git-subtree
+
+Using git-subtree with `rustc` requires a patched git to make it work.
+The PR that is needed is [here](https://github.com/gitgitgadget/git/pull/493).
+Use the following instructions to install it:
+
+```bash
+git clone git@github.com:tqc/git.git
+cd git
+git checkout tqc/subtree
+make
+make install
+cd contrib/subtree
+make
+cp git-subtree ~/bin
+```
+
+### Syncing with rust compiler
+
+Do a sync with this command:
+
+```bash
+PATH="$HOME/bin:$PATH" ~/bin/git-subtree push -P compiler/rustc_codegen_gcc/ ../rustc_codegen_gcc/ sync_branch_name
+cd ../rustc_codegen_gcc
+git checkout master
+git pull
+git checkout sync_branch_name
+git merge master
+```
+
+To send the changes to the rust repo:
+
+```bash
+cd ../rust
+git pull origin master
+git checkout -b subtree-update_cg_gcc_YYYY-MM-DD
+PATH="$HOME/bin:$PATH" ~/bin/git-subtree pull --prefix=compiler/rustc_codegen_gcc/ https://github.com/rust-lang/rustc_codegen_gcc.git master
+git push
+
+# Immediately merge the merge commit into cg_gcc to prevent merge conflicts when syncing from rust-lang/rust later.
+PATH="$HOME/bin:$PATH" ~/bin/git-subtree push -P compiler/rustc_codegen_gcc/ ../rustc_codegen_gcc/ sync_branch_name
+```
+
+TODO: write a script that does the above.
+
+https://rust-lang.zulipchat.com/#narrow/stream/301329-t-devtools/topic/subtree.20madness/near/258877725
diff --git a/compiler/rustc_codegen_gcc/doc/tips.md b/compiler/rustc_codegen_gcc/doc/tips.md
new file mode 100644
index 00000000000..1379f5130be
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/doc/tips.md
@@ -0,0 +1,72 @@
+# Tips
+
+The following shows how to do different random small things we encountered and thought could
+be useful.
+
+### How to send arguments to the GCC linker
+
+```
+CG_RUSTFLAGS="-Clink-args=-save-temps -v" ../y.sh cargo build
+```
+
+### How to see the personality functions in the asm dump
+
+```
+CG_RUSTFLAGS="-Clink-arg=-save-temps -v -Clink-arg=-dA" ../y.sh cargo build
+```
+
+### How to see the LLVM IR for a sysroot crate
+
+```
+cargo build -v --target x86_64-unknown-linux-gnu -Zbuild-std
+# Take the command from the output and add --emit=llvm-ir
+```
+
+### To prevent the linker from unmangling symbols
+
+Run with:
+
+```
+COLLECT_NO_DEMANGLE=1
+```
+
+### How to use a custom-build rustc
+
+ * Build the stage2 compiler (`rustup toolchain link debug-current build/x86_64-unknown-linux-gnu/stage2`).
+ * Clean and rebuild the codegen with `debug-current` in the file `rust-toolchain`.
+
+### How to use [mem-trace](https://github.com/antoyo/mem-trace)
+
+`rustc` needs to be built without `jemalloc` so that `mem-trace` can overload `malloc` since `jemalloc` is linked statically, so a `LD_PRELOAD`-ed library won't a chance to intercept the calls to `malloc`.
+
+### How to generate GIMPLE
+
+If you need to check what gccjit is generating (GIMPLE), then take a look at how to
+generate it in [gimple.md](./doc/gimple.md).
+
+### How to build a cross-compiling libgccjit
+
+#### Building libgccjit
+
+ * Follow the instructions on [this repo](https://github.com/cross-cg-gcc-tools/cross-gcc).
+
+#### Configuring rustc_codegen_gcc
+
+ * Run `./y.sh prepare --cross` so that the sysroot is patched for the cross-compiling case.
+ * Set the path to the cross-compiling libgccjit in `gcc-path` (in `config.toml`).
+ * Make sure you have the linker for your target (for instance `m68k-unknown-linux-gnu-gcc`) in your `$PATH`. Currently, the linker name is hardcoded as being `$TARGET-gcc`. Specify the target when building the sysroot: `./y.sh build --target-triple m68k-unknown-linux-gnu`.
+ * Build your project by specifying the target: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../y.sh cargo build --target m68k-unknown-linux-gnu`.
+
+If the target is not yet supported by the Rust compiler, create a [target specification file](https://docs.rust-embedded.org/embedonomicon/custom-target.html) (note that the `arch` specified in this file must be supported by the rust compiler).
+Then, you can use it the following way:
+
+ * Add the target specification file using `--target` as an **absolute** path to build the sysroot: `./y.sh build --target-triple m68k-unknown-linux-gnu --target $(pwd)/m68k-unknown-linux-gnu.json`
+ * Build your project by specifying the target specification file: `OVERWRITE_TARGET_TRIPLE=m68k-unknown-linux-gnu ../y.sh cargo build --target path/to/m68k-unknown-linux-gnu.json`.
+
+If you get the following error:
+
+```
+/usr/bin/ld: unrecognised emulation mode: m68kelf
+```
+
+Make sure you set `gcc-path` (in `config.toml`) to the install directory.
diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs
index cc3d647c8c8..a868471ed1d 100644
--- a/compiler/rustc_codegen_gcc/example/mini_core.rs
+++ b/compiler/rustc_codegen_gcc/example/mini_core.rs
@@ -1,6 +1,6 @@
 #![feature(
     no_core, lang_items, intrinsics, unboxed_closures, type_ascription, extern_types,
-    decl_macro, rustc_attrs, transparent_unions, auto_traits,
+    decl_macro, rustc_attrs, transparent_unions, auto_traits, freeze_impls,
     thread_local
 )]
 #![no_core]
diff --git a/compiler/rustc_codegen_gcc/libgccjit.version b/compiler/rustc_codegen_gcc/libgccjit.version
new file mode 100644
index 00000000000..41bec6df5d9
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/libgccjit.version
@@ -0,0 +1 @@
+b6f163f52
diff --git a/compiler/rustc_codegen_gcc/messages.ftl b/compiler/rustc_codegen_gcc/messages.ftl
index 5ca0a2e1b6d..0235384445e 100644
--- a/compiler/rustc_codegen_gcc/messages.ftl
+++ b/compiler/rustc_codegen_gcc/messages.ftl
@@ -20,8 +20,6 @@ codegen_gcc_dynamic_linking_with_lto =
     cannot prefer dynamic linking when performing LTO
     .note = only 'staticlib', 'bin', and 'cdylib' outputs are supported with LTO
 
-codegen_gcc_load_bitcode = failed to load bitcode of module "{$name}"
-
 codegen_gcc_lto_disallowed = lto can only be run for executables, cdylibs and static library outputs
 
 codegen_gcc_lto_dylib = lto cannot be used for `dylib` crate type without `-Zdylib-lto`
diff --git a/compiler/rustc_codegen_gcc/patches/0022-core-Disable-not-compiling-tests.patch b/compiler/rustc_codegen_gcc/patches/0022-core-Disable-not-compiling-tests.patch
index 4db56fa3bd2..a7d523f9408 100644
--- a/compiler/rustc_codegen_gcc/patches/0022-core-Disable-not-compiling-tests.patch
+++ b/compiler/rustc_codegen_gcc/patches/0022-core-Disable-not-compiling-tests.patch
@@ -39,6 +39,4 @@ index 42a26ae..5ac1042 100644
 +#![cfg(test)]
  #![feature(alloc_layout_extra)]
  #![feature(array_chunks)]
- #![feature(array_methods)]
---
-2.21.0 (Apple Git-122)
+ #![feature(array_windows)]
diff --git a/compiler/rustc_codegen_gcc/patches/crates/0001-Remove-deny-warnings.patch b/compiler/rustc_codegen_gcc/patches/crates/0001-Remove-deny-warnings.patch
new file mode 100644
index 00000000000..66ea1df4e13
--- /dev/null
+++ b/compiler/rustc_codegen_gcc/patches/crates/0001-Remove-deny-warnings.patch
@@ -0,0 +1,24 @@
+From f4a31d2c57cdbd578b778ab70eb2a0cfb248652c Mon Sep 17 00:00:00 2001
+From: Antoni Boucher <bouanto@zoho.com>
+Date: Tue, 5 Mar 2024 12:39:44 -0500
+Subject: [PATCH] Remove #[deny(warnings)]
+
+---
+ src/lib.rs | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/src/lib.rs b/src/lib.rs
+index 8ade2881d5..e26c595e38 100644
+--- a/src/lib.rs
++++ b/src/lib.rs
+@@ -47,7 +47,6 @@
+ )]
+ #![deny(missing_docs)]
+ #![deny(missing_debug_implementations)]
+-#![doc(test(attr(allow(unused_variables), deny(warnings))))]
+ #![no_std]
+ #![cfg_attr(feature = "simd_support", feature(stdsimd, portable_simd))]
+ #![cfg_attr(doc_cfg, feature(doc_cfg))]
+-- 
+2.44.0
+
diff --git a/compiler/rustc_codegen_gcc/cross_patches/0001-Disable-libstd-and-libtest-dylib.patch b/compiler/rustc_codegen_gcc/patches/cross_patches/0001-Disable-libstd-and-libtest-dylib.patch
index 74d9c208a05..c220f53040f 100644
--- a/compiler/rustc_codegen_gcc/cross_patches/0001-Disable-libstd-and-libtest-dylib.patch
+++ b/compiler/rustc_codegen_gcc/patches/cross_patches/0001-Disable-libstd-and-libtest-dylib.patch
@@ -21,19 +21,3 @@ index 5b21355..cb0c49b 100644
  
  [dependencies]
  alloc = { path = "../alloc", public = true }
-diff --git a/library/test/Cargo.toml b/library/test/Cargo.toml
-index 91a1abd..a58c160 100644
---- a/library/test/Cargo.toml
-+++ b/library/test/Cargo.toml
-@@ -4,7 +4,7 @@ version = "0.0.0"
- edition = "2021"
- 
- [lib]
--crate-type = ["dylib", "rlib"]
-+crate-type = ["rlib"]
- 
- [dependencies]
- getopts = { version = "0.2.21", features = ['rustc-dep-of-std'] }
--- 
-2.42.0
-
diff --git a/compiler/rustc_codegen_gcc/rust-toolchain b/compiler/rustc_codegen_gcc/rust-toolchain
index 1962c217258..a0ac8286660 100644
--- a/compiler/rustc_codegen_gcc/rust-toolchain
+++ b/compiler/rustc_codegen_gcc/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2023-11-17"
+channel = "nightly-2024-03-05"
 components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
diff --git a/compiler/rustc_codegen_gcc/rustup.sh b/compiler/rustc_codegen_gcc/rustup.sh
deleted file mode 100755
index a4f938e4b5b..00000000000
--- a/compiler/rustc_codegen_gcc/rustup.sh
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/usr/bin/env bash
-
-set -e
-
-case $1 in
-    "prepare")
-        TOOLCHAIN=$(date +%Y-%m-%d)
-
-        echo "=> Installing new nightly"
-        rustup toolchain install --profile minimal nightly-${TOOLCHAIN} # Sanity check to see if the nightly exists
-        echo nightly-${TOOLCHAIN} > rust-toolchain
-
-        echo "=> Uninstalling all old nightlies"
-        for nightly in $(rustup toolchain list | grep nightly | grep -v $TOOLCHAIN | grep -v nightly-x86_64); do
-            rustup toolchain uninstall $nightly
-        done
-
-        ./clean_all.sh
-        ./y.sh prepare
-        ;;
-    "commit")
-        git add rust-toolchain
-        git commit -m "Rustup to $(rustc -V)"
-        ;;
-    *)
-        echo "Unknown command '$1'"
-        echo "Usage: ./rustup.sh prepare|commit"
-        ;;
-esac
diff --git a/compiler/rustc_codegen_gcc/src/abi.rs b/compiler/rustc_codegen_gcc/src/abi.rs
index f601cd95f2a..b098594dbcc 100644
--- a/compiler/rustc_codegen_gcc/src/abi.rs
+++ b/compiler/rustc_codegen_gcc/src/abi.rs
@@ -18,17 +18,16 @@ impl<'a, 'gcc, 'tcx> AbiBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
     fn get_param(&mut self, index: usize) -> Self::Value {
         let func = self.current_func();
         let param = func.get_param(index as i32);
-        let on_stack =
-            if let Some(on_stack_param_indices) = self.on_stack_function_params.borrow().get(&func) {
-                on_stack_param_indices.contains(&index)
-            }
-            else {
-                false
-            };
+        let on_stack = if let Some(on_stack_param_indices) =
+            self.on_stack_function_params.borrow().get(&func)
+        {
+            on_stack_param_indices.contains(&index)
+        } else {
+            false
+        };
         if on_stack {
             param.to_lvalue().get_address(None)
-        }
-        else {
+        } else {
             param.to_rvalue()
         }
     }
@@ -37,13 +36,14 @@ impl<'a, 'gcc, 'tcx> AbiBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
 impl GccType for CastTarget {
     fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, '_>) -> Type<'gcc> {
         let rest_gcc_unit = self.rest.unit.gcc_type(cx);
-        let (rest_count, rem_bytes) =
-            if self.rest.unit.size.bytes() == 0 {
-                (0, 0)
-            }
-            else {
-                (self.rest.total.bytes() / self.rest.unit.size.bytes(), self.rest.total.bytes() % self.rest.unit.size.bytes())
-            };
+        let (rest_count, rem_bytes) = if self.rest.unit.size.bytes() == 0 {
+            (0, 0)
+        } else {
+            (
+                self.rest.total.bytes() / self.rest.unit.size.bytes(),
+                self.rest.total.bytes() % self.rest.unit.size.bytes(),
+            )
+        };
 
         if self.prefix.iter().all(|x| x.is_none()) {
             // Simplify to a single unit when there is no prefix and size <= unit size
@@ -61,9 +61,7 @@ impl GccType for CastTarget {
         let mut args: Vec<_> = self
             .prefix
             .iter()
-            .flat_map(|option_reg| {
-                option_reg.map(|reg| reg.gcc_type(cx))
-            })
+            .flat_map(|option_reg| option_reg.map(|reg| reg.gcc_type(cx)))
             .chain((0..rest_count).map(|_| rest_gcc_unit))
             .collect();
 
@@ -86,12 +84,10 @@ impl GccType for Reg {
     fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, '_>) -> Type<'gcc> {
         match self.kind {
             RegKind::Integer => cx.type_ix(self.size.bits()),
-            RegKind::Float => {
-                match self.size.bits() {
-                    32 => cx.type_f32(),
-                    64 => cx.type_f64(),
-                    _ => bug!("unsupported float: {:?}", self),
-                }
+            RegKind::Float => match self.size.bits() {
+                32 => cx.type_f32(),
+                64 => cx.type_f64(),
+                _ => bug!("unsupported float: {:?}", self),
             },
             RegKind::Vector => unimplemented!(), //cx.type_vector(cx.type_i8(), self.size.bytes()),
         }
@@ -119,19 +115,18 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
 
         // This capacity calculation is approximate.
         let mut argument_tys = Vec::with_capacity(
-            self.args.len() + if let PassMode::Indirect { .. } = self.ret.mode { 1 } else { 0 }
+            self.args.len() + if let PassMode::Indirect { .. } = self.ret.mode { 1 } else { 0 },
         );
 
-        let return_type =
-            match self.ret.mode {
-                PassMode::Ignore => cx.type_void(),
-                PassMode::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_gcc_type(cx),
-                PassMode::Cast { ref cast, .. } => cast.gcc_type(cx),
-                PassMode::Indirect { .. } => {
-                    argument_tys.push(cx.type_ptr_to(self.ret.memory_ty(cx)));
-                    cx.type_void()
-                }
-            };
+        let return_type = match self.ret.mode {
+            PassMode::Ignore => cx.type_void(),
+            PassMode::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_gcc_type(cx),
+            PassMode::Cast { ref cast, .. } => cast.gcc_type(cx),
+            PassMode::Indirect { .. } => {
+                argument_tys.push(cx.type_ptr_to(self.ret.memory_ty(cx)));
+                cx.type_void()
+            }
+        };
         #[cfg(feature = "master")]
         let mut non_null_args = Vec::new();
 
@@ -149,17 +144,23 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
             ty
         };
         #[cfg(not(feature = "master"))]
-        let apply_attrs = |ty: Type<'gcc>, _attrs: &ArgAttributes, _arg_index: usize| {
-            ty
-        };
+        let apply_attrs = |ty: Type<'gcc>, _attrs: &ArgAttributes, _arg_index: usize| ty;
 
         for arg in self.args.iter() {
             let arg_ty = match arg.mode {
                 PassMode::Ignore => continue,
                 PassMode::Pair(a, b) => {
                     let arg_pos = argument_tys.len();
-                    argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 0), &a, arg_pos));
-                    argument_tys.push(apply_attrs(arg.layout.scalar_pair_element_gcc_type(cx, 1), &b, arg_pos + 1));
+                    argument_tys.push(apply_attrs(
+                        arg.layout.scalar_pair_element_gcc_type(cx, 0),
+                        &a,
+                        arg_pos,
+                    ));
+                    argument_tys.push(apply_attrs(
+                        arg.layout.scalar_pair_element_gcc_type(cx, 1),
+                        &b,
+                        arg_pos + 1,
+                    ));
                     continue;
                 }
                 PassMode::Cast { ref cast, pad_i32 } => {
@@ -174,14 +175,17 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
                     // This is a "byval" argument, so we don't apply the `restrict` attribute on it.
                     on_stack_param_indices.insert(argument_tys.len());
                     arg.memory_ty(cx)
-                },
-                PassMode::Direct(attrs) => apply_attrs(arg.layout.immediate_gcc_type(cx), &attrs, argument_tys.len()),
+                }
+                PassMode::Direct(attrs) => {
+                    apply_attrs(arg.layout.immediate_gcc_type(cx), &attrs, argument_tys.len())
+                }
                 PassMode::Indirect { attrs, meta_attrs: None, on_stack: false } => {
                     apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs, argument_tys.len())
                 }
                 PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack } => {
                     assert!(!on_stack);
-                    let ty = apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs, argument_tys.len());
+                    let ty =
+                        apply_attrs(cx.type_ptr_to(arg.memory_ty(cx)), &attrs, argument_tys.len());
                     apply_attrs(ty, &meta_attrs, argument_tys.len())
                 }
             };
@@ -207,15 +211,14 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
 
     fn ptr_to_gcc_type(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> {
         // FIXME(antoyo): Should we do something with `FnAbiGcc::fn_attributes`?
-        let FnAbiGcc {
-            return_type,
-            arguments_type,
-            is_c_variadic,
+        let FnAbiGcc { return_type, arguments_type, is_c_variadic, on_stack_param_indices, .. } =
+            self.gcc_type(cx);
+        let pointer_type =
+            cx.context.new_function_pointer_type(None, return_type, &arguments_type, is_c_variadic);
+        cx.on_stack_params.borrow_mut().insert(
+            pointer_type.dyncast_function_ptr_type().expect("function ptr type"),
             on_stack_param_indices,
-            ..
-        } = self.gcc_type(cx);
-        let pointer_type = cx.context.new_function_pointer_type(None, return_type, &arguments_type, is_c_variadic);
-        cx.on_stack_params.borrow_mut().insert(pointer_type.dyncast_function_ptr_type().expect("function ptr type"), on_stack_param_indices);
+        );
         pointer_type
     }
 }
diff --git a/compiler/rustc_codegen_gcc/src/allocator.rs b/compiler/rustc_codegen_gcc/src/allocator.rs
index 7c7044830f3..deeb55e9d12 100644
--- a/compiler/rustc_codegen_gcc/src/allocator.rs
+++ b/compiler/rustc_codegen_gcc/src/allocator.rs
@@ -1,4 +1,4 @@
-#[cfg(feature="master")]
+#[cfg(feature = "master")]
 use gccjit::FnAttribute;
 use gccjit::{Context, FunctionType, GlobalKind, ToRValue, Type};
 use rustc_ast::expand::allocator::{
@@ -11,15 +11,20 @@ use rustc_session::config::OomStrategy;
 
 use crate::GccContext;
 
-pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_name: &str, kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind) {
+pub(crate) unsafe fn codegen(
+    tcx: TyCtxt<'_>,
+    mods: &mut GccContext,
+    _module_name: &str,
+    kind: AllocatorKind,
+    alloc_error_handler_kind: AllocatorKind,
+) {
     let context = &mods.context;
-    let usize =
-        match tcx.sess.target.pointer_width {
-            16 => context.new_type::<u16>(),
-            32 => context.new_type::<u32>(),
-            64 => context.new_type::<u64>(),
-            tws => bug!("Unsupported target word size for int: {}", tws),
-        };
+    let usize = match tcx.sess.target.pointer_width {
+        16 => context.new_type::<u16>(),
+        32 => context.new_type::<u32>(),
+        64 => context.new_type::<u64>(),
+        tws => bug!("Unsupported target word size for int: {}", tws),
+    };
     let i8 = context.new_type::<i8>();
     let i8p = i8.make_pointer();
 
@@ -58,7 +63,7 @@ pub(crate) unsafe fn codegen(tcx: TyCtxt<'_>, mods: &mut GccContext, _module_nam
         tcx,
         context,
         "__rust_alloc_error_handler",
-        &alloc_error_handler_name(alloc_error_handler_kind),
+        alloc_error_handler_name(alloc_error_handler_kind),
         &[usize, usize],
         None,
     );
@@ -85,24 +90,42 @@ fn create_wrapper_function(
 ) {
     let void = context.new_type::<()>();
 
-    let args: Vec<_> = types.iter().enumerate()
-        .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
+    let args: Vec<_> = types
+        .iter()
+        .enumerate()
+        .map(|(index, typ)| context.new_parameter(None, *typ, format!("param{}", index)))
         .collect();
-    let func = context.new_function(None, FunctionType::Exported, output.unwrap_or(void), &args, from_name, false);
+    let func = context.new_function(
+        None,
+        FunctionType::Exported,
+        output.unwrap_or(void),
+        &args,
+        from_name,
+        false,
+    );
 
     if tcx.sess.default_hidden_visibility() {
-        #[cfg(feature="master")]
+        #[cfg(feature = "master")]
         func.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
     }
     if tcx.sess.must_emit_unwind_tables() {
         // TODO(antoyo): emit unwind tables.
     }
 
-    let args: Vec<_> = types.iter().enumerate()
-        .map(|(index, typ)| context.new_parameter(None, *typ, &format!("param{}", index)))
+    let args: Vec<_> = types
+        .iter()
+        .enumerate()
+        .map(|(index, typ)| context.new_parameter(None, *typ, format!("param{}", index)))
         .collect();
-    let callee = context.new_function(None, FunctionType::Extern, output.unwrap_or(void), &args, to_name, false);
-    #[cfg(feature="master")]
+    let callee = context.new_function(
+        None,
+        FunctionType::Extern,
+        output.unwrap_or(void),
+        &args,
+        to_name,
+        false,
+    );
+    #[cfg(feature = "master")]
     callee.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
 
     let block = func.new_block("entry");
@@ -116,8 +139,7 @@ fn create_wrapper_function(
     //llvm::LLVMSetTailCall(ret, True);
     if output.is_some() {
         block.end_with_return(None, ret);
-    }
-    else {
+    } else {
         block.end_with_void_return(None);
     }
 
diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs
index 07edd26e27a..9b679019e96 100644
--- a/compiler/rustc_codegen_gcc/src/asm.rs
+++ b/compiler/rustc_codegen_gcc/src/asm.rs
@@ -2,7 +2,10 @@ use gccjit::{LValue, RValue, ToRValue, Type};
 use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
 use rustc_codegen_ssa::mir::operand::OperandValue;
 use rustc_codegen_ssa::mir::place::PlaceRef;
-use rustc_codegen_ssa::traits::{AsmBuilderMethods, AsmMethods, BaseTypeMethods, BuilderMethods, GlobalAsmOperandRef, InlineAsmOperandRef};
+use rustc_codegen_ssa::traits::{
+    AsmBuilderMethods, AsmMethods, BaseTypeMethods, BuilderMethods, GlobalAsmOperandRef,
+    InlineAsmOperandRef,
+};
 
 use rustc_middle::{bug, ty::Instance};
 use rustc_span::Span;
@@ -11,11 +14,10 @@ use rustc_target::asm::*;
 use std::borrow::Cow;
 
 use crate::builder::Builder;
+use crate::callee::get_fn;
 use crate::context::CodegenCx;
 use crate::errors::UnwindingInlineAsm;
 use crate::type_of::LayoutGccExt;
-use crate::callee::get_fn;
-
 
 // Rust asm! and GCC Extended Asm semantics differ substantially.
 //
@@ -68,7 +70,6 @@ use crate::callee::get_fn;
 const ATT_SYNTAX_INS: &str = ".att_syntax noprefix\n\t";
 const INTEL_SYNTAX_INS: &str = "\n\t.intel_syntax noprefix";
 
-
 struct AsmOutOperand<'a, 'tcx, 'gcc> {
     rust_idx: usize,
     constraint: &'a str,
@@ -76,13 +77,13 @@ struct AsmOutOperand<'a, 'tcx, 'gcc> {
     readwrite: bool,
 
     tmp_var: LValue<'gcc>,
-    out_place: Option<PlaceRef<'tcx, RValue<'gcc>>>
+    out_place: Option<PlaceRef<'tcx, RValue<'gcc>>>,
 }
 
 struct AsmInOperand<'a, 'tcx> {
     rust_idx: usize,
     constraint: Cow<'a, str>,
-    val: RValue<'tcx>
+    val: RValue<'tcx>,
 }
 
 impl AsmOutOperand<'_, '_, '_> {
@@ -95,23 +96,29 @@ impl AsmOutOperand<'_, '_, '_> {
             res.push('&');
         }
 
-        res.push_str(&self.constraint);
+        res.push_str(self.constraint);
         res
     }
 }
 
 enum ConstraintOrRegister {
     Constraint(&'static str),
-    Register(&'static str)
+    Register(&'static str),
 }
 
-
 impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
-    fn codegen_inline_asm(&mut self, template: &[InlineAsmTemplatePiece], rust_operands: &[InlineAsmOperandRef<'tcx, Self>], options: InlineAsmOptions, span: &[Span], instance: Instance<'_>, dest: Option<Self::BasicBlock>, _catch_funclet: Option<(Self::BasicBlock, Option<&Self::Funclet>)>) {
+    fn codegen_inline_asm(
+        &mut self,
+        template: &[InlineAsmTemplatePiece],
+        rust_operands: &[InlineAsmOperandRef<'tcx, Self>],
+        options: InlineAsmOptions,
+        span: &[Span],
+        instance: Instance<'_>,
+        dest: Option<Self::BasicBlock>,
+        _catch_funclet: Option<(Self::BasicBlock, Option<&Self::Funclet>)>,
+    ) {
         if options.contains(InlineAsmOptions::MAY_UNWIND) {
-            self.sess().dcx()
-                .create_err(UnwindingInlineAsm { span: span[0] })
-                .emit();
+            self.sess().dcx().create_err(UnwindingInlineAsm { span: span[0] }).emit();
             return;
         }
 
@@ -161,32 +168,40 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
                     use ConstraintOrRegister::*;
 
                     let (constraint, ty) = match (reg_to_gcc(reg), place) {
-                        (Constraint(constraint), Some(place)) => (constraint, place.layout.gcc_type(self.cx)),
+                        (Constraint(constraint), Some(place)) => {
+                            (constraint, place.layout.gcc_type(self.cx))
+                        }
                         // When `reg` is a class and not an explicit register but the out place is not specified,
                         // we need to create an unused output variable to assign the output to. This var
                         // needs to be of a type that's "compatible" with the register class, but specific type
                         // doesn't matter.
-                        (Constraint(constraint), None) => (constraint, dummy_output_type(self.cx, reg.reg_class())),
+                        (Constraint(constraint), None) => {
+                            (constraint, dummy_output_type(self.cx, reg.reg_class()))
+                        }
                         (Register(_), Some(_)) => {
                             // left for the next pass
-                            continue
-                        },
+                            continue;
+                        }
                         (Register(reg_name), None) => {
                             // `clobber_abi` can add lots of clobbers that are not supported by the target,
                             // such as AVX-512 registers, so we just ignore unsupported registers
-                            let is_target_supported = reg.reg_class().supported_types(asm_arch).iter()
-                                .any(|&(_, feature)| {
-                                    if let Some(feature) = feature {
-                                        self.tcx.asm_target_features(instance.def_id()).contains(&feature)
-                                    } else {
-                                        true // Register class is unconditionally supported
-                                    }
-                                });
+                            let is_target_supported =
+                                reg.reg_class().supported_types(asm_arch).iter().any(
+                                    |&(_, feature)| {
+                                        if let Some(feature) = feature {
+                                            self.tcx
+                                                .asm_target_features(instance.def_id())
+                                                .contains(&feature)
+                                        } else {
+                                            true // Register class is unconditionally supported
+                                        }
+                                    },
+                                );
 
                             if is_target_supported && !clobbers.contains(&reg_name) {
                                 clobbers.push(reg_name);
                             }
-                            continue
+                            continue;
                         }
                     };
 
@@ -197,7 +212,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
                         late,
                         readwrite: false,
                         tmp_var,
-                        out_place: place
+                        out_place: place,
                     });
                 }
 
@@ -206,23 +221,22 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
                         inputs.push(AsmInOperand {
                             constraint: Cow::Borrowed(constraint),
                             rust_idx,
-                            val: value.immediate()
+                            val: value.immediate(),
                         });
-                    }
-                    else {
+                    } else {
                         // left for the next pass
-                        continue
+                        continue;
                     }
                 }
 
                 InlineAsmOperandRef::InOut { reg, late, in_value, out_place } => {
-                    let constraint = if let ConstraintOrRegister::Constraint(constraint) = reg_to_gcc(reg) {
-                        constraint
-                    }
-                    else {
-                        // left for the next pass
-                        continue
-                    };
+                    let constraint =
+                        if let ConstraintOrRegister::Constraint(constraint) = reg_to_gcc(reg) {
+                            constraint
+                        } else {
+                            // left for the next pass
+                            continue;
+                        };
 
                     // Rustc frontend guarantees that input and output types are "compatible",
                     // so we can just use input var's type for the output variable.
@@ -253,7 +267,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
                         inputs.push(AsmInOperand {
                             constraint,
                             rust_idx,
-                            val: in_value.immediate()
+                            val: in_value.immediate(),
                         });
                     }
                 }
@@ -271,7 +285,8 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
                 InlineAsmOperandRef::SymStatic { def_id } => {
                     // TODO(@Amanieu): Additional mangling is needed on
                     // some targets to add a leading underscore (Mach-O).
-                    constants_len += self.tcx.symbol_name(Instance::mono(self.tcx, def_id)).name.len();
+                    constants_len +=
+                        self.tcx.symbol_name(Instance::mono(self.tcx, def_id)).name.len();
                 }
 
                 InlineAsmOperandRef::Label { label } => {
@@ -288,10 +303,9 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
                     if let ConstraintOrRegister::Register(reg_name) = reg_to_gcc(reg) {
                         let out_place = if let Some(place) = place {
                             place
-                        }
-                        else {
+                        } else {
                             // processed in the previous pass
-                            continue
+                            continue;
                         };
 
                         let ty = out_place.layout.gcc_type(self.cx);
@@ -299,12 +313,12 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
                         tmp_var.set_register_name(reg_name);
 
                         outputs.push(AsmOutOperand {
-                            constraint: "r".into(),
+                            constraint: "r",
                             rust_idx,
                             late,
                             readwrite: false,
                             tmp_var,
-                            out_place: Some(out_place)
+                            out_place: Some(out_place),
                         });
                     }
 
@@ -322,7 +336,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
                         inputs.push(AsmInOperand {
                             constraint: "r".into(),
                             rust_idx,
-                            val: reg_var.to_rvalue()
+                            val: reg_var.to_rvalue(),
                         });
                     }
 
@@ -338,7 +352,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
                         tmp_var.set_register_name(reg_name);
 
                         outputs.push(AsmOutOperand {
-                            constraint: "r".into(),
+                            constraint: "r",
                             rust_idx,
                             late,
                             readwrite: false,
@@ -350,7 +364,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
                         inputs.push(AsmInOperand {
                             constraint,
                             rust_idx,
-                            val: in_value.immediate()
+                            val: in_value.immediate(),
                         });
                     }
 
@@ -385,7 +399,8 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
 
         // 3. Build the template string
 
-        let mut template_str = String::with_capacity(estimate_template_length(template, constants_len, att_dialect));
+        let mut template_str =
+            String::with_capacity(estimate_template_length(template, constants_len, att_dialect));
         if att_dialect {
             template_str.push_str(ATT_SYNTAX_INS);
         }
@@ -395,16 +410,15 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
                 InlineAsmTemplatePiece::String(ref string) => {
                     for char in string.chars() {
                         // TODO(antoyo): might also need to escape | if rustc doesn't do it.
-                        let escaped_char =
-                            match char {
-                                '%' => "%%",
-                                '{' => "%{",
-                                '}' => "%}",
-                                _ => {
-                                    template_str.push(char);
-                                    continue;
-                                },
-                            };
+                        let escaped_char = match char {
+                            '%' => "%%",
+                            '{' => "%{",
+                            '}' => "%}",
+                            _ => {
+                                template_str.push(char);
+                                continue;
+                            }
+                        };
                         template_str.push_str(escaped_char);
                     }
                 }
@@ -420,9 +434,10 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
                     };
 
                     match rust_operands[operand_idx] {
-                        InlineAsmOperandRef::Out { reg, ..  } => {
+                        InlineAsmOperandRef::Out { reg, .. } => {
                             let modifier = modifier_to_gcc(asm_arch, reg.reg_class(), modifier);
-                            let gcc_index = outputs.iter()
+                            let gcc_index = outputs
+                                .iter()
                                 .position(|op| operand_idx == op.rust_idx)
                                 .expect("wrong rust index");
                             push_to_template(modifier, gcc_index);
@@ -430,7 +445,8 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
 
                         InlineAsmOperandRef::In { reg, .. } => {
                             let modifier = modifier_to_gcc(asm_arch, reg.reg_class(), modifier);
-                            let in_gcc_index = inputs.iter()
+                            let in_gcc_index = inputs
+                                .iter()
                                 .position(|op| operand_idx == op.rust_idx)
                                 .expect("wrong rust index");
                             let gcc_index = in_gcc_index + outputs.len();
@@ -441,7 +457,8 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
                             let modifier = modifier_to_gcc(asm_arch, reg.reg_class(), modifier);
 
                             // The input register is tied to the output, so we can just use the index of the output register
-                            let gcc_index = outputs.iter()
+                            let gcc_index = outputs
+                                .iter()
                                 .position(|op| operand_idx == op.rust_idx)
                                 .expect("wrong rust index");
                             push_to_template(modifier, gcc_index);
@@ -521,7 +538,9 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
         }
         if dest.is_none() && options.contains(InlineAsmOptions::NORETURN) {
             let builtin_unreachable = self.context.get_builtin_function("__builtin_unreachable");
-            let builtin_unreachable: RValue<'gcc> = unsafe { std::mem::transmute(builtin_unreachable) };
+            let builtin_unreachable: RValue<'gcc> = unsafe {
+                std::mem::transmute(builtin_unreachable)
+            };
             self.call(self.type_void(), None, None, builtin_unreachable, &[], None);
         }
 
@@ -542,19 +561,23 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 }
 
-fn estimate_template_length(template: &[InlineAsmTemplatePiece], constants_len: usize, att_dialect: bool) -> usize {
-    let len: usize = template.iter().map(|piece| {
-        match *piece {
-            InlineAsmTemplatePiece::String(ref string) => {
-                string.len()
-            }
-            InlineAsmTemplatePiece::Placeholder { .. } => {
-                // '%' + 1 char modifier + 1 char index
-                3
+fn estimate_template_length(
+    template: &[InlineAsmTemplatePiece],
+    constants_len: usize,
+    att_dialect: bool,
+) -> usize {
+    let len: usize = template
+        .iter()
+        .map(|piece| {
+            match *piece {
+                InlineAsmTemplatePiece::String(ref string) => string.len(),
+                InlineAsmTemplatePiece::Placeholder { .. } => {
+                    // '%' + 1 char modifier + 1 char index
+                    3
+                }
             }
-        }
-    })
-    .sum();
+        })
+        .sum();
 
     // increase it by 5% to account for possible '%' signs that'll be duplicated
     // I pulled the number out of blue, but should be fair enough
@@ -587,7 +610,7 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
 
                 _ => unimplemented!(),
             }
-        },
+        }
         // They can be retrieved from https://gcc.gnu.org/onlinedocs/gcc/Machine-Constraints.html
         InlineAsmRegOrRegClass::RegClass(reg) => match reg {
             InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => "r",
@@ -635,7 +658,7 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
             InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
             | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
                 unreachable!("clobber-only")
-            },
+            }
             InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r",
             InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f",
             InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
@@ -662,7 +685,7 @@ fn reg_to_gcc(reg: InlineAsmRegOrRegClass) -> ConstraintOrRegister {
             InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg_addr) => "a",
             InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f",
             InlineAsmRegClass::Err => unreachable!(),
-        }
+        },
     };
 
     ConstraintOrRegister::Constraint(constraint)
@@ -678,7 +701,7 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
         | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => {
             unimplemented!()
         }
-        InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg)=> cx.type_i32(),
+        InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => cx.type_i32(),
         InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
         | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => cx.type_f32(),
         InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg)
@@ -711,7 +734,7 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
         InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
         | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
             unreachable!("clobber-only")
-        },
+        }
         InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(),
         InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => cx.type_f32(),
         InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => cx.type_f32(),
@@ -729,9 +752,9 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
         InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(),
         InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
             bug!("LLVM backend does not support SPIR-V")
-        },
+        }
         InlineAsmRegClass::S390x(
-            S390xInlineAsmRegClass::reg | S390xInlineAsmRegClass::reg_addr
+            S390xInlineAsmRegClass::reg | S390xInlineAsmRegClass::reg_addr,
         ) => cx.type_i32(),
         InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(),
         InlineAsmRegClass::Err => unreachable!(),
@@ -739,7 +762,13 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
 }
 
 impl<'gcc, 'tcx> AsmMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
-    fn codegen_global_asm(&self, template: &[InlineAsmTemplatePiece], operands: &[GlobalAsmOperandRef<'tcx>], options: InlineAsmOptions, _line_spans: &[Span]) {
+    fn codegen_global_asm(
+        &self,
+        template: &[InlineAsmTemplatePiece],
+        operands: &[GlobalAsmOperandRef<'tcx>],
+        options: InlineAsmOptions,
+        _line_spans: &[Span],
+    ) {
         let asm_arch = self.tcx.sess.asm_arch.unwrap();
 
         // Default to Intel syntax on x86
@@ -757,15 +786,17 @@ impl<'gcc, 'tcx> AsmMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
                     let mut index = 0;
                     while index < string.len() {
                         // NOTE: gcc does not allow inline comment, so remove them.
-                        let comment_index = string[index..].find("//")
+                        let comment_index = string[index..]
+                            .find("//")
                             .map(|comment_index| comment_index + index)
                             .unwrap_or(string.len());
                         template_str.push_str(&string[index..comment_index]);
-                        index = string[comment_index..].find('\n')
+                        index = string[comment_index..]
+                            .find('\n')
                             .map(|index| index + comment_index)
                             .unwrap_or(string.len());
                     }
-                },
+                }
                 InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: _ } => {
                     match operands[operand_idx] {
                         GlobalAsmOperandRef::Const { ref string } => {
@@ -807,14 +838,22 @@ impl<'gcc, 'tcx> AsmMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     }
 }
 
-fn modifier_to_gcc(arch: InlineAsmArch, reg: InlineAsmRegClass, modifier: Option<char>) -> Option<char> {
+fn modifier_to_gcc(
+    arch: InlineAsmArch,
+    reg: InlineAsmRegClass,
+    modifier: Option<char>,
+) -> Option<char> {
     // The modifiers can be retrieved from
     // https://gcc.gnu.org/onlinedocs/gcc/Modifiers.html#Modifiers
     match reg {
         InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => modifier,
         InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg)
         | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => {
-            if modifier == Some('v') { None } else { modifier }
+            if modifier == Some('v') {
+                None
+            } else {
+                modifier
+            }
         }
         InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
             unreachable!("clobber-only")
@@ -846,7 +885,13 @@ fn modifier_to_gcc(arch: InlineAsmArch, reg: InlineAsmRegClass, modifier: Option
         }
         InlineAsmRegClass::X86(X86InlineAsmRegClass::reg)
         | InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => match modifier {
-            None => if arch == InlineAsmArch::X86_64 { Some('q') } else { Some('k') },
+            None => {
+                if arch == InlineAsmArch::X86_64 {
+                    Some('q')
+                } else {
+                    Some('k')
+                }
+            }
             Some('l') => Some('b'),
             Some('h') => Some('h'),
             Some('x') => Some('w'),
diff --git a/compiler/rustc_codegen_gcc/src/attributes.rs b/compiler/rustc_codegen_gcc/src/attributes.rs
index 142f86b003d..8602566ab8f 100644
--- a/compiler/rustc_codegen_gcc/src/attributes.rs
+++ b/compiler/rustc_codegen_gcc/src/attributes.rs
@@ -1,21 +1,24 @@
-#[cfg(feature="master")]
+#[cfg(feature = "master")]
 use gccjit::FnAttribute;
 use gccjit::Function;
-use rustc_attr::InstructionSetAttr;
-#[cfg(feature="master")]
+#[cfg(feature = "master")]
 use rustc_attr::InlineAttr;
-use rustc_middle::ty;
-#[cfg(feature="master")]
+use rustc_attr::InstructionSetAttr;
+#[cfg(feature = "master")]
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
+use rustc_middle::ty;
 use rustc_span::symbol::sym;
 
-use crate::{context::CodegenCx, errors::TiedTargetFeatures};
 use crate::gcc_util::{check_tied_features, to_gcc_features};
+use crate::{context::CodegenCx, errors::TiedTargetFeatures};
 
 /// Get GCC attribute for the provided inline heuristic.
-#[cfg(feature="master")]
+#[cfg(feature = "master")]
 #[inline]
-fn inline_attr<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, inline: InlineAttr) -> Option<FnAttribute<'gcc>> {
+fn inline_attr<'gcc, 'tcx>(
+    cx: &CodegenCx<'gcc, 'tcx>,
+    inline: InlineAttr,
+) -> Option<FnAttribute<'gcc>> {
     match inline {
         InlineAttr::Hint => Some(FnAttribute::Inline),
         InlineAttr::Always => Some(FnAttribute::AlwaysInline),
@@ -34,24 +37,22 @@ fn inline_attr<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, inline: InlineAttr) -> Op
 /// attributes.
 pub fn from_fn_attrs<'gcc, 'tcx>(
     cx: &CodegenCx<'gcc, 'tcx>,
-    #[cfg_attr(not(feature="master"), allow(unused_variables))]
-    func: Function<'gcc>,
+    #[cfg_attr(not(feature = "master"), allow(unused_variables))] func: Function<'gcc>,
     instance: ty::Instance<'tcx>,
 ) {
     let codegen_fn_attrs = cx.tcx.codegen_fn_attrs(instance.def_id());
 
-    #[cfg(feature="master")]
+    #[cfg(feature = "master")]
     {
-        let inline =
-            if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
-                InlineAttr::Never
-            }
-            else if codegen_fn_attrs.inline == InlineAttr::None && instance.def.requires_inline(cx.tcx) {
-                InlineAttr::Hint
-            }
-            else {
-                codegen_fn_attrs.inline
-            };
+        let inline = if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
+            InlineAttr::Never
+        } else if codegen_fn_attrs.inline == InlineAttr::None
+            && instance.def.requires_inline(cx.tcx)
+        {
+            InlineAttr::Hint
+        } else {
+            codegen_fn_attrs.inline
+        };
         if let Some(attr) = inline_attr(cx, inline) {
             if let FnAttribute::AlwaysInline = attr {
                 func.add_attribute(FnAttribute::Inline);
@@ -70,18 +71,21 @@ pub fn from_fn_attrs<'gcc, 'tcx>(
         }
     }
 
-    let function_features =
-        codegen_fn_attrs.target_features.iter().map(|features| features.as_str()).collect::<Vec<&str>>();
+    let function_features = codegen_fn_attrs
+        .target_features
+        .iter()
+        .map(|features| features.as_str())
+        .collect::<Vec<&str>>();
 
-    if let Some(features) = check_tied_features(cx.tcx.sess, &function_features.iter().map(|features| (*features, true)).collect()) {
-        let span = cx.tcx
+    if let Some(features) = check_tied_features(
+        cx.tcx.sess,
+        &function_features.iter().map(|features| (*features, true)).collect(),
+    ) {
+        let span = cx
+            .tcx
             .get_attr(instance.def_id(), sym::target_feature)
             .map_or_else(|| cx.tcx.def_span(instance.def_id()), |a| a.span);
-        cx.tcx.dcx().create_err(TiedTargetFeatures {
-            features: features.join(", "),
-            span,
-        })
-            .emit();
+        cx.tcx.dcx().create_err(TiedTargetFeatures { features: features.join(", "), span }).emit();
         return;
     }
 
@@ -105,24 +109,25 @@ pub fn from_fn_attrs<'gcc, 'tcx>(
             // compiling Rust for Linux:
             // SSE register return with SSE disabled
             // TODO(antoyo): support soft-float and retpoline-external-thunk.
-            if feature.contains("soft-float") || feature.contains("retpoline-external-thunk") || *feature == "-sse" {
+            if feature.contains("soft-float")
+                || feature.contains("retpoline-external-thunk")
+                || *feature == "-sse"
+            {
                 return None;
             }
 
             if feature.starts_with('-') {
                 Some(format!("no{}", feature))
-            }
-            else if feature.starts_with('+') {
+            } else if feature.starts_with('+') {
                 Some(feature[1..].to_string())
-            }
-            else {
+            } else {
                 Some(feature.to_string())
             }
         })
         .collect::<Vec<_>>()
         .join(",");
     if !target_features.is_empty() {
-        #[cfg(feature="master")]
+        #[cfg(feature = "master")]
         func.add_attribute(FnAttribute::Target(&target_features));
     }
 }
diff --git a/compiler/rustc_codegen_gcc/src/back/lto.rs b/compiler/rustc_codegen_gcc/src/back/lto.rs
index c21b7686823..61e0f203ee0 100644
--- a/compiler/rustc_codegen_gcc/src/back/lto.rs
+++ b/compiler/rustc_codegen_gcc/src/back/lto.rs
@@ -1,7 +1,6 @@
 /// GCC requires to use the same toolchain for the whole compilation when doing LTO.
 /// So, we need the same version/commit of the linker (gcc) and lto front-end binaries (lto1,
 /// lto-wrapper, liblto_plugin.so).
-
 // FIXME(antoyo): the executables compiled with LTO are bigger than those compiled without LTO.
 // Since it is the opposite for cg_llvm, check if this is normal.
 //
@@ -17,7 +16,6 @@
 // /usr/bin/ld: warning: type of symbol `_RNvNvNvNtCs5JWOrf9uCus_5rayon11thread_pool19WORKER_THREAD_STATE7___getit5___KEY' changed from 1 to 6 in /tmp/ccKeUSiR.ltrans0.ltrans.o
 // /usr/bin/ld: warning: type of symbol `_RNvNvNvNvNtNtNtCsAj5i4SGTR7_3std4sync4mpmc5waker17current_thread_id5DUMMY7___getit5___KEY' changed from 1 to 6 in /tmp/ccKeUSiR.ltrans0.ltrans.o
 // /usr/bin/ld: warning: incremental linking of LTO and non-LTO objects; using -flinker-output=nolto-rel which will bypass whole program optimization
-
 use std::ffi::CString;
 use std::fs::{self, File};
 use std::path::{Path, PathBuf};
@@ -30,18 +28,16 @@ use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput};
 use rustc_codegen_ssa::traits::*;
 use rustc_codegen_ssa::{looks_like_rust_object_file, ModuleCodegen, ModuleKind};
 use rustc_data_structures::memmap::Mmap;
-use rustc_errors::{FatalError, DiagCtxt};
+use rustc_errors::{DiagCtxt, FatalError};
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_middle::dep_graph::WorkProduct;
 use rustc_middle::middle::exported_symbols::{SymbolExportInfo, SymbolExportLevel};
 use rustc_session::config::{CrateType, Lto};
-use tempfile::{TempDir, tempdir};
+use tempfile::{tempdir, TempDir};
 
 use crate::back::write::save_temp_bitcode;
-use crate::errors::{
-    DynamicLinkingWithLTO, LtoBitcodeFromRlib, LtoDisallowed, LtoDylib,
-};
-use crate::{GccCodegenBackend, GccContext, to_gcc_opt_level};
+use crate::errors::{DynamicLinkingWithLTO, LtoBitcodeFromRlib, LtoDisallowed, LtoDylib};
+use crate::{to_gcc_opt_level, GccCodegenBackend, GccContext};
 
 /// We keep track of the computed LTO cache keys from the previous
 /// session to determine which CGUs we can reuse.
@@ -61,7 +57,10 @@ struct LtoData {
     tmp_path: TempDir,
 }
 
-fn prepare_lto(cgcx: &CodegenContext<GccCodegenBackend>, dcx: &DiagCtxt) -> Result<LtoData, FatalError> {
+fn prepare_lto(
+    cgcx: &CodegenContext<GccCodegenBackend>,
+    dcx: &DiagCtxt,
+) -> Result<LtoData, FatalError> {
     let export_threshold = match cgcx.lto {
         // We're just doing LTO for our one crate
         Lto::ThinLocal => SymbolExportLevel::Rust,
@@ -72,14 +71,13 @@ fn prepare_lto(cgcx: &CodegenContext<GccCodegenBackend>, dcx: &DiagCtxt) -> Resu
         Lto::No => panic!("didn't request LTO but we're doing LTO"),
     };
 
-    let tmp_path =
-        match tempdir() {
-            Ok(tmp_path) => tmp_path,
-            Err(error) => {
-                eprintln!("Cannot create temporary directory: {}", error);
-                return Err(FatalError);
-            },
-        };
+    let tmp_path = match tempdir() {
+        Ok(tmp_path) => tmp_path,
+        Err(error) => {
+            eprintln!("Cannot create temporary directory: {}", error);
+            return Err(FatalError);
+        }
+    };
 
     let symbol_filter = &|&(ref name, info): &(String, SymbolExportInfo)| {
         if info.level.is_below_threshold(export_threshold) || info.used {
@@ -108,11 +106,10 @@ fn prepare_lto(cgcx: &CodegenContext<GccCodegenBackend>, dcx: &DiagCtxt) -> Resu
             if !crate_type_allows_lto(*crate_type) {
                 dcx.emit_err(LtoDisallowed);
                 return Err(FatalError);
-            } else if *crate_type == CrateType::Dylib {
-                if !cgcx.opts.unstable_opts.dylib_lto {
-                    dcx.emit_err(LtoDylib);
-                    return Err(FatalError);
-                }
+            }
+            if *crate_type == CrateType::Dylib && !cgcx.opts.unstable_opts.dylib_lto {
+                dcx.emit_err(LtoDylib);
+                return Err(FatalError);
             }
         }
 
@@ -125,8 +122,7 @@ fn prepare_lto(cgcx: &CodegenContext<GccCodegenBackend>, dcx: &DiagCtxt) -> Resu
             let exported_symbols =
                 cgcx.exported_symbols.as_ref().expect("needs exported symbols for LTO");
             {
-                let _timer =
-                    cgcx.prof.generic_activity("GCC_lto_generate_symbols_below_threshold");
+                let _timer = cgcx.prof.generic_activity("GCC_lto_generate_symbols_below_threshold");
                 symbols_below_threshold
                     .extend(exported_symbols[&cnum].iter().filter_map(symbol_filter));
             }
@@ -170,10 +166,9 @@ fn prepare_lto(cgcx: &CodegenContext<GccCodegenBackend>, dcx: &DiagCtxt) -> Resu
 }
 
 fn save_as_file(obj: &[u8], path: &Path) -> Result<(), LtoBitcodeFromRlib> {
-    fs::write(path, obj)
-        .map_err(|error| LtoBitcodeFromRlib {
-            gcc_err: format!("write object file to temp dir: {}", error)
-        })
+    fs::write(path, obj).map_err(|error| LtoBitcodeFromRlib {
+        gcc_err: format!("write object file to temp dir: {}", error),
+    })
 }
 
 /// Performs fat LTO by merging all modules into a single one and returning it
@@ -186,13 +181,25 @@ pub(crate) fn run_fat(
     let dcx = cgcx.create_dcx();
     let lto_data = prepare_lto(cgcx, &dcx)?;
     /*let symbols_below_threshold =
-        lto_data.symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::<Vec<_>>();*/
-    fat_lto(cgcx, &dcx, modules, cached_modules, lto_data.upstream_modules, lto_data.tmp_path,
+    lto_data.symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::<Vec<_>>();*/
+    fat_lto(
+        cgcx,
+        &dcx,
+        modules,
+        cached_modules,
+        lto_data.upstream_modules,
+        lto_data.tmp_path,
         //&symbols_below_threshold,
     )
 }
 
-fn fat_lto(cgcx: &CodegenContext<GccCodegenBackend>, _dcx: &DiagCtxt, modules: Vec<FatLtoInput<GccCodegenBackend>>, cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>, mut serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>, tmp_path: TempDir,
+fn fat_lto(
+    cgcx: &CodegenContext<GccCodegenBackend>,
+    _dcx: &DiagCtxt,
+    modules: Vec<FatLtoInput<GccCodegenBackend>>,
+    cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
+    mut serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
+    tmp_path: TempDir,
     //symbols_below_threshold: &[*const libc::c_char],
 ) -> Result<LtoModuleCodegen<GccCodegenBackend>, FatalError> {
     let _timer = cgcx.prof.generic_activity("GCC_fat_lto_build_monolithic_module");
@@ -298,10 +305,15 @@ fn fat_lto(cgcx: &CodegenContext<GccCodegenBackend>, _dcx: &DiagCtxt, modules: V
             match bc_decoded {
                 SerializedModule::Local(ref module_buffer) => {
                     module.module_llvm.should_combine_object_files = true;
-                    module.module_llvm.context.add_driver_option(module_buffer.0.to_str().expect("path"));
-                },
+                    module
+                        .module_llvm
+                        .context
+                        .add_driver_option(module_buffer.0.to_str().expect("path"));
+                }
                 SerializedModule::FromRlib(_) => unimplemented!("from rlib"),
-                SerializedModule::FromUncompressedFile(_) => unimplemented!("from uncompressed file"),
+                SerializedModule::FromUncompressedFile(_) => {
+                    unimplemented!("from uncompressed file")
+                }
             }
             serialized_bitcode.push(bc_decoded);
         }
@@ -309,13 +321,13 @@ fn fat_lto(cgcx: &CodegenContext<GccCodegenBackend>, _dcx: &DiagCtxt, modules: V
 
         // Internalize everything below threshold to help strip out more modules and such.
         /*unsafe {
-            let ptr = symbols_below_threshold.as_ptr();
-            llvm::LLVMRustRunRestrictionPass(
-                llmod,
-                ptr as *const *const libc::c_char,
-                symbols_below_threshold.len() as libc::size_t,
-            );*/
-            save_temp_bitcode(cgcx, &module, "lto.after-restriction");
+        let ptr = symbols_below_threshold.as_ptr();
+        llvm::LLVMRustRunRestrictionPass(
+            llmod,
+            ptr as *const *const libc::c_char,
+            symbols_below_threshold.len() as libc::size_t,
+        );*/
+        save_temp_bitcode(cgcx, &module, "lto.after-restriction");
         //}
     }
 
diff --git a/compiler/rustc_codegen_gcc/src/back/write.rs b/compiler/rustc_codegen_gcc/src/back/write.rs
index 2f8a54f529c..76a619a1af7 100644
--- a/compiler/rustc_codegen_gcc/src/back/write.rs
+++ b/compiler/rustc_codegen_gcc/src/back/write.rs
@@ -1,19 +1,24 @@
 use std::{env, fs};
 
 use gccjit::OutputKind;
-use rustc_codegen_ssa::{CompiledModule, ModuleCodegen};
 use rustc_codegen_ssa::back::link::ensure_removed;
 use rustc_codegen_ssa::back::write::{BitcodeSection, CodegenContext, EmitObj, ModuleConfig};
+use rustc_codegen_ssa::{CompiledModule, ModuleCodegen};
 use rustc_errors::DiagCtxt;
 use rustc_fs_util::link_or_copy;
 use rustc_session::config::OutputType;
 use rustc_span::fatal_error::FatalError;
 use rustc_target::spec::SplitDebuginfo;
 
-use crate::{GccCodegenBackend, GccContext};
 use crate::errors::CopyBitcode;
+use crate::{GccCodegenBackend, GccContext};
 
-pub(crate) unsafe fn codegen(cgcx: &CodegenContext<GccCodegenBackend>, dcx: &DiagCtxt, module: ModuleCodegen<GccContext>, config: &ModuleConfig) -> Result<CompiledModule, FatalError> {
+pub(crate) unsafe fn codegen(
+    cgcx: &CodegenContext<GccCodegenBackend>,
+    dcx: &DiagCtxt,
+    module: ModuleCodegen<GccContext>,
+    config: &ModuleConfig,
+) -> Result<CompiledModule, FatalError> {
     let _timer = cgcx.prof.generic_activity_with_arg("GCC_module_codegen", &*module.name);
     {
         let context = &module.module_llvm.context;
@@ -51,7 +56,8 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<GccCodegenBackend>, dcx: &Dia
                     .generic_activity_with_arg("GCC_module_codegen_emit_bitcode", &*module.name);
                 context.add_command_line_option("-flto=auto");
                 context.add_command_line_option("-flto-partition=one");
-                context.compile_to_file(OutputKind::ObjectFile, bc_out.to_str().expect("path to str"));
+                context
+                    .compile_to_file(OutputKind::ObjectFile, bc_out.to_str().expect("path to str"));
             }
 
             if config.emit_obj == EmitObj::ObjectCode(BitcodeSection::Full) {
@@ -65,18 +71,19 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<GccCodegenBackend>, dcx: &Dia
                 context.add_command_line_option("-flto-partition=one");
                 context.add_command_line_option("-ffat-lto-objects");
                 // TODO(antoyo): Send -plugin/usr/lib/gcc/x86_64-pc-linux-gnu/11.1.0/liblto_plugin.so to linker (this should be done when specifying the appropriate rustc cli argument).
-                context.compile_to_file(OutputKind::ObjectFile, bc_out.to_str().expect("path to str"));
+                context
+                    .compile_to_file(OutputKind::ObjectFile, bc_out.to_str().expect("path to str"));
             }
         }
 
         if config.emit_ir {
-            unimplemented!();
+            let out = cgcx.output_filenames.temp_path(OutputType::LlvmAssembly, module_name);
+            std::fs::write(out, "").expect("write file");
         }
 
         if config.emit_asm {
-            let _timer = cgcx
-                .prof
-                .generic_activity_with_arg("GCC_module_codegen_emit_asm", &*module.name);
+            let _timer =
+                cgcx.prof.generic_activity_with_arg("GCC_module_codegen_emit_asm", &*module.name);
             let path = cgcx.output_filenames.temp_path(OutputType::Assembly, module_name);
             context.compile_to_file(OutputKind::Assembler, path.to_str().expect("path to str"));
         }
@@ -89,7 +96,9 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<GccCodegenBackend>, dcx: &Dia
                 if env::var("CG_GCCJIT_DUMP_MODULE_NAMES").as_deref() == Ok("1") {
                     println!("Module {}", module.name);
                 }
-                if env::var("CG_GCCJIT_DUMP_ALL_MODULES").as_deref() == Ok("1") || env::var("CG_GCCJIT_DUMP_MODULE").as_deref() == Ok(&module.name) {
+                if env::var("CG_GCCJIT_DUMP_ALL_MODULES").as_deref() == Ok("1")
+                    || env::var("CG_GCCJIT_DUMP_MODULE").as_deref() == Ok(&module.name)
+                {
                     println!("Dumping reproducer {}", module.name);
                     let _ = fs::create_dir("/tmp/reproducers");
                     // FIXME(antoyo): segfault in dump_reproducer_to_file() might be caused by
@@ -117,10 +126,15 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<GccCodegenBackend>, dcx: &Dia
                     context.add_driver_option("-fuse-linker-plugin");
 
                     // NOTE: this doesn't actually generate an executable. With the above flags, it combines the .o files together in another .o.
-                    context.compile_to_file(OutputKind::Executable, obj_out.to_str().expect("path to str"));
-                }
-                else {
-                    context.compile_to_file(OutputKind::ObjectFile, obj_out.to_str().expect("path to str"));
+                    context.compile_to_file(
+                        OutputKind::Executable,
+                        obj_out.to_str().expect("path to str"),
+                    );
+                } else {
+                    context.compile_to_file(
+                        OutputKind::ObjectFile,
+                        obj_out.to_str().expect("path to str"),
+                    );
                 }
             }
 
@@ -148,11 +162,19 @@ pub(crate) unsafe fn codegen(cgcx: &CodegenContext<GccCodegenBackend>, dcx: &Dia
     ))
 }
 
-pub(crate) fn link(_cgcx: &CodegenContext<GccCodegenBackend>, _dcx: &DiagCtxt, mut _modules: Vec<ModuleCodegen<GccContext>>) -> Result<ModuleCodegen<GccContext>, FatalError> {
+pub(crate) fn link(
+    _cgcx: &CodegenContext<GccCodegenBackend>,
+    _dcx: &DiagCtxt,
+    mut _modules: Vec<ModuleCodegen<GccContext>>,
+) -> Result<ModuleCodegen<GccContext>, FatalError> {
     unimplemented!();
 }
 
-pub(crate) fn save_temp_bitcode(cgcx: &CodegenContext<GccCodegenBackend>, _module: &ModuleCodegen<GccContext>, _name: &str) {
+pub(crate) fn save_temp_bitcode(
+    cgcx: &CodegenContext<GccCodegenBackend>,
+    _module: &ModuleCodegen<GccContext>,
+    _name: &str,
+) {
     if !cgcx.save_temps {
         return;
     }
diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs
index b0788718da4..2a2d5741d13 100644
--- a/compiler/rustc_codegen_gcc/src/base.rs
+++ b/compiler/rustc_codegen_gcc/src/base.rs
@@ -2,29 +2,26 @@ use std::collections::HashSet;
 use std::env;
 use std::time::Instant;
 
-use gccjit::{
-    FunctionType,
-    GlobalKind,
-};
-use rustc_middle::dep_graph;
-use rustc_middle::ty::TyCtxt;
-#[cfg(feature="master")]
-use rustc_middle::mir::mono::Visibility;
-use rustc_middle::mir::mono::Linkage;
-use rustc_codegen_ssa::{ModuleCodegen, ModuleKind};
+use gccjit::{FunctionType, GlobalKind};
 use rustc_codegen_ssa::base::maybe_create_entry_wrapper;
 use rustc_codegen_ssa::mono_item::MonoItemExt;
 use rustc_codegen_ssa::traits::DebugInfoMethods;
+use rustc_codegen_ssa::{ModuleCodegen, ModuleKind};
+use rustc_middle::dep_graph;
+use rustc_middle::mir::mono::Linkage;
+#[cfg(feature = "master")]
+use rustc_middle::mir::mono::Visibility;
+use rustc_middle::ty::TyCtxt;
 use rustc_session::config::DebugInfo;
 use rustc_span::Symbol;
 use rustc_target::spec::PanicStrategy;
 
-use crate::{LockedTargetInfo, gcc_util, new_context};
-use crate::GccContext;
 use crate::builder::Builder;
 use crate::context::CodegenCx;
+use crate::GccContext;
+use crate::{gcc_util, new_context, LockedTargetInfo};
 
-#[cfg(feature="master")]
+#[cfg(feature = "master")]
 pub fn visibility_to_gcc(linkage: Visibility) -> gccjit::Visibility {
     match linkage {
         Visibility::Default => gccjit::Visibility::Default,
@@ -66,7 +63,11 @@ pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType {
     }
 }
 
-pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: LockedTargetInfo) -> (ModuleCodegen<GccContext>, u64) {
+pub fn compile_codegen_unit(
+    tcx: TyCtxt<'_>,
+    cgu_name: Symbol,
+    target_info: LockedTargetInfo,
+) -> (ModuleCodegen<GccContext>, u64) {
     let prof_timer = tcx.prof.generic_activity("codegen_module");
     let start_time = Instant::now();
 
@@ -85,7 +86,10 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Lock
     // the time we needed for codegenning it.
     let cost = time_to_codegen.as_secs() * 1_000_000_000 + time_to_codegen.subsec_nanos() as u64;
 
-    fn module_codegen(tcx: TyCtxt<'_>, (cgu_name, target_info): (Symbol, LockedTargetInfo)) -> ModuleCodegen<GccContext> {
+    fn module_codegen(
+        tcx: TyCtxt<'_>,
+        (cgu_name, target_info): (Symbol, LockedTargetInfo),
+    ) -> ModuleCodegen<GccContext> {
         let cgu = tcx.codegen_unit(cgu_name);
         // Instantiate monomorphizations without filling out definitions yet...
         let context = new_context(tcx);
@@ -95,7 +99,12 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Lock
             context.add_driver_option("-fexceptions");
         }
 
-        let disabled_features: HashSet<_> = tcx.sess.opts.cg.target_feature.split(',')
+        let disabled_features: HashSet<_> = tcx
+            .sess
+            .opts
+            .cg
+            .target_feature
+            .split(',')
             .filter(|feature| feature.starts_with('-'))
             .map(|string| &string[1..])
             .collect();
@@ -129,7 +138,13 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Lock
             context.add_command_line_option(&format!("-march={}", target_cpu));
         }
 
-        if tcx.sess.opts.unstable_opts.function_sections.unwrap_or(tcx.sess.target.function_sections) {
+        if tcx
+            .sess
+            .opts
+            .unstable_opts
+            .function_sections
+            .unwrap_or(tcx.sess.target.function_sections)
+        {
             context.add_command_line_option("-ffunction-sections");
             context.add_command_line_option("-fdata-sections");
         }
@@ -152,19 +167,17 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Lock
         if env::var("CG_GCCJIT_DUMP_GIMPLE").as_deref() == Ok("1") {
             context.set_dump_initial_gimple(true);
         }
-        context.set_debug_info(true);
         if env::var("CG_GCCJIT_DUMP_EVERYTHING").as_deref() == Ok("1") {
             context.set_dump_everything(true);
         }
         if env::var("CG_GCCJIT_KEEP_INTERMEDIATES").as_deref() == Ok("1") {
             context.set_keep_intermediates(true);
         }
-
         if env::var("CG_GCCJIT_VERBOSE").as_deref() == Ok("1") {
             context.add_driver_option("-v");
         }
 
-        // NOTE: The codegen generates unrechable blocks.
+        // NOTE: The codegen generates unreachable blocks.
         context.set_allow_unreachable_blocks(true);
 
         {
@@ -192,11 +205,7 @@ pub fn compile_codegen_unit(tcx: TyCtxt<'_>, cgu_name: Symbol, target_info: Lock
 
         ModuleCodegen {
             name: cgu_name.to_string(),
-            module_llvm: GccContext {
-                context,
-                should_combine_object_files: false,
-                temp_dir: None,
-            },
+            module_llvm: GccContext { context, should_combine_object_files: false, temp_dir: None },
             kind: ModuleKind::Regular,
         }
     }
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index 71a0a4c2e96..f5cda81f6ab 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -4,53 +4,36 @@ use std::convert::TryFrom;
 use std::ops::Deref;
 
 use gccjit::{
-    BinaryOp,
-    Block,
-    ComparisonOp,
-    Context,
-    Function,
-    LValue,
-    RValue,
-    ToRValue,
-    Type,
+    BinaryOp, Block, ComparisonOp, Context, Function, LValue, Location, RValue, ToRValue, Type,
     UnaryOp,
 };
 use rustc_apfloat::{ieee, Float, Round, Status};
-use rustc_codegen_ssa::MemFlags;
 use rustc_codegen_ssa::common::{
     AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope, TypeKind,
 };
 use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
 use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::traits::{
-    BackendTypes,
-    BaseTypeMethods,
-    BuilderMethods,
-    ConstMethods,
-    LayoutTypeMethods,
-    HasCodegen,
-    OverflowOp,
-    StaticBuilderMethods,
+    BackendTypes, BaseTypeMethods, BuilderMethods, ConstMethods, HasCodegen, LayoutTypeMethods,
+    OverflowOp, StaticBuilderMethods,
 };
+use rustc_codegen_ssa::MemFlags;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::bug;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
+use rustc_middle::ty::layout::{
+    FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers,
+    TyAndLayout,
+};
 use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
-use rustc_middle::ty::layout::{FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout};
-use rustc_span::Span;
 use rustc_span::def_id::DefId;
+use rustc_span::Span;
 use rustc_target::abi::{
-    self,
-    call::FnAbi,
-    Align,
-    HasDataLayout,
-    Size,
-    TargetDataLayout,
-    WrappingRange,
+    self, call::FnAbi, Align, HasDataLayout, Size, TargetDataLayout, WrappingRange,
 };
 use rustc_target::spec::{HasTargetSpec, Target};
 
-use crate::common::{SignType, TypeReflection, type_is_pointer};
+use crate::common::{type_is_pointer, SignType, TypeReflection};
 use crate::context::CodegenCx;
 use crate::intrinsic::llvm;
 use crate::type_of::LayoutGccExt;
@@ -70,54 +53,74 @@ pub struct Builder<'a: 'gcc, 'gcc, 'tcx> {
     pub cx: &'a CodegenCx<'gcc, 'tcx>,
     pub block: Block<'gcc>,
     stack_var_count: Cell<usize>,
+    pub location: Option<Location<'gcc>>,
 }
 
 impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
     fn with_cx(cx: &'a CodegenCx<'gcc, 'tcx>, block: Block<'gcc>) -> Self {
-        Builder {
-            cx,
-            block,
-            stack_var_count: Cell::new(0),
-        }
+        Builder { cx, block, stack_var_count: Cell::new(0), location: None }
     }
 
-    fn atomic_extremum(&mut self, operation: ExtremumOperation, dst: RValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering) -> RValue<'gcc> {
+    fn atomic_extremum(
+        &mut self,
+        operation: ExtremumOperation,
+        dst: RValue<'gcc>,
+        src: RValue<'gcc>,
+        order: AtomicOrdering,
+    ) -> RValue<'gcc> {
         let size = src.get_type().get_size();
 
         let func = self.current_func();
 
-        let load_ordering =
-            match order {
-                // TODO(antoyo): does this make sense?
-                AtomicOrdering::AcquireRelease | AtomicOrdering::Release => AtomicOrdering::Acquire,
-                _ => order,
-            };
-        let previous_value = self.atomic_load(dst.get_type(), dst, load_ordering, Size::from_bytes(size));
-        let previous_var = func.new_local(None, previous_value.get_type(), "previous_value");
-        let return_value = func.new_local(None, previous_value.get_type(), "return_value");
-        self.llbb().add_assignment(None, previous_var, previous_value);
-        self.llbb().add_assignment(None, return_value, previous_var.to_rvalue());
+        let load_ordering = match order {
+            // TODO(antoyo): does this make sense?
+            AtomicOrdering::AcquireRelease | AtomicOrdering::Release => AtomicOrdering::Acquire,
+            _ => order,
+        };
+        let previous_value =
+            self.atomic_load(dst.get_type(), dst, load_ordering, Size::from_bytes(size));
+        let previous_var =
+            func.new_local(self.location, previous_value.get_type(), "previous_value");
+        let return_value = func.new_local(self.location, previous_value.get_type(), "return_value");
+        self.llbb().add_assignment(self.location, previous_var, previous_value);
+        self.llbb().add_assignment(self.location, return_value, previous_var.to_rvalue());
 
         let while_block = func.new_block("while");
         let after_block = func.new_block("after_while");
-        self.llbb().end_with_jump(None, while_block);
+        self.llbb().end_with_jump(self.location, while_block);
 
         // NOTE: since jumps were added and compare_exchange doesn't expect this, the current block in the
         // state need to be updated.
         self.switch_to_block(while_block);
 
-        let comparison_operator =
-            match operation {
-                ExtremumOperation::Max => ComparisonOp::LessThan,
-                ExtremumOperation::Min => ComparisonOp::GreaterThan,
-            };
-
-        let cond1 = self.context.new_comparison(None, comparison_operator, previous_var.to_rvalue(), self.context.new_cast(None, src, previous_value.get_type()));
-        let compare_exchange = self.compare_exchange(dst, previous_var, src, order, load_ordering, false);
-        let cond2 = self.cx.context.new_unary_op(None, UnaryOp::LogicalNegate, compare_exchange.get_type(), compare_exchange);
-        let cond = self.cx.context.new_binary_op(None, BinaryOp::LogicalAnd, self.cx.bool_type, cond1, cond2);
+        let comparison_operator = match operation {
+            ExtremumOperation::Max => ComparisonOp::LessThan,
+            ExtremumOperation::Min => ComparisonOp::GreaterThan,
+        };
 
-        while_block.end_with_conditional(None, cond, while_block, after_block);
+        let cond1 = self.context.new_comparison(
+            self.location,
+            comparison_operator,
+            previous_var.to_rvalue(),
+            self.context.new_cast(self.location, src, previous_value.get_type()),
+        );
+        let compare_exchange =
+            self.compare_exchange(dst, previous_var, src, order, load_ordering, false);
+        let cond2 = self.cx.context.new_unary_op(
+            self.location,
+            UnaryOp::LogicalNegate,
+            compare_exchange.get_type(),
+            compare_exchange,
+        );
+        let cond = self.cx.context.new_binary_op(
+            self.location,
+            BinaryOp::LogicalAnd,
+            self.cx.bool_type,
+            cond1,
+            cond2,
+        );
+
+        while_block.end_with_conditional(self.location, cond, while_block, after_block);
 
         // NOTE: since jumps were added in a place rustc does not expect, the current block in the
         // state need to be updated.
@@ -126,29 +129,48 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         return_value.to_rvalue()
     }
 
-    fn compare_exchange(&self, dst: RValue<'gcc>, cmp: LValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering, failure_order: AtomicOrdering, weak: bool) -> RValue<'gcc> {
+    fn compare_exchange(
+        &self,
+        dst: RValue<'gcc>,
+        cmp: LValue<'gcc>,
+        src: RValue<'gcc>,
+        order: AtomicOrdering,
+        failure_order: AtomicOrdering,
+        weak: bool,
+    ) -> RValue<'gcc> {
         let size = src.get_type().get_size();
-        let compare_exchange = self.context.get_builtin_function(&format!("__atomic_compare_exchange_{}", size));
+        let compare_exchange =
+            self.context.get_builtin_function(&format!("__atomic_compare_exchange_{}", size));
         let order = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc());
         let failure_order = self.context.new_rvalue_from_int(self.i32_type, failure_order.to_gcc());
         let weak = self.context.new_rvalue_from_int(self.bool_type, weak as i32);
 
         let void_ptr_type = self.context.new_type::<*mut ()>();
         let volatile_void_ptr_type = void_ptr_type.make_volatile();
-        let dst = self.context.new_cast(None, dst, volatile_void_ptr_type);
-        let expected = self.context.new_cast(None, cmp.get_address(None), void_ptr_type);
+        let dst = self.context.new_cast(self.location, dst, volatile_void_ptr_type);
+        let expected =
+            self.context.new_cast(self.location, cmp.get_address(self.location), void_ptr_type);
 
         // NOTE: not sure why, but we have the wrong type here.
         let int_type = compare_exchange.get_param(2).to_rvalue().get_type();
-        let src = self.context.new_cast(None, src, int_type);
-        self.context.new_call(None, compare_exchange, &[dst, expected, src, weak, order, failure_order])
+        let src = self.context.new_cast(self.location, src, int_type);
+        self.context.new_call(
+            self.location,
+            compare_exchange,
+            &[dst, expected, src, weak, order, failure_order],
+        )
     }
 
     pub fn assign(&self, lvalue: LValue<'gcc>, value: RValue<'gcc>) {
-        self.llbb().add_assignment(None, lvalue, value);
+        self.llbb().add_assignment(self.location, lvalue, value);
     }
 
-    fn check_call<'b>(&mut self, _typ: &str, func: Function<'gcc>, args: &'b [RValue<'gcc>]) -> Cow<'b, [RValue<'gcc>]> {
+    fn check_call<'b>(
+        &mut self,
+        _typ: &str,
+        func: Function<'gcc>,
+        args: &'b [RValue<'gcc>],
+    ) -> Cow<'b, [RValue<'gcc>]> {
         let mut all_args_match = true;
         let mut param_types = vec![];
         let param_count = func.get_param_count();
@@ -173,8 +195,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
                 let actual_ty = actual_val.get_type();
                 if expected_ty != actual_ty {
                     self.bitcast(actual_val, expected_ty)
-                }
-                else {
+                } else {
                     actual_val
                 }
             })
@@ -185,7 +206,12 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         Cow::Owned(casted_args)
     }
 
-    fn check_ptr_call<'b>(&mut self, _typ: &str, func_ptr: RValue<'gcc>, args: &'b [RValue<'gcc>]) -> Cow<'b, [RValue<'gcc>]> {
+    fn check_ptr_call<'b>(
+        &mut self,
+        _typ: &str,
+        func_ptr: RValue<'gcc>,
+        args: &'b [RValue<'gcc>],
+    ) -> Cow<'b, [RValue<'gcc>]> {
         let mut all_args_match = true;
         let mut param_types = vec![];
         let gcc_func = func_ptr.get_type().dyncast_function_ptr_type().expect("function ptr");
@@ -219,20 +245,32 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
 
                 let actual_ty = actual_val.get_type();
                 if expected_ty != actual_ty {
-                    if !actual_ty.is_vector() && !expected_ty.is_vector() && (actual_ty.is_integral() && expected_ty.is_integral()) || (actual_ty.get_pointee().is_some() && expected_ty.get_pointee().is_some()) {
-                        self.context.new_cast(None, actual_val, expected_ty)
-                    }
-                    else if on_stack_param_indices.contains(&index) {
-                        actual_val.dereference(None).to_rvalue()
-                    }
-                    else {
-                        assert!(!((actual_ty.is_vector() && !expected_ty.is_vector()) || (!actual_ty.is_vector() && expected_ty.is_vector())), "{:?} ({}) -> {:?} ({}), index: {:?}[{}]", actual_ty, actual_ty.is_vector(), expected_ty, expected_ty.is_vector(), func_ptr, index);
+                    if !actual_ty.is_vector()
+                        && !expected_ty.is_vector()
+                        && (actual_ty.is_integral() && expected_ty.is_integral())
+                        || (actual_ty.get_pointee().is_some()
+                            && expected_ty.get_pointee().is_some())
+                    {
+                        self.context.new_cast(self.location, actual_val, expected_ty)
+                    } else if on_stack_param_indices.contains(&index) {
+                        actual_val.dereference(self.location).to_rvalue()
+                    } else {
+                        assert!(
+                            !((actual_ty.is_vector() && !expected_ty.is_vector())
+                                || (!actual_ty.is_vector() && expected_ty.is_vector())),
+                            "{:?} ({}) -> {:?} ({}), index: {:?}[{}]",
+                            actual_ty,
+                            actual_ty.is_vector(),
+                            expected_ty,
+                            expected_ty.is_vector(),
+                            func_ptr,
+                            index
+                        );
                         // TODO(antoyo): perhaps use __builtin_convertvector for vector casting.
                         // TODO: remove bitcast now that vector types can be compared?
                         self.bitcast(actual_val, expected_ty)
                     }
-                }
-                else {
+                } else {
                     actual_val
                 }
             })
@@ -256,7 +294,12 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         self.block.get_function()
     }
 
-    fn function_call(&mut self, func: RValue<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> {
+    fn function_call(
+        &mut self,
+        func: RValue<'gcc>,
+        args: &[RValue<'gcc>],
+        _funclet: Option<&Funclet>,
+    ) -> RValue<'gcc> {
         // TODO(antoyo): remove when the API supports a different type for functions.
         let func: Function<'gcc> = self.cx.rvalue_as_function(func);
         let args = self.check_call("call", func, args);
@@ -268,35 +311,54 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         let current_func = self.block.get_function();
         if return_type != void_type {
             unsafe { RETURN_VALUE_COUNT += 1 };
-            let result = current_func.new_local(None, return_type, &format!("returnValue{}", unsafe { RETURN_VALUE_COUNT }));
-            self.block.add_assignment(None, result, self.cx.context.new_call(None, func, &args));
+            let result = current_func.new_local(
+                self.location,
+                return_type,
+                &format!("returnValue{}", unsafe { RETURN_VALUE_COUNT }),
+            );
+            self.block.add_assignment(
+                self.location,
+                result,
+                self.cx.context.new_call(self.location, func, &args),
+            );
             result.to_rvalue()
-        }
-        else {
-            self.block.add_eval(None, self.cx.context.new_call(None, func, &args));
+        } else {
+            self.block
+                .add_eval(self.location, self.cx.context.new_call(self.location, func, &args));
             // Return dummy value when not having return value.
             self.context.new_rvalue_from_long(self.isize_type, 0)
         }
     }
 
-    fn function_ptr_call(&mut self, typ: Type<'gcc>, mut func_ptr: RValue<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> {
-        let gcc_func =
-            match func_ptr.get_type().dyncast_function_ptr_type() {
-                Some(func) => func,
-                None => {
-                    // NOTE: due to opaque pointers now being used, we need to cast here.
-                    let new_func_type = typ.dyncast_function_ptr_type().expect("function ptr");
-                    func_ptr = self.context.new_cast(None, func_ptr, typ);
-                    new_func_type
-                },
-            };
+    fn function_ptr_call(
+        &mut self,
+        typ: Type<'gcc>,
+        mut func_ptr: RValue<'gcc>,
+        args: &[RValue<'gcc>],
+        _funclet: Option<&Funclet>,
+    ) -> RValue<'gcc> {
+        let gcc_func = match func_ptr.get_type().dyncast_function_ptr_type() {
+            Some(func) => func,
+            None => {
+                // NOTE: due to opaque pointers now being used, we need to cast here.
+                let new_func_type = typ.dyncast_function_ptr_type().expect("function ptr");
+                func_ptr = self.context.new_cast(self.location, func_ptr, typ);
+                new_func_type
+            }
+        };
         let func_name = format!("{:?}", func_ptr);
         let previous_arg_count = args.len();
         let orig_args = args;
         let args = {
             let function_address_names = self.function_address_names.borrow();
             let original_function_name = function_address_names.get(&func_ptr);
-            llvm::adjust_intrinsic_arguments(&self, gcc_func, args.into(), &func_name, original_function_name)
+            llvm::adjust_intrinsic_arguments(
+                &self,
+                gcc_func,
+                args.into(),
+                &func_name,
+                original_function_name,
+            )
         };
         let args_adjusted = args.len() != previous_arg_count;
         let args = self.check_ptr_call("call", func_ptr, &*args);
@@ -309,39 +371,78 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
 
         if return_type != void_type {
             unsafe { RETURN_VALUE_COUNT += 1 };
-            let return_value = self.cx.context.new_call_through_ptr(None, func_ptr, &args);
-            let return_value = llvm::adjust_intrinsic_return_value(&self, return_value, &func_name, &args, args_adjusted, orig_args);
-            let result = current_func.new_local(None, return_value.get_type(), &format!("ptrReturnValue{}", unsafe { RETURN_VALUE_COUNT }));
-            self.block.add_assignment(None, result, return_value);
+            let return_value = self.cx.context.new_call_through_ptr(self.location, func_ptr, &args);
+            let return_value = llvm::adjust_intrinsic_return_value(
+                &self,
+                return_value,
+                &func_name,
+                &args,
+                args_adjusted,
+                orig_args,
+            );
+            let result = current_func.new_local(
+                self.location,
+                return_value.get_type(),
+                &format!("ptrReturnValue{}", unsafe { RETURN_VALUE_COUNT }),
+            );
+            self.block.add_assignment(self.location, result, return_value);
             result.to_rvalue()
-        }
-        else {
-            #[cfg(not(feature="master"))]
+        } else {
+            #[cfg(not(feature = "master"))]
             if gcc_func.get_param_count() == 0 {
                 // FIXME(antoyo): As a temporary workaround for unsupported LLVM intrinsics.
-                self.block.add_eval(None, self.cx.context.new_call_through_ptr(None, func_ptr, &[]));
-            }
-            else {
-                self.block.add_eval(None, self.cx.context.new_call_through_ptr(None, func_ptr, &args));
+                self.block.add_eval(
+                    self.location,
+                    self.cx.context.new_call_through_ptr(self.location, func_ptr, &[]),
+                );
+            } else {
+                self.block.add_eval(
+                    self.location,
+                    self.cx.context.new_call_through_ptr(self.location, func_ptr, &args),
+                );
             }
-            #[cfg(feature="master")]
-            self.block.add_eval(None, self.cx.context.new_call_through_ptr(None, func_ptr, &args));
+            #[cfg(feature = "master")]
+            self.block.add_eval(
+                self.location,
+                self.cx.context.new_call_through_ptr(self.location, func_ptr, &args),
+            );
             // Return dummy value when not having return value.
-            let result = current_func.new_local(None, self.isize_type, "dummyValueThatShouldNeverBeUsed");
-            self.block.add_assignment(None, result, self.context.new_rvalue_from_long(self.isize_type, 0));
+            let result = current_func.new_local(
+                self.location,
+                self.isize_type,
+                "dummyValueThatShouldNeverBeUsed",
+            );
+            self.block.add_assignment(
+                self.location,
+                result,
+                self.context.new_rvalue_from_long(self.isize_type, 0),
+            );
             result.to_rvalue()
         }
     }
 
-    pub fn overflow_call(&self, func: Function<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>) -> RValue<'gcc> {
+    pub fn overflow_call(
+        &self,
+        func: Function<'gcc>,
+        args: &[RValue<'gcc>],
+        _funclet: Option<&Funclet>,
+    ) -> RValue<'gcc> {
         // gccjit requires to use the result of functions, even when it's not used.
         // That's why we assign the result to a local.
         let return_type = self.context.new_type::<bool>();
         let current_func = self.block.get_function();
         // TODO(antoyo): return the new_call() directly? Since the overflow function has no side-effects.
         unsafe { RETURN_VALUE_COUNT += 1 };
-        let result = current_func.new_local(None, return_type, &format!("overflowReturnValue{}", unsafe { RETURN_VALUE_COUNT }));
-        self.block.add_assignment(None, result, self.cx.context.new_call(None, func, &args));
+        let result = current_func.new_local(
+            self.location,
+            return_type,
+            &format!("overflowReturnValue{}", unsafe { RETURN_VALUE_COUNT }),
+        );
+        self.block.add_assignment(
+            self.location,
+            result,
+            self.cx.context.new_call(self.location, func, &args),
+        );
         result.to_rvalue()
     }
 }
@@ -405,6 +506,17 @@ impl<'gcc, 'tcx> BackendTypes for Builder<'_, 'gcc, 'tcx> {
     type DIVariable = <CodegenCx<'gcc, 'tcx> as BackendTypes>::DIVariable;
 }
 
+fn set_rvalue_location<'a, 'gcc, 'tcx>(
+    bx: &mut Builder<'a, 'gcc, 'tcx>,
+    rvalue: RValue<'gcc>,
+) -> RValue<'gcc> {
+    if bx.location.is_some() {
+        #[cfg(feature = "master")]
+        rvalue.set_location(bx.location.unwrap());
+    }
+    rvalue
+}
+
 impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     fn build(cx: &'a CodegenCx<'gcc, 'tcx>, block: Block<'gcc>) -> Builder<'a, 'gcc, 'tcx> {
         Builder::with_cx(cx, block)
@@ -429,43 +541,58 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     fn ret_void(&mut self) {
-        self.llbb().end_with_void_return(None)
+        self.llbb().end_with_void_return(self.location)
     }
 
     fn ret(&mut self, mut value: RValue<'gcc>) {
         if self.structs_as_pointer.borrow().contains(&value) {
             // NOTE: hack to workaround a limitation of the rustc API: see comment on
             // CodegenCx.structs_as_pointer
-            value = value.dereference(None).to_rvalue();
+            value = value.dereference(self.location).to_rvalue();
         }
         let expected_return_type = self.current_func().get_return_type();
         if !expected_return_type.is_compatible_with(value.get_type()) {
             // NOTE: due to opaque pointers now being used, we need to cast here.
-            value = self.context.new_cast(None, value, expected_return_type);
+            value = self.context.new_cast(self.location, value, expected_return_type);
         }
-        self.llbb().end_with_return(None, value);
+        self.llbb().end_with_return(self.location, value);
     }
 
     fn br(&mut self, dest: Block<'gcc>) {
-        self.llbb().end_with_jump(None, dest)
+        self.llbb().end_with_jump(self.location, dest)
     }
 
     fn cond_br(&mut self, cond: RValue<'gcc>, then_block: Block<'gcc>, else_block: Block<'gcc>) {
-        self.llbb().end_with_conditional(None, cond, then_block, else_block)
+        self.llbb().end_with_conditional(self.location, cond, then_block, else_block)
     }
 
-    fn switch(&mut self, value: RValue<'gcc>, default_block: Block<'gcc>, cases: impl ExactSizeIterator<Item = (u128, Block<'gcc>)>) {
+    fn switch(
+        &mut self,
+        value: RValue<'gcc>,
+        default_block: Block<'gcc>,
+        cases: impl ExactSizeIterator<Item = (u128, Block<'gcc>)>,
+    ) {
         let mut gcc_cases = vec![];
         let typ = self.val_ty(value);
         for (on_val, dest) in cases {
             let on_val = self.const_uint_big(typ, on_val);
             gcc_cases.push(self.context.new_case(on_val, on_val, dest));
         }
-        self.block.end_with_switch(None, value, default_block, &gcc_cases);
+        self.block.end_with_switch(self.location, value, default_block, &gcc_cases);
     }
 
-    #[cfg(feature="master")]
-    fn invoke(&mut self, typ: Type<'gcc>, fn_attrs: Option<&CodegenFnAttrs>, _fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> {
+    #[cfg(feature = "master")]
+    fn invoke(
+        &mut self,
+        typ: Type<'gcc>,
+        fn_attrs: Option<&CodegenFnAttrs>,
+        _fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
+        func: RValue<'gcc>,
+        args: &[RValue<'gcc>],
+        then: Block<'gcc>,
+        catch: Block<'gcc>,
+        _funclet: Option<&Funclet>,
+    ) -> RValue<'gcc> {
         let try_block = self.current_func().new_block("try");
 
         let current_block = self.block.clone();
@@ -473,30 +600,39 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         let call = self.call(typ, fn_attrs, None, func, args, None); // TODO(antoyo): use funclet here?
         self.block = current_block;
 
-        let return_value = self.current_func()
-            .new_local(None, call.get_type(), "invokeResult");
+        let return_value =
+            self.current_func().new_local(self.location, call.get_type(), "invokeResult");
 
-        try_block.add_assignment(None, return_value, call);
+        try_block.add_assignment(self.location, return_value, call);
 
-        try_block.end_with_jump(None, then);
+        try_block.end_with_jump(self.location, then);
 
         if self.cleanup_blocks.borrow().contains(&catch) {
-            self.block.add_try_finally(None, try_block, catch);
-        }
-        else {
-            self.block.add_try_catch(None, try_block, catch);
+            self.block.add_try_finally(self.location, try_block, catch);
+        } else {
+            self.block.add_try_catch(self.location, try_block, catch);
         }
 
-        self.block.end_with_jump(None, then);
+        self.block.end_with_jump(self.location, then);
 
         return_value.to_rvalue()
     }
 
-    #[cfg(not(feature="master"))]
-    fn invoke(&mut self, typ: Type<'gcc>, fn_attrs: Option<&CodegenFnAttrs>, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>) -> RValue<'gcc> {
+    #[cfg(not(feature = "master"))]
+    fn invoke(
+        &mut self,
+        typ: Type<'gcc>,
+        fn_attrs: Option<&CodegenFnAttrs>,
+        fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
+        func: RValue<'gcc>,
+        args: &[RValue<'gcc>],
+        then: Block<'gcc>,
+        catch: Block<'gcc>,
+        _funclet: Option<&Funclet>,
+    ) -> RValue<'gcc> {
         let call_site = self.call(typ, fn_attrs, None, func, args, None);
         let condition = self.context.new_rvalue_from_int(self.bool_type, 1);
-        self.llbb().end_with_conditional(None, condition, then, catch);
+        self.llbb().end_with_conditional(self.location, condition, then, catch);
         if let Some(_fn_abi) = fn_abi {
             // TODO(bjorn3): Apply function attributes
         }
@@ -505,16 +641,15 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
 
     fn unreachable(&mut self) {
         let func = self.context.get_builtin_function("__builtin_unreachable");
-        self.block.add_eval(None, self.context.new_call(None, func, &[]));
+        self.block.add_eval(self.location, self.context.new_call(self.location, func, &[]));
         let return_type = self.block.get_function().get_return_type();
         let void_type = self.context.new_type::<()>();
         if return_type == void_type {
-            self.block.end_with_void_return(None)
-        }
-        else {
-            let return_value = self.current_func()
-                .new_local(None, return_type, "unreachableReturn");
-            self.block.end_with_return(None, return_value)
+            self.block.end_with_void_return(self.location)
+        } else {
+            let return_value =
+                self.current_func().new_local(self.location, return_type, "unreachableReturn");
+            self.block.end_with_return(self.location, return_value)
         }
     }
 
@@ -539,7 +674,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     fn fmul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        a * b
+        self.cx.context.new_binary_op(self.location, BinaryOp::Mult, a.get_type(), a, b)
     }
 
     fn udiv(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
@@ -564,7 +699,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         // FIXME(antoyo): rustc_codegen_ssa::mir::intrinsic uses different types for a and b but they
         // should be the same.
         let typ = a.get_type().to_signed(self);
-        let b = self.context.new_cast(None, b, typ);
+        let b = self.context.new_cast(self.location, b, typ);
         a / b
     }
 
@@ -606,15 +741,32 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         //     ../../../gcc/gcc/cfgexpand.cc:6069
         // 0x7f0101bf9194 execute
         //     ../../../gcc/gcc/cfgexpand.cc:6795
-        if a.get_type().is_compatible_with(self.cx.float_type) {
+        let a_type = a.get_type();
+        let a_type_unqualified = a_type.unqualified();
+        if a_type.is_compatible_with(self.cx.float_type) {
             let fmodf = self.context.get_builtin_function("fmodf");
             // FIXME(antoyo): this seems to produce the wrong result.
-            return self.context.new_call(None, fmodf, &[a, b]);
+            return self.context.new_call(self.location, fmodf, &[a, b]);
+        }
+        if let Some(vector_type) = a_type_unqualified.dyncast_vector() {
+            assert_eq!(a_type_unqualified, b.get_type().unqualified());
+
+            let num_units = vector_type.get_num_units();
+            let new_elements: Vec<_> = (0..num_units)
+                .map(|i| {
+                    let index = self.context.new_rvalue_from_long(self.cx.type_u32(), i as _);
+                    let x = self.extract_element(a, index).to_rvalue();
+                    let y = self.extract_element(b, index).to_rvalue();
+                    self.frem(x, y)
+                })
+                .collect();
+
+            return self.context.new_rvalue_from_vector(self.location, a_type, &new_elements);
         }
-        assert_eq!(a.get_type().unqualified(), self.cx.double_type);
+        assert_eq!(a_type_unqualified, self.cx.double_type);
 
         let fmod = self.context.get_builtin_function("fmod");
-        return self.context.new_call(None, fmod, &[a, b]);
+        self.context.new_call(self.location, fmod, &[a, b])
     }
 
     fn shl(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
@@ -636,73 +788,78 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     fn or(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        self.cx.gcc_or(a, b)
+        self.cx.gcc_or(a, b, self.location)
     }
 
     fn xor(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        self.gcc_xor(a, b)
+        set_rvalue_location(self, self.gcc_xor(a, b))
     }
 
     fn neg(&mut self, a: RValue<'gcc>) -> RValue<'gcc> {
-        self.gcc_neg(a)
+        set_rvalue_location(self, self.gcc_neg(a))
     }
 
     fn fneg(&mut self, a: RValue<'gcc>) -> RValue<'gcc> {
-        self.cx.context.new_unary_op(None, UnaryOp::Minus, a.get_type(), a)
+        set_rvalue_location(
+            self,
+            self.cx.context.new_unary_op(self.location, UnaryOp::Minus, a.get_type(), a),
+        )
     }
 
     fn not(&mut self, a: RValue<'gcc>) -> RValue<'gcc> {
-        self.gcc_not(a)
+        set_rvalue_location(self, self.gcc_not(a))
     }
 
     fn unchecked_sadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        self.gcc_add(a, b)
+        set_rvalue_location(self, self.gcc_add(a, b))
     }
 
     fn unchecked_uadd(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        self.gcc_add(a, b)
+        set_rvalue_location(self, self.gcc_add(a, b))
     }
 
     fn unchecked_ssub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        self.gcc_sub(a, b)
+        set_rvalue_location(self, self.gcc_sub(a, b))
     }
 
     fn unchecked_usub(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
         // TODO(antoyo): should generate poison value?
-        self.gcc_sub(a, b)
+        set_rvalue_location(self, self.gcc_sub(a, b))
     }
 
     fn unchecked_smul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        self.gcc_mul(a, b)
+        set_rvalue_location(self, self.gcc_mul(a, b))
     }
 
     fn unchecked_umul(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        self.gcc_mul(a, b)
+        set_rvalue_location(self, self.gcc_mul(a, b))
     }
 
     fn fadd_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
         // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
-        lhs + rhs
+        set_rvalue_location(self, lhs + rhs)
     }
 
     fn fsub_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
         // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
-        lhs - rhs
+        set_rvalue_location(self, lhs - rhs)
     }
 
     fn fmul_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
         // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
-        lhs * rhs
+        set_rvalue_location(self, lhs * rhs)
     }
 
     fn fdiv_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
         // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
-        lhs / rhs
+        set_rvalue_location(self, lhs / rhs)
     }
 
     fn frem_fast(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
         // NOTE: it seems like we cannot enable fast-mode for a single operation in GCC.
-        self.frem(lhs, rhs)
+        let result = self.frem(lhs, rhs);
+        set_rvalue_location(self, result);
+        result
     }
 
     fn fadd_algebraic(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
@@ -730,23 +887,33 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         self.frem(lhs, rhs)
     }
 
-    fn checked_binop(&mut self, oop: OverflowOp, typ: Ty<'_>, lhs: Self::Value, rhs: Self::Value) -> (Self::Value, Self::Value) {
+    fn checked_binop(
+        &mut self,
+        oop: OverflowOp,
+        typ: Ty<'_>,
+        lhs: Self::Value,
+        rhs: Self::Value,
+    ) -> (Self::Value, Self::Value) {
         self.gcc_checked_binop(oop, typ, lhs, rhs)
     }
 
     fn alloca(&mut self, ty: Type<'gcc>, align: Align) -> RValue<'gcc> {
         // FIXME(antoyo): this check that we don't call get_aligned() a second time on a type.
         // Ideally, we shouldn't need to do this check.
-        let aligned_type =
-            if ty == self.cx.u128_type || ty == self.cx.i128_type {
-                ty
-            }
-            else {
-                ty.get_aligned(align.bytes())
-            };
+        let aligned_type = if ty == self.cx.u128_type || ty == self.cx.i128_type {
+            ty
+        } else {
+            ty.get_aligned(align.bytes())
+        };
         // TODO(antoyo): It might be better to return a LValue, but fixing the rustc API is non-trivial.
         self.stack_var_count.set(self.stack_var_count.get() + 1);
-        self.current_func().new_local(None, aligned_type, &format!("stack_var_{}", self.stack_var_count.get())).get_address(None)
+        self.current_func()
+            .new_local(
+                self.location,
+                aligned_type,
+                &format!("stack_var_{}", self.stack_var_count.get()),
+            )
+            .get_address(self.location)
     }
 
     fn byte_array_alloca(&mut self, _len: RValue<'gcc>, _align: Align) -> RValue<'gcc> {
@@ -761,48 +928,62 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         // dereference after a drop, for instance.
         // FIXME(antoyo): this check that we don't call get_aligned() a second time on a type.
         // Ideally, we shouldn't need to do this check.
-        let aligned_type =
-            if pointee_ty == self.cx.u128_type || pointee_ty == self.cx.i128_type {
-                pointee_ty
-            }
-            else {
-                pointee_ty.get_aligned(align.bytes())
-            };
-        let ptr = self.context.new_cast(None, ptr, aligned_type.make_pointer());
-        let deref = ptr.dereference(None).to_rvalue();
+        let aligned_type = if pointee_ty == self.cx.u128_type || pointee_ty == self.cx.i128_type {
+            pointee_ty
+        } else {
+            pointee_ty.get_aligned(align.bytes())
+        };
+        let ptr = self.context.new_cast(self.location, ptr, aligned_type.make_pointer());
+        let deref = ptr.dereference(self.location).to_rvalue();
         unsafe { RETURN_VALUE_COUNT += 1 };
-        let loaded_value = function.new_local(None, aligned_type, &format!("loadedValue{}", unsafe { RETURN_VALUE_COUNT }));
-        block.add_assignment(None, loaded_value, deref);
+        let loaded_value = function.new_local(
+            self.location,
+            aligned_type,
+            &format!("loadedValue{}", unsafe { RETURN_VALUE_COUNT }),
+        );
+        block.add_assignment(self.location, loaded_value, deref);
         loaded_value.to_rvalue()
     }
 
     fn volatile_load(&mut self, ty: Type<'gcc>, ptr: RValue<'gcc>) -> RValue<'gcc> {
-        let ptr = self.context.new_cast(None, ptr, ty.make_volatile().make_pointer());
-        ptr.dereference(None).to_rvalue()
+        let ptr = self.context.new_cast(self.location, ptr, ty.make_volatile().make_pointer());
+        ptr.dereference(self.location).to_rvalue()
     }
 
-    fn atomic_load(&mut self, _ty: Type<'gcc>, ptr: RValue<'gcc>, order: AtomicOrdering, size: Size) -> RValue<'gcc> {
+    fn atomic_load(
+        &mut self,
+        _ty: Type<'gcc>,
+        ptr: RValue<'gcc>,
+        order: AtomicOrdering,
+        size: Size,
+    ) -> RValue<'gcc> {
         // TODO(antoyo): use ty.
         // TODO(antoyo): handle alignment.
-        let atomic_load = self.context.get_builtin_function(&format!("__atomic_load_{}", size.bytes()));
+        let atomic_load =
+            self.context.get_builtin_function(&format!("__atomic_load_{}", size.bytes()));
         let ordering = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc());
 
-        let volatile_const_void_ptr_type = self.context.new_type::<()>()
-            .make_const()
-            .make_volatile()
-            .make_pointer();
-        let ptr = self.context.new_cast(None, ptr, volatile_const_void_ptr_type);
-        self.context.new_call(None, atomic_load, &[ptr, ordering])
+        let volatile_const_void_ptr_type =
+            self.context.new_type::<()>().make_const().make_volatile().make_pointer();
+        let ptr = self.context.new_cast(self.location, ptr, volatile_const_void_ptr_type);
+        self.context.new_call(self.location, atomic_load, &[ptr, ordering])
     }
 
-    fn load_operand(&mut self, place: PlaceRef<'tcx, RValue<'gcc>>) -> OperandRef<'tcx, RValue<'gcc>> {
+    fn load_operand(
+        &mut self,
+        place: PlaceRef<'tcx, RValue<'gcc>>,
+    ) -> OperandRef<'tcx, RValue<'gcc>> {
         assert_eq!(place.llextra.is_some(), place.layout.is_unsized());
 
         if place.layout.is_zst() {
             return OperandRef::zero_sized(place.layout);
         }
 
-        fn scalar_load_metadata<'a, 'gcc, 'tcx>(bx: &mut Builder<'a, 'gcc, 'tcx>, load: RValue<'gcc>, scalar: &abi::Scalar) {
+        fn scalar_load_metadata<'a, 'gcc, 'tcx>(
+            bx: &mut Builder<'a, 'gcc, 'tcx>,
+            load: RValue<'gcc>,
+            scalar: &abi::Scalar,
+        ) {
             let vr = scalar.valid_range(bx);
             match scalar.primitive() {
                 abi::Int(..) => {
@@ -817,49 +998,50 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
             }
         }
 
-        let val =
-            if let Some(llextra) = place.llextra {
-                OperandValue::Ref(place.llval, Some(llextra), place.align)
-            }
-            else if place.layout.is_gcc_immediate() {
-                let load = self.load(
-                    place.layout.gcc_type(self),
-                    place.llval,
-                    place.align,
-                );
-                if let abi::Abi::Scalar(ref scalar) = place.layout.abi {
-                    scalar_load_metadata(self, load, scalar);
-                }
-                OperandValue::Immediate(self.to_immediate(load, place.layout))
+        let val = if let Some(llextra) = place.llextra {
+            OperandValue::Ref(place.llval, Some(llextra), place.align)
+        } else if place.layout.is_gcc_immediate() {
+            let load = self.load(place.layout.gcc_type(self), place.llval, place.align);
+            if let abi::Abi::Scalar(ref scalar) = place.layout.abi {
+                scalar_load_metadata(self, load, scalar);
             }
-            else if let abi::Abi::ScalarPair(ref a, ref b) = place.layout.abi {
-                let b_offset = a.size(self).align_to(b.align(self).abi);
-
-                let mut load = |i, scalar: &abi::Scalar, align| {
-                    let llptr = if i == 0 {
-                        place.llval
-                    } else {
-                        self.inbounds_ptradd(place.llval, self.const_usize(b_offset.bytes()))
-                    };
-                    let llty = place.layout.scalar_pair_element_gcc_type(self, i);
-                    let load = self.load(llty, llptr, align);
-                    scalar_load_metadata(self, load, scalar);
-                    if scalar.is_bool() { self.trunc(load, self.type_i1()) } else { load }
+            OperandValue::Immediate(self.to_immediate(load, place.layout))
+        } else if let abi::Abi::ScalarPair(ref a, ref b) = place.layout.abi {
+            let b_offset = a.size(self).align_to(b.align(self).abi);
+
+            let mut load = |i, scalar: &abi::Scalar, align| {
+                let llptr = if i == 0 {
+                    place.llval
+                } else {
+                    self.inbounds_ptradd(place.llval, self.const_usize(b_offset.bytes()))
                 };
-
-                OperandValue::Pair(
-                    load(0, a, place.align),
-                    load(1, b, place.align.restrict_for_offset(b_offset)),
-                )
-            }
-            else {
-                OperandValue::Ref(place.llval, None, place.align)
+                let llty = place.layout.scalar_pair_element_gcc_type(self, i);
+                let load = self.load(llty, llptr, align);
+                scalar_load_metadata(self, load, scalar);
+                if scalar.is_bool() {
+                    self.trunc(load, self.type_i1())
+                } else {
+                    load
+                }
             };
 
+            OperandValue::Pair(
+                load(0, a, place.align),
+                load(1, b, place.align.restrict_for_offset(b_offset)),
+            )
+        } else {
+            OperandValue::Ref(place.llval, None, place.align)
+        };
+
         OperandRef { val, layout: place.layout }
     }
 
-    fn write_operand_repeatedly(&mut self, cg_elem: OperandRef<'tcx, RValue<'gcc>>, count: u64, dest: PlaceRef<'tcx, RValue<'gcc>>) {
+    fn write_operand_repeatedly(
+        &mut self,
+        cg_elem: OperandRef<'tcx, RValue<'gcc>>,
+        count: u64,
+        dest: PlaceRef<'tcx, RValue<'gcc>>,
+    ) {
         let zero = self.const_usize(0);
         let count = self.const_usize(count);
         let start = dest.project_index(self, zero).llval;
@@ -870,7 +1052,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         let next_bb = self.append_sibling_block("repeat_loop_next");
 
         let ptr_type = start.get_type();
-        let current = self.llbb().get_function().new_local(None, ptr_type, "loop_var");
+        let current = self.llbb().get_function().new_local(self.location, ptr_type, "loop_var");
         let current_val = current.to_rvalue();
         self.assign(current, start);
 
@@ -884,8 +1066,12 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         let align = dest.align.restrict_for_offset(dest.layout.field(self.cx(), 0).size);
         cg_elem.val.store(self, PlaceRef::new_sized_aligned(current_val, cg_elem.layout, align));
 
-        let next = self.inbounds_gep(self.backend_type(cg_elem.layout), current.to_rvalue(), &[self.const_usize(1)]);
-        self.llbb().add_assignment(None, current, next);
+        let next = self.inbounds_gep(
+            self.backend_type(cg_elem.layout),
+            current.to_rvalue(),
+            &[self.const_usize(1)],
+        );
+        self.llbb().add_assignment(self.location, current, next);
         self.br(header_bb);
 
         self.switch_to_block(next_bb);
@@ -903,75 +1089,100 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         self.store_with_flags(val, ptr, align, MemFlags::empty())
     }
 
-    fn store_with_flags(&mut self, val: RValue<'gcc>, ptr: RValue<'gcc>, align: Align, _flags: MemFlags) -> RValue<'gcc> {
+    fn store_with_flags(
+        &mut self,
+        val: RValue<'gcc>,
+        ptr: RValue<'gcc>,
+        align: Align,
+        _flags: MemFlags,
+    ) -> RValue<'gcc> {
         let ptr = self.check_store(val, ptr);
-        let destination = ptr.dereference(None);
+        let destination = ptr.dereference(self.location);
         // NOTE: libgccjit does not support specifying the alignment on the assignment, so we cast
         // to type so it gets the proper alignment.
         let destination_type = destination.to_rvalue().get_type().unqualified();
         let aligned_type = destination_type.get_aligned(align.bytes()).make_pointer();
-        let aligned_destination = self.cx.context.new_bitcast(None, ptr, aligned_type);
-        let aligned_destination = aligned_destination.dereference(None);
-        self.llbb().add_assignment(None, aligned_destination, val);
+        let aligned_destination = self.cx.context.new_bitcast(self.location, ptr, aligned_type);
+        let aligned_destination = aligned_destination.dereference(self.location);
+        self.llbb().add_assignment(self.location, aligned_destination, val);
         // TODO(antoyo): handle align and flags.
         // NOTE: dummy value here since it's never used. FIXME(antoyo): API should not return a value here?
         self.cx.context.new_rvalue_zero(self.type_i32())
     }
 
-    fn atomic_store(&mut self, value: RValue<'gcc>, ptr: RValue<'gcc>, order: AtomicOrdering, size: Size) {
+    fn atomic_store(
+        &mut self,
+        value: RValue<'gcc>,
+        ptr: RValue<'gcc>,
+        order: AtomicOrdering,
+        size: Size,
+    ) {
         // TODO(antoyo): handle alignment.
-        let atomic_store = self.context.get_builtin_function(&format!("__atomic_store_{}", size.bytes()));
+        let atomic_store =
+            self.context.get_builtin_function(&format!("__atomic_store_{}", size.bytes()));
         let ordering = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc());
-        let volatile_const_void_ptr_type = self.context.new_type::<()>()
-            .make_volatile()
-            .make_pointer();
-        let ptr = self.context.new_cast(None, ptr, volatile_const_void_ptr_type);
+        let volatile_const_void_ptr_type =
+            self.context.new_type::<()>().make_volatile().make_pointer();
+        let ptr = self.context.new_cast(self.location, ptr, volatile_const_void_ptr_type);
 
         // FIXME(antoyo): fix libgccjit to allow comparing an integer type with an aligned integer type because
         // the following cast is required to avoid this error:
         // gcc_jit_context_new_call: mismatching types for argument 2 of function "__atomic_store_4": assignment to param arg1 (type: int) from loadedValue3577 (type: unsigned int  __attribute__((aligned(4))))
         let int_type = atomic_store.get_param(1).to_rvalue().get_type();
-        let value = self.context.new_cast(None, value, int_type);
-        self.llbb()
-            .add_eval(None, self.context.new_call(None, atomic_store, &[ptr, value, ordering]));
+        let value = self.context.new_cast(self.location, value, int_type);
+        self.llbb().add_eval(
+            self.location,
+            self.context.new_call(self.location, atomic_store, &[ptr, value, ordering]),
+        );
     }
 
-    fn gep(&mut self, typ: Type<'gcc>, ptr: RValue<'gcc>, indices: &[RValue<'gcc>]) -> RValue<'gcc> {
+    fn gep(
+        &mut self,
+        typ: Type<'gcc>,
+        ptr: RValue<'gcc>,
+        indices: &[RValue<'gcc>],
+    ) -> RValue<'gcc> {
         // NOTE: due to opaque pointers now being used, we need to cast here.
-        let ptr = self.context.new_cast(None, ptr, typ.make_pointer());
+        let ptr = self.context.new_cast(self.location, ptr, typ.make_pointer());
         let ptr_type = ptr.get_type();
         let mut pointee_type = ptr.get_type();
         // NOTE: we cannot use array indexing here like in inbounds_gep because array indexing is
         // always considered in bounds in GCC (TODO(antoyo): to be verified).
         // So, we have to cast to a number.
-        let mut result = self.context.new_bitcast(None, ptr, self.sizet_type);
+        let mut result = self.context.new_bitcast(self.location, ptr, self.sizet_type);
         // FIXME(antoyo): if there were more than 1 index, this code is probably wrong and would
         // require dereferencing the pointer.
         for index in indices {
             pointee_type = pointee_type.get_pointee().expect("pointee type");
-            #[cfg(feature="master")]
+            #[cfg(feature = "master")]
             let pointee_size = {
                 let size = self.cx.context.new_sizeof(pointee_type);
-                self.context.new_cast(None, size, index.get_type())
+                self.context.new_cast(self.location, size, index.get_type())
             };
-            #[cfg(not(feature="master"))]
-            let pointee_size = self.context.new_rvalue_from_int(index.get_type(), pointee_type.get_size() as i32);
+            #[cfg(not(feature = "master"))]
+            let pointee_size =
+                self.context.new_rvalue_from_int(index.get_type(), pointee_type.get_size() as i32);
             result = result + self.gcc_int_cast(*index * pointee_size, self.sizet_type);
         }
-        self.context.new_bitcast(None, result, ptr_type)
+        self.context.new_bitcast(self.location, result, ptr_type)
     }
 
-    fn inbounds_gep(&mut self, typ: Type<'gcc>, ptr: RValue<'gcc>, indices: &[RValue<'gcc>]) -> RValue<'gcc> {
+    fn inbounds_gep(
+        &mut self,
+        typ: Type<'gcc>,
+        ptr: RValue<'gcc>,
+        indices: &[RValue<'gcc>],
+    ) -> RValue<'gcc> {
         // NOTE: due to opaque pointers now being used, we need to cast here.
-        let ptr = self.context.new_cast(None, ptr, typ.make_pointer());
+        let ptr = self.context.new_cast(self.location, ptr, typ.make_pointer());
         // NOTE: array indexing is always considered in bounds in GCC (TODO(antoyo): to be verified).
         let mut indices = indices.into_iter();
         let index = indices.next().expect("first index in inbounds_gep");
-        let mut result = self.context.new_array_access(None, ptr, *index);
+        let mut result = self.context.new_array_access(self.location, ptr, *index);
         for index in indices {
-            result = self.context.new_array_access(None, result, *index);
+            result = self.context.new_array_access(self.location, result, *index);
         }
-        result.get_address(None)
+        result.get_address(self.location)
     }
 
     /* Casts */
@@ -986,32 +1197,32 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
             // TODO(antoyo): nothing to do as it is only for LLVM?
             return value;
         }
-        self.context.new_cast(None, value, dest_ty)
+        self.context.new_cast(self.location, value, dest_ty)
     }
 
     fn fptoui(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
-        self.gcc_float_to_uint_cast(value, dest_ty)
+        set_rvalue_location(self, self.gcc_float_to_uint_cast(value, dest_ty))
     }
 
     fn fptosi(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
-        self.gcc_float_to_int_cast(value, dest_ty)
+        set_rvalue_location(self, self.gcc_float_to_int_cast(value, dest_ty))
     }
 
     fn uitofp(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
-        self.gcc_uint_to_float_cast(value, dest_ty)
+        set_rvalue_location(self, self.gcc_uint_to_float_cast(value, dest_ty))
     }
 
     fn sitofp(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
-        self.gcc_int_to_float_cast(value, dest_ty)
+        set_rvalue_location(self, self.gcc_int_to_float_cast(value, dest_ty))
     }
 
     fn fptrunc(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
         // TODO(antoyo): make sure it truncates.
-        self.context.new_cast(None, value, dest_ty)
+        set_rvalue_location(self, self.context.new_cast(self.location, value, dest_ty))
     }
 
     fn fpext(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
-        self.context.new_cast(None, value, dest_ty)
+        set_rvalue_location(self, self.context.new_cast(self.location, value, dest_ty))
     }
 
     fn ptrtoint(&mut self, value: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
@@ -1028,7 +1239,12 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         self.cx.const_bitcast(value, dest_ty)
     }
 
-    fn intcast(&mut self, value: RValue<'gcc>, dest_typ: Type<'gcc>, _is_signed: bool) -> RValue<'gcc> {
+    fn intcast(
+        &mut self,
+        value: RValue<'gcc>,
+        dest_typ: Type<'gcc>,
+        _is_signed: bool,
+    ) -> RValue<'gcc> {
         // NOTE: is_signed is for value, not dest_typ.
         self.gcc_int_cast(value, dest_typ)
     }
@@ -1039,13 +1255,17 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
             (false, true) => {
                 // NOTE: Projecting a field of a pointer type will attempt a cast from a signed char to
                 // a pointer, which is not supported by gccjit.
-                return self.cx.context.new_cast(None, self.inttoptr(value, val_type.make_pointer()), dest_ty);
-            },
+                self.cx.context.new_cast(
+                    self.location,
+                    self.inttoptr(value, val_type.make_pointer()),
+                    dest_ty,
+                )
+            }
             (false, false) => {
                 // When they are not pointers, we want a transmute (or reinterpret_cast).
                 self.bitcast(value, dest_ty)
-            },
-            (true, true) => self.cx.context.new_cast(None, value, dest_ty),
+            }
+            (true, true) => self.cx.context.new_cast(self.location, value, dest_ty),
             (true, false) => unimplemented!(),
         }
     }
@@ -1056,11 +1276,19 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     fn fcmp(&mut self, op: RealPredicate, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> RValue<'gcc> {
-        self.context.new_comparison(None, op.to_gcc_comparison(), lhs, rhs)
+        self.context.new_comparison(self.location, op.to_gcc_comparison(), lhs, rhs)
     }
 
     /* Miscellaneous instructions */
-    fn memcpy(&mut self, dst: RValue<'gcc>, _dst_align: Align, src: RValue<'gcc>, _src_align: Align, size: RValue<'gcc>, flags: MemFlags) {
+    fn memcpy(
+        &mut self,
+        dst: RValue<'gcc>,
+        _dst_align: Align,
+        src: RValue<'gcc>,
+        _src_align: Align,
+        size: RValue<'gcc>,
+        flags: MemFlags,
+    ) {
         assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memcpy not supported");
         let size = self.intcast(size, self.type_size_t(), false);
         let _is_volatile = flags.contains(MemFlags::VOLATILE);
@@ -1068,10 +1296,21 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         let src = self.pointercast(src, self.type_ptr_to(self.type_void()));
         let memcpy = self.context.get_builtin_function("memcpy");
         // TODO(antoyo): handle aligns and is_volatile.
-        self.block.add_eval(None, self.context.new_call(None, memcpy, &[dst, src, size]));
+        self.block.add_eval(
+            self.location,
+            self.context.new_call(self.location, memcpy, &[dst, src, size]),
+        );
     }
 
-    fn memmove(&mut self, dst: RValue<'gcc>, dst_align: Align, src: RValue<'gcc>, src_align: Align, size: RValue<'gcc>, flags: MemFlags) {
+    fn memmove(
+        &mut self,
+        dst: RValue<'gcc>,
+        dst_align: Align,
+        src: RValue<'gcc>,
+        src_align: Align,
+        size: RValue<'gcc>,
+        flags: MemFlags,
+    ) {
         if flags.contains(MemFlags::NONTEMPORAL) {
             // HACK(nox): This is inefficient but there is no nontemporal memmove.
             let val = self.load(src.get_type().get_pointee().expect("get_pointee"), src, src_align);
@@ -1086,35 +1325,53 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
 
         let memmove = self.context.get_builtin_function("memmove");
         // TODO(antoyo): handle is_volatile.
-        self.block.add_eval(None, self.context.new_call(None, memmove, &[dst, src, size]));
+        self.block.add_eval(
+            self.location,
+            self.context.new_call(self.location, memmove, &[dst, src, size]),
+        );
     }
 
-    fn memset(&mut self, ptr: RValue<'gcc>, fill_byte: RValue<'gcc>, size: RValue<'gcc>, _align: Align, flags: MemFlags) {
+    fn memset(
+        &mut self,
+        ptr: RValue<'gcc>,
+        fill_byte: RValue<'gcc>,
+        size: RValue<'gcc>,
+        _align: Align,
+        flags: MemFlags,
+    ) {
         let _is_volatile = flags.contains(MemFlags::VOLATILE);
         let ptr = self.pointercast(ptr, self.type_i8p());
         let memset = self.context.get_builtin_function("memset");
         // TODO(antoyo): handle align and is_volatile.
-        let fill_byte = self.context.new_cast(None, fill_byte, self.i32_type);
+        let fill_byte = self.context.new_cast(self.location, fill_byte, self.i32_type);
         let size = self.intcast(size, self.type_size_t(), false);
-        self.block.add_eval(None, self.context.new_call(None, memset, &[ptr, fill_byte, size]));
+        self.block.add_eval(
+            self.location,
+            self.context.new_call(self.location, memset, &[ptr, fill_byte, size]),
+        );
     }
 
-    fn select(&mut self, cond: RValue<'gcc>, then_val: RValue<'gcc>, mut else_val: RValue<'gcc>) -> RValue<'gcc> {
+    fn select(
+        &mut self,
+        cond: RValue<'gcc>,
+        then_val: RValue<'gcc>,
+        mut else_val: RValue<'gcc>,
+    ) -> RValue<'gcc> {
         let func = self.current_func();
-        let variable = func.new_local(None, then_val.get_type(), "selectVar");
+        let variable = func.new_local(self.location, then_val.get_type(), "selectVar");
         let then_block = func.new_block("then");
         let else_block = func.new_block("else");
         let after_block = func.new_block("after");
-        self.llbb().end_with_conditional(None, cond, then_block, else_block);
+        self.llbb().end_with_conditional(self.location, cond, then_block, else_block);
 
-        then_block.add_assignment(None, variable, then_val);
-        then_block.end_with_jump(None, after_block);
+        then_block.add_assignment(self.location, variable, then_val);
+        then_block.end_with_jump(self.location, after_block);
 
         if !then_val.get_type().is_compatible_with(else_val.get_type()) {
-            else_val = self.context.new_cast(None, else_val, then_val.get_type());
+            else_val = self.context.new_cast(self.location, else_val, then_val.get_type());
         }
-        else_block.add_assignment(None, variable, else_val);
-        else_block.end_with_jump(None, after_block);
+        else_block.add_assignment(self.location, variable, else_val);
+        else_block.end_with_jump(self.location, after_block);
 
         // NOTE: since jumps were added in a place rustc does not expect, the current block in the
         // state need to be updated.
@@ -1128,19 +1385,24 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         unimplemented!();
     }
 
-    #[cfg(feature="master")]
+    #[cfg(feature = "master")]
     fn extract_element(&mut self, vec: RValue<'gcc>, idx: RValue<'gcc>) -> RValue<'gcc> {
-        self.context.new_vector_access(None, vec, idx).to_rvalue()
+        self.context.new_vector_access(self.location, vec, idx).to_rvalue()
     }
 
-    #[cfg(not(feature="master"))]
+    #[cfg(not(feature = "master"))]
     fn extract_element(&mut self, vec: RValue<'gcc>, idx: RValue<'gcc>) -> RValue<'gcc> {
-        let vector_type = vec.get_type().unqualified().dyncast_vector().expect("Called extract_element on a non-vector type");
+        let vector_type = vec
+            .get_type()
+            .unqualified()
+            .dyncast_vector()
+            .expect("Called extract_element on a non-vector type");
         let element_type = vector_type.get_element_type();
         let vec_num_units = vector_type.get_num_units();
-        let array_type = self.context.new_array_type(None, element_type, vec_num_units as u64);
-        let array = self.context.new_bitcast(None, vec, array_type).to_rvalue();
-        self.context.new_array_access(None, array, idx).to_rvalue()
+        let array_type =
+            self.context.new_array_type(self.location, element_type, vec_num_units as u64);
+        let array = self.context.new_bitcast(self.location, vec, array_type).to_rvalue();
+        self.context.new_array_access(self.location, array, idx).to_rvalue()
     }
 
     fn vector_splat(&mut self, _num_elts: usize, _elt: RValue<'gcc>) -> RValue<'gcc> {
@@ -1153,82 +1415,85 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         let value_type = aggregate_value.get_type();
 
         if value_type.dyncast_array().is_some() {
-            let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from"));
-            let element = self.context.new_array_access(None, aggregate_value, index);
-            element.get_address(None)
-        }
-        else if value_type.dyncast_vector().is_some() {
+            let index = self
+                .context
+                .new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from"));
+            let element = self.context.new_array_access(self.location, aggregate_value, index);
+            element.get_address(self.location)
+        } else if value_type.dyncast_vector().is_some() {
             panic!();
-        }
-        else if let Some(pointer_type) = value_type.get_pointee() {
+        } else if let Some(pointer_type) = value_type.get_pointee() {
             if let Some(struct_type) = pointer_type.is_struct() {
                 // NOTE: hack to workaround a limitation of the rustc API: see comment on
                 // CodegenCx.structs_as_pointer
-                aggregate_value.dereference_field(None, struct_type.get_field(idx as i32)).to_rvalue()
-            }
-            else {
+                aggregate_value
+                    .dereference_field(self.location, struct_type.get_field(idx as i32))
+                    .to_rvalue()
+            } else {
                 panic!("Unexpected type {:?}", value_type);
             }
-        }
-        else if let Some(struct_type) = value_type.is_struct() {
-            aggregate_value.access_field(None, struct_type.get_field(idx as i32)).to_rvalue()
-        }
-        else {
+        } else if let Some(struct_type) = value_type.is_struct() {
+            aggregate_value
+                .access_field(self.location, struct_type.get_field(idx as i32))
+                .to_rvalue()
+        } else {
             panic!("Unexpected type {:?}", value_type);
         }
     }
 
-    fn insert_value(&mut self, aggregate_value: RValue<'gcc>, value: RValue<'gcc>, idx: u64) -> RValue<'gcc> {
+    fn insert_value(
+        &mut self,
+        aggregate_value: RValue<'gcc>,
+        value: RValue<'gcc>,
+        idx: u64,
+    ) -> RValue<'gcc> {
         // FIXME(antoyo): it would be better if the API only called this on struct, not on arrays.
         assert_eq!(idx as usize as u64, idx);
         let value_type = aggregate_value.get_type();
 
-        let lvalue =
-            if value_type.dyncast_array().is_some() {
-                let index = self.context.new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from"));
-                self.context.new_array_access(None, aggregate_value, index)
-            }
-            else if value_type.dyncast_vector().is_some() {
-                panic!();
-            }
-            else if let Some(pointer_type) = value_type.get_pointee() {
-                if let Some(struct_type) = pointer_type.is_struct() {
-                    // NOTE: hack to workaround a limitation of the rustc API: see comment on
-                    // CodegenCx.structs_as_pointer
-                    aggregate_value.dereference_field(None, struct_type.get_field(idx as i32))
-                }
-                else {
-                    panic!("Unexpected type {:?}", value_type);
-                }
-            }
-            else {
+        let lvalue = if value_type.dyncast_array().is_some() {
+            let index = self
+                .context
+                .new_rvalue_from_long(self.u64_type, i64::try_from(idx).expect("i64::try_from"));
+            self.context.new_array_access(self.location, aggregate_value, index)
+        } else if value_type.dyncast_vector().is_some() {
+            panic!();
+        } else if let Some(pointer_type) = value_type.get_pointee() {
+            if let Some(struct_type) = pointer_type.is_struct() {
+                // NOTE: hack to workaround a limitation of the rustc API: see comment on
+                // CodegenCx.structs_as_pointer
+                aggregate_value.dereference_field(self.location, struct_type.get_field(idx as i32))
+            } else {
                 panic!("Unexpected type {:?}", value_type);
-            };
+            }
+        } else {
+            panic!("Unexpected type {:?}", value_type);
+        };
 
         let lvalue_type = lvalue.to_rvalue().get_type();
         let value =
             // NOTE: sometimes, rustc will create a value with the wrong type.
             if lvalue_type != value.get_type() {
-                self.context.new_cast(None, value, lvalue_type)
+                self.context.new_cast(self.location, value, lvalue_type)
             }
             else {
                 value
             };
 
-        self.llbb().add_assignment(None, lvalue, value);
+        self.llbb().add_assignment(self.location, lvalue, value);
 
         aggregate_value
     }
 
     fn set_personality_fn(&mut self, _personality: RValue<'gcc>) {
-        #[cfg(feature="master")]
+        #[cfg(feature = "master")]
         {
             let personality = self.rvalue_as_function(_personality);
             self.current_func().set_personality_function(personality);
         }
     }
 
-    #[cfg(feature="master")]
+    #[cfg(feature = "master")]
     fn cleanup_landing_pad(&mut self, pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
         self.set_personality_fn(pers_fn);
 
@@ -1236,23 +1501,27 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         // generate a try/finally instead of a try/catch for this block.
         self.cleanup_blocks.borrow_mut().insert(self.block);
 
-        let eh_pointer_builtin = self.cx.context.get_target_builtin_function("__builtin_eh_pointer");
+        let eh_pointer_builtin =
+            self.cx.context.get_target_builtin_function("__builtin_eh_pointer");
         let zero = self.cx.context.new_rvalue_zero(self.int_type);
-        let ptr = self.cx.context.new_call(None, eh_pointer_builtin, &[zero]);
+        let ptr = self.cx.context.new_call(self.location, eh_pointer_builtin, &[zero]);
 
         let value1_type = self.u8_type.make_pointer();
-        let ptr = self.cx.context.new_cast(None, ptr, value1_type);
+        let ptr = self.cx.context.new_cast(self.location, ptr, value1_type);
         let value1 = ptr;
         let value2 = zero; // TODO(antoyo): set the proper value here (the type of exception?).
 
         (value1, value2)
     }
 
-    #[cfg(not(feature="master"))]
+    #[cfg(not(feature = "master"))]
     fn cleanup_landing_pad(&mut self, _pers_fn: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
-        let value1 = self.current_func().new_local(None, self.u8_type.make_pointer(), "landing_pad0")
-                .to_rvalue();
-        let value2 = self.current_func().new_local(None, self.i32_type, "landing_pad1").to_rvalue();
+        let value1 = self
+            .current_func()
+            .new_local(self.location, self.u8_type.make_pointer(), "landing_pad0")
+            .to_rvalue();
+        let value2 =
+            self.current_func().new_local(self.location, self.i32_type, "landing_pad1").to_rvalue();
         (value1, value2)
     }
 
@@ -1261,16 +1530,17 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         self.cleanup_landing_pad(pers_fn)
     }
 
-    #[cfg(feature="master")]
+    #[cfg(feature = "master")]
     fn resume(&mut self, exn0: RValue<'gcc>, _exn1: RValue<'gcc>) {
         let exn_type = exn0.get_type();
-        let exn = self.context.new_cast(None, exn0, exn_type);
+        let exn = self.context.new_cast(self.location, exn0, exn_type);
         let unwind_resume = self.context.get_target_builtin_function("__builtin_unwind_resume");
-        self.llbb().add_eval(None, self.context.new_call(None, unwind_resume, &[exn]));
+        self.llbb()
+            .add_eval(self.location, self.context.new_call(self.location, unwind_resume, &[exn]));
         self.unreachable();
     }
 
-    #[cfg(not(feature="master"))]
+    #[cfg(not(feature = "master"))]
     fn resume(&mut self, _exn0: RValue<'gcc>, _exn1: RValue<'gcc>) {
         self.unreachable();
     }
@@ -1297,68 +1567,82 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 
     // Atomic Operations
-    fn atomic_cmpxchg(&mut self, dst: RValue<'gcc>, cmp: RValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering, failure_order: AtomicOrdering, weak: bool) -> (RValue<'gcc>, RValue<'gcc>) {
+    fn atomic_cmpxchg(
+        &mut self,
+        dst: RValue<'gcc>,
+        cmp: RValue<'gcc>,
+        src: RValue<'gcc>,
+        order: AtomicOrdering,
+        failure_order: AtomicOrdering,
+        weak: bool,
+    ) -> (RValue<'gcc>, RValue<'gcc>) {
         let expected = self.current_func().new_local(None, cmp.get_type(), "expected");
         self.llbb().add_assignment(None, expected, cmp);
         // NOTE: gcc doesn't support a failure memory model that is stronger than the success
         // memory model.
-        let order =
-            if failure_order as i32 > order as i32 {
-                failure_order
-            }
-            else {
-                order
-            };
+        let order = if failure_order as i32 > order as i32 { failure_order } else { order };
         let success = self.compare_exchange(dst, expected, src, order, failure_order, weak);
 
         // NOTE: since success contains the call to the intrinsic, it must be added to the basic block before
         // expected so that we store expected after the call.
-        let success_var = self.current_func().new_local(None, self.bool_type, "success");
-        self.llbb().add_assignment(None, success_var, success);
+        let success_var = self.current_func().new_local(self.location, self.bool_type, "success");
+        self.llbb().add_assignment(self.location, success_var, success);
 
         (expected.to_rvalue(), success_var.to_rvalue())
     }
 
-    fn atomic_rmw(&mut self, op: AtomicRmwBinOp, dst: RValue<'gcc>, src: RValue<'gcc>, order: AtomicOrdering) -> RValue<'gcc> {
+    fn atomic_rmw(
+        &mut self,
+        op: AtomicRmwBinOp,
+        dst: RValue<'gcc>,
+        src: RValue<'gcc>,
+        order: AtomicOrdering,
+    ) -> RValue<'gcc> {
         let size = src.get_type().get_size();
-        let name =
-            match op {
-                AtomicRmwBinOp::AtomicXchg => format!("__atomic_exchange_{}", size),
-                AtomicRmwBinOp::AtomicAdd => format!("__atomic_fetch_add_{}", size),
-                AtomicRmwBinOp::AtomicSub => format!("__atomic_fetch_sub_{}", size),
-                AtomicRmwBinOp::AtomicAnd => format!("__atomic_fetch_and_{}", size),
-                AtomicRmwBinOp::AtomicNand => format!("__atomic_fetch_nand_{}", size),
-                AtomicRmwBinOp::AtomicOr => format!("__atomic_fetch_or_{}", size),
-                AtomicRmwBinOp::AtomicXor => format!("__atomic_fetch_xor_{}", size),
-                AtomicRmwBinOp::AtomicMax => return self.atomic_extremum(ExtremumOperation::Max, dst, src, order),
-                AtomicRmwBinOp::AtomicMin => return self.atomic_extremum(ExtremumOperation::Min, dst, src, order),
-                AtomicRmwBinOp::AtomicUMax => return self.atomic_extremum(ExtremumOperation::Max, dst, src, order),
-                AtomicRmwBinOp::AtomicUMin => return self.atomic_extremum(ExtremumOperation::Min, dst, src, order),
-            };
-
+        let name = match op {
+            AtomicRmwBinOp::AtomicXchg => format!("__atomic_exchange_{}", size),
+            AtomicRmwBinOp::AtomicAdd => format!("__atomic_fetch_add_{}", size),
+            AtomicRmwBinOp::AtomicSub => format!("__atomic_fetch_sub_{}", size),
+            AtomicRmwBinOp::AtomicAnd => format!("__atomic_fetch_and_{}", size),
+            AtomicRmwBinOp::AtomicNand => format!("__atomic_fetch_nand_{}", size),
+            AtomicRmwBinOp::AtomicOr => format!("__atomic_fetch_or_{}", size),
+            AtomicRmwBinOp::AtomicXor => format!("__atomic_fetch_xor_{}", size),
+            AtomicRmwBinOp::AtomicMax => {
+                return self.atomic_extremum(ExtremumOperation::Max, dst, src, order);
+            }
+            AtomicRmwBinOp::AtomicMin => {
+                return self.atomic_extremum(ExtremumOperation::Min, dst, src, order);
+            }
+            AtomicRmwBinOp::AtomicUMax => {
+                return self.atomic_extremum(ExtremumOperation::Max, dst, src, order);
+            }
+            AtomicRmwBinOp::AtomicUMin => {
+                return self.atomic_extremum(ExtremumOperation::Min, dst, src, order);
+            }
+        };
 
         let atomic_function = self.context.get_builtin_function(name);
         let order = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc());
 
         let void_ptr_type = self.context.new_type::<*mut ()>();
         let volatile_void_ptr_type = void_ptr_type.make_volatile();
-        let dst = self.context.new_cast(None, dst, volatile_void_ptr_type);
+        let dst = self.context.new_cast(self.location, dst, volatile_void_ptr_type);
         // FIXME(antoyo): not sure why, but we have the wrong type here.
         let new_src_type = atomic_function.get_param(1).to_rvalue().get_type();
-        let src = self.context.new_cast(None, src, new_src_type);
-        let res = self.context.new_call(None, atomic_function, &[dst, src, order]);
-        self.context.new_cast(None, res, src.get_type())
+        let src = self.context.new_cast(self.location, src, new_src_type);
+        let res = self.context.new_call(self.location, atomic_function, &[dst, src, order]);
+        self.context.new_cast(self.location, res, src.get_type())
     }
 
     fn atomic_fence(&mut self, order: AtomicOrdering, scope: SynchronizationScope) {
-        let name =
-            match scope {
-                SynchronizationScope::SingleThread => "__atomic_signal_fence",
-                SynchronizationScope::CrossThread => "__atomic_thread_fence",
-            };
+        let name = match scope {
+            SynchronizationScope::SingleThread => "__atomic_signal_fence",
+            SynchronizationScope::CrossThread => "__atomic_thread_fence",
+        };
         let thread_fence = self.context.get_builtin_function(name);
         let order = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc());
-        self.llbb().add_eval(None, self.context.new_call(None, thread_fence, &[order]));
+        self.llbb()
+            .add_eval(self.location, self.context.new_call(self.location, thread_fence, &[order]));
     }
 
     fn set_invariant_load(&mut self, load: RValue<'gcc>) {
@@ -1388,8 +1672,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         let gcc_func = unsafe { std::mem::transmute(func) };
         let call = if self.functions.borrow().values().any(|value| *value == gcc_func) {
             self.function_call(func, args, funclet)
-        }
-        else {
+        } else {
             // If it's a not function that was defined, it's a function pointer.
             self.function_ptr_call(typ, func, args, funclet)
         };
@@ -1422,8 +1705,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
     fn from_immediate(&mut self, val: Self::Value) -> Self::Value {
         if self.cx().val_ty(val) == self.cx().type_i1() {
             self.zext(val, self.cx().type_i8())
-        }
-        else {
+        } else {
             val
         }
     }
@@ -1443,13 +1725,24 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         self.fptoint_sat(true, val, dest_ty)
     }
 
-    fn instrprof_increment(&mut self, _fn_name: RValue<'gcc>, _hash: RValue<'gcc>, _num_counters: RValue<'gcc>, _index: RValue<'gcc>) {
+    fn instrprof_increment(
+        &mut self,
+        _fn_name: RValue<'gcc>,
+        _hash: RValue<'gcc>,
+        _num_counters: RValue<'gcc>,
+        _index: RValue<'gcc>,
+    ) {
         unimplemented!();
     }
 }
 
 impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
-    fn fptoint_sat(&mut self, signed: bool, val: RValue<'gcc>, dest_ty: Type<'gcc>) -> RValue<'gcc> {
+    fn fptoint_sat(
+        &mut self,
+        signed: bool,
+        val: RValue<'gcc>,
+        dest_ty: Type<'gcc>,
+    ) -> RValue<'gcc> {
         let src_ty = self.cx.val_ty(val);
         let (float_ty, int_ty) = if self.cx.type_kind(src_ty) == TypeKind::Vector {
             assert_eq!(self.cx.vector_length(src_ty), self.cx.vector_length(dest_ty));
@@ -1486,10 +1779,18 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         // This already happens today with u128::MAX = 2^128 - 1 > f32::MAX.
         let int_max = |signed: bool, int_width: u64| -> u128 {
             let shift_amount = 128 - int_width;
-            if signed { i128::MAX as u128 >> shift_amount } else { u128::MAX >> shift_amount }
+            if signed {
+                i128::MAX as u128 >> shift_amount
+            } else {
+                u128::MAX >> shift_amount
+            }
         };
         let int_min = |signed: bool, int_width: u64| -> i128 {
-            if signed { i128::MIN >> (128 - int_width) } else { 0 }
+            if signed {
+                i128::MIN >> (128 - int_width)
+            } else {
+                0
+            }
         };
 
         let compute_clamp_bounds_single = |signed: bool, int_width: u64| -> (u128, u128) {
@@ -1573,7 +1874,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         let zero = maybe_splat(self, zero);
 
         // Step 1 ...
-        let fptosui_result = if signed { self.fptosi(val, dest_ty) } else { self.fptoui(val, dest_ty) };
+        let fptosui_result =
+            if signed { self.fptosi(val, dest_ty) } else { self.fptoui(val, dest_ty) };
         let less_or_nan = self.fcmp(RealPredicate::RealULT, val, f_min);
         let greater = self.fcmp(RealPredicate::RealOGT, val, f_max);
 
@@ -1609,8 +1911,13 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         }
     }
 
-    #[cfg(feature="master")]
-    pub fn shuffle_vector(&mut self, v1: RValue<'gcc>, v2: RValue<'gcc>, mask: RValue<'gcc>) -> RValue<'gcc> {
+    #[cfg(feature = "master")]
+    pub fn shuffle_vector(
+        &mut self,
+        v1: RValue<'gcc>,
+        v2: RValue<'gcc>,
+        mask: RValue<'gcc>,
+    ) -> RValue<'gcc> {
         let struct_type = mask.get_type().is_struct().expect("mask should be of struct type");
 
         // TODO(antoyo): use a recursive unqualified() here.
@@ -1620,21 +1927,23 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
 
         let mask_num_units = struct_type.get_field_count();
         let mut vector_elements = vec![];
-        let mask_element_type =
-            if element_type.is_integral() {
-                element_type
+        let mask_element_type = if element_type.is_integral() {
+            element_type
+        } else {
+            #[cfg(feature = "master")]
+            {
+                self.cx.type_ix(element_type.get_size() as u64 * 8)
             }
-            else {
-                #[cfg(feature="master")]
-                {
-                    self.cx.type_ix(element_type.get_size() as u64 * 8)
-                }
-                #[cfg(not(feature="master"))]
-                self.int_type
-            };
+            #[cfg(not(feature = "master"))]
+            self.int_type
+        };
         for i in 0..mask_num_units {
             let field = struct_type.get_field(i as i32);
-            vector_elements.push(self.context.new_cast(None, mask.access_field(None, field).to_rvalue(), mask_element_type));
+            vector_elements.push(self.context.new_cast(
+                self.location,
+                mask.access_field(self.location, field).to_rvalue(),
+                mask_element_type,
+            ));
         }
 
         // NOTE: the mask needs to be the same length as the input vectors, so add the missing
@@ -1644,53 +1953,84 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         }
 
         let result_type = self.context.new_vector_type(element_type, mask_num_units as u64);
-        let (v1, v2) =
-            if vec_num_units < mask_num_units {
-                // NOTE: the mask needs to be the same length as the input vectors, so join the 2
-                // vectors and create a dummy second vector.
-                let mut elements = vec![];
-                for i in 0..vec_num_units {
-                    elements.push(self.context.new_vector_access(None, v1, self.context.new_rvalue_from_int(self.int_type, i as i32)).to_rvalue());
-                }
-                for i in 0..(mask_num_units - vec_num_units) {
-                    elements.push(self.context.new_vector_access(None, v2, self.context.new_rvalue_from_int(self.int_type, i as i32)).to_rvalue());
-                }
-                let v1 = self.context.new_rvalue_from_vector(None, result_type, &elements);
-                let zero = self.context.new_rvalue_zero(element_type);
-                let v2 = self.context.new_rvalue_from_vector(None, result_type, &vec![zero; mask_num_units]);
-                (v1, v2)
+        let (v1, v2) = if vec_num_units < mask_num_units {
+            // NOTE: the mask needs to be the same length as the input vectors, so join the 2
+            // vectors and create a dummy second vector.
+            let mut elements = vec![];
+            for i in 0..vec_num_units {
+                elements.push(
+                    self.context
+                        .new_vector_access(
+                            self.location,
+                            v1,
+                            self.context.new_rvalue_from_int(self.int_type, i as i32),
+                        )
+                        .to_rvalue(),
+                );
             }
-            else {
-                (v1, v2)
-            };
+            for i in 0..(mask_num_units - vec_num_units) {
+                elements.push(
+                    self.context
+                        .new_vector_access(
+                            self.location,
+                            v2,
+                            self.context.new_rvalue_from_int(self.int_type, i as i32),
+                        )
+                        .to_rvalue(),
+                );
+            }
+            let v1 = self.context.new_rvalue_from_vector(self.location, result_type, &elements);
+            let zero = self.context.new_rvalue_zero(element_type);
+            let v2 = self.context.new_rvalue_from_vector(
+                self.location,
+                result_type,
+                &vec![zero; mask_num_units],
+            );
+            (v1, v2)
+        } else {
+            (v1, v2)
+        };
 
         let new_mask_num_units = std::cmp::max(mask_num_units, vec_num_units);
         let mask_type = self.context.new_vector_type(mask_element_type, new_mask_num_units as u64);
-        let mask = self.context.new_rvalue_from_vector(None, mask_type, &vector_elements);
-        let result = self.context.new_rvalue_vector_perm(None, v1, v2, mask);
+        let mask = self.context.new_rvalue_from_vector(self.location, mask_type, &vector_elements);
+        let result = self.context.new_rvalue_vector_perm(self.location, v1, v2, mask);
 
         if vec_num_units != mask_num_units {
             // NOTE: if padding was added, only select the number of elements of the masks to
             // remove that padding in the result.
             let mut elements = vec![];
             for i in 0..mask_num_units {
-                elements.push(self.context.new_vector_access(None, result, self.context.new_rvalue_from_int(self.int_type, i as i32)).to_rvalue());
+                elements.push(
+                    self.context
+                        .new_vector_access(
+                            self.location,
+                            result,
+                            self.context.new_rvalue_from_int(self.int_type, i as i32),
+                        )
+                        .to_rvalue(),
+                );
             }
-            self.context.new_rvalue_from_vector(None, result_type, &elements)
-        }
-        else {
+            self.context.new_rvalue_from_vector(self.location, result_type, &elements)
+        } else {
             result
         }
     }
 
-    #[cfg(not(feature="master"))]
-    pub fn shuffle_vector(&mut self, _v1: RValue<'gcc>, _v2: RValue<'gcc>, _mask: RValue<'gcc>) -> RValue<'gcc> {
+    #[cfg(not(feature = "master"))]
+    pub fn shuffle_vector(
+        &mut self,
+        _v1: RValue<'gcc>,
+        _v2: RValue<'gcc>,
+        _mask: RValue<'gcc>,
+    ) -> RValue<'gcc> {
         unimplemented!();
     }
 
-    #[cfg(feature="master")]
+    #[cfg(feature = "master")]
     pub fn vector_reduce<F>(&mut self, src: RValue<'gcc>, op: F) -> RValue<'gcc>
-    where F: Fn(RValue<'gcc>, RValue<'gcc>, &'gcc Context<'gcc>) -> RValue<'gcc>
+    where
+        F: Fn(RValue<'gcc>, RValue<'gcc>, &'gcc Context<'gcc>) -> RValue<'gcc>,
     {
         let vector_type = src.get_type().unqualified().dyncast_vector().expect("vector type");
         let element_type = vector_type.get_element_type();
@@ -1704,130 +2044,178 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         let mut shift = 1;
         let mut res = src;
         while shift < element_count {
-            let vector_elements: Vec<_> =
-                vector_elements.iter()
-                    .map(|i| self.context.new_rvalue_from_int(mask_element_type, ((i + shift) % element_count) as i32))
-                    .collect();
-            let mask = self.context.new_rvalue_from_vector(None, mask_type, &vector_elements);
-            let shifted = self.context.new_rvalue_vector_perm(None, res, res, mask);
+            let vector_elements: Vec<_> = vector_elements
+                .iter()
+                .map(|i| {
+                    self.context.new_rvalue_from_int(
+                        mask_element_type,
+                        ((i + shift) % element_count) as i32,
+                    )
+                })
+                .collect();
+            let mask =
+                self.context.new_rvalue_from_vector(self.location, mask_type, &vector_elements);
+            let shifted = self.context.new_rvalue_vector_perm(self.location, res, res, mask);
             shift *= 2;
             res = op(res, shifted, &self.context);
         }
-        self.context.new_vector_access(None, res, self.context.new_rvalue_zero(self.int_type))
+        self.context
+            .new_vector_access(self.location, res, self.context.new_rvalue_zero(self.int_type))
             .to_rvalue()
     }
 
-    #[cfg(not(feature="master"))]
+    #[cfg(not(feature = "master"))]
     pub fn vector_reduce<F>(&mut self, _src: RValue<'gcc>, _op: F) -> RValue<'gcc>
-    where F: Fn(RValue<'gcc>, RValue<'gcc>, &'gcc Context<'gcc>) -> RValue<'gcc>
+    where
+        F: Fn(RValue<'gcc>, RValue<'gcc>, &'gcc Context<'gcc>) -> RValue<'gcc>,
     {
         unimplemented!();
     }
 
     pub fn vector_reduce_op(&mut self, src: RValue<'gcc>, op: BinaryOp) -> RValue<'gcc> {
-        self.vector_reduce(src, |a, b, context| context.new_binary_op(None, op, a.get_type(), a, b))
+        let loc = self.location.clone();
+        self.vector_reduce(src, |a, b, context| context.new_binary_op(loc, op, a.get_type(), a, b))
     }
 
-    pub fn vector_reduce_fadd_reassoc(&mut self, _acc: RValue<'gcc>, _src: RValue<'gcc>) -> RValue<'gcc> {
+    pub fn vector_reduce_fadd_reassoc(
+        &mut self,
+        _acc: RValue<'gcc>,
+        _src: RValue<'gcc>,
+    ) -> RValue<'gcc> {
         unimplemented!();
     }
 
-    #[cfg(feature="master")]
+    #[cfg(feature = "master")]
     pub fn vector_reduce_fadd(&mut self, acc: RValue<'gcc>, src: RValue<'gcc>) -> RValue<'gcc> {
         let vector_type = src.get_type().unqualified().dyncast_vector().expect("vector type");
         let element_count = vector_type.get_num_units();
-        (0..element_count).into_iter()
-            .map(|i| self.context
-                .new_vector_access(None, src, self.context.new_rvalue_from_int(self.int_type, i as _))
-                .to_rvalue())
+        (0..element_count)
+            .into_iter()
+            .map(|i| {
+                self.context
+                    .new_vector_access(
+                        self.location,
+                        src,
+                        self.context.new_rvalue_from_int(self.int_type, i as _),
+                    )
+                    .to_rvalue()
+            })
             .fold(acc, |x, i| x + i)
     }
 
-    #[cfg(not(feature="master"))]
+    #[cfg(not(feature = "master"))]
     pub fn vector_reduce_fadd(&mut self, _acc: RValue<'gcc>, _src: RValue<'gcc>) -> RValue<'gcc> {
         unimplemented!();
     }
 
-    pub fn vector_reduce_fmul_reassoc(&mut self, _acc: RValue<'gcc>, _src: RValue<'gcc>) -> RValue<'gcc> {
+    pub fn vector_reduce_fmul_reassoc(
+        &mut self,
+        _acc: RValue<'gcc>,
+        _src: RValue<'gcc>,
+    ) -> RValue<'gcc> {
         unimplemented!();
     }
 
-    #[cfg(feature="master")]
+    #[cfg(feature = "master")]
     pub fn vector_reduce_fmul(&mut self, acc: RValue<'gcc>, src: RValue<'gcc>) -> RValue<'gcc> {
         let vector_type = src.get_type().unqualified().dyncast_vector().expect("vector type");
         let element_count = vector_type.get_num_units();
-        (0..element_count).into_iter()
-            .map(|i| self.context
-                .new_vector_access(None, src, self.context.new_rvalue_from_int(self.int_type, i as _))
-                .to_rvalue())
+        (0..element_count)
+            .into_iter()
+            .map(|i| {
+                self.context
+                    .new_vector_access(
+                        self.location,
+                        src,
+                        self.context.new_rvalue_from_int(self.int_type, i as _),
+                    )
+                    .to_rvalue()
+            })
             .fold(acc, |x, i| x * i)
     }
 
-    #[cfg(not(feature="master"))]
+    #[cfg(not(feature = "master"))]
     pub fn vector_reduce_fmul(&mut self, _acc: RValue<'gcc>, _src: RValue<'gcc>) -> RValue<'gcc> {
         unimplemented!()
     }
 
     // Inspired by Hacker's Delight min implementation.
     pub fn vector_reduce_min(&mut self, src: RValue<'gcc>) -> RValue<'gcc> {
+        let loc = self.location.clone();
         self.vector_reduce(src, |a, b, context| {
-            let differences_or_zeros = difference_or_zero(a, b, context);
-            context.new_binary_op(None, BinaryOp::Plus, b.get_type(), b, differences_or_zeros)
+            let differences_or_zeros = difference_or_zero(loc, a, b, context);
+            context.new_binary_op(loc, BinaryOp::Plus, b.get_type(), b, differences_or_zeros)
         })
     }
 
     // Inspired by Hacker's Delight max implementation.
     pub fn vector_reduce_max(&mut self, src: RValue<'gcc>) -> RValue<'gcc> {
+        let loc = self.location.clone();
         self.vector_reduce(src, |a, b, context| {
-            let differences_or_zeros = difference_or_zero(a, b, context);
-            context.new_binary_op(None, BinaryOp::Minus, a.get_type(), a, differences_or_zeros)
+            let differences_or_zeros = difference_or_zero(loc, a, b, context);
+            context.new_binary_op(loc, BinaryOp::Minus, a.get_type(), a, differences_or_zeros)
         })
     }
 
-    fn vector_extremum(&mut self, a: RValue<'gcc>, b: RValue<'gcc>, direction: ExtremumOperation) -> RValue<'gcc> {
+    fn vector_extremum(
+        &mut self,
+        a: RValue<'gcc>,
+        b: RValue<'gcc>,
+        direction: ExtremumOperation,
+    ) -> RValue<'gcc> {
         let vector_type = a.get_type();
 
         // mask out the NaNs in b and replace them with the corresponding lane in a, so when a and
         // b get compared & spliced together, we get the numeric values instead of NaNs.
-        let b_nan_mask = self.context.new_comparison(None, ComparisonOp::NotEquals, b, b);
+        let b_nan_mask = self.context.new_comparison(self.location, ComparisonOp::NotEquals, b, b);
         let mask_type = b_nan_mask.get_type();
-        let b_nan_mask_inverted = self.context.new_unary_op(None, UnaryOp::BitwiseNegate, mask_type, b_nan_mask);
-        let a_cast = self.context.new_bitcast(None, a, mask_type);
-        let b_cast = self.context.new_bitcast(None, b, mask_type);
+        let b_nan_mask_inverted =
+            self.context.new_unary_op(self.location, UnaryOp::BitwiseNegate, mask_type, b_nan_mask);
+        let a_cast = self.context.new_bitcast(self.location, a, mask_type);
+        let b_cast = self.context.new_bitcast(self.location, b, mask_type);
         let res = (b_nan_mask & a_cast) | (b_nan_mask_inverted & b_cast);
-        let b = self.context.new_bitcast(None, res, vector_type);
+        let b = self.context.new_bitcast(self.location, res, vector_type);
 
         // now do the actual comparison
         let comparison_op = match direction {
             ExtremumOperation::Min => ComparisonOp::LessThan,
             ExtremumOperation::Max => ComparisonOp::GreaterThan,
         };
-        let cmp = self.context.new_comparison(None, comparison_op, a, b);
-        let cmp_inverted = self.context.new_unary_op(None, UnaryOp::BitwiseNegate, cmp.get_type(), cmp);
+        let cmp = self.context.new_comparison(self.location, comparison_op, a, b);
+        let cmp_inverted =
+            self.context.new_unary_op(self.location, UnaryOp::BitwiseNegate, cmp.get_type(), cmp);
         let res = (cmp & a_cast) | (cmp_inverted & res);
-        self.context.new_bitcast(None, res, vector_type)
+        self.context.new_bitcast(self.location, res, vector_type)
     }
 
     pub fn vector_fmin(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
         self.vector_extremum(a, b, ExtremumOperation::Min)
     }
 
-    #[cfg(feature="master")]
+    #[cfg(feature = "master")]
     pub fn vector_reduce_fmin(&mut self, src: RValue<'gcc>) -> RValue<'gcc> {
         let vector_type = src.get_type().unqualified().dyncast_vector().expect("vector type");
         let element_count = vector_type.get_num_units();
-        let mut acc = self.context.new_vector_access(None, src, self.context.new_rvalue_zero(self.int_type)).to_rvalue();
+        let mut acc = self
+            .context
+            .new_vector_access(self.location, src, self.context.new_rvalue_zero(self.int_type))
+            .to_rvalue();
         for i in 1..element_count {
-            let elem = self.context
-                .new_vector_access(None, src, self.context.new_rvalue_from_int(self.int_type, i as _))
+            let elem = self
+                .context
+                .new_vector_access(
+                    self.location,
+                    src,
+                    self.context.new_rvalue_from_int(self.int_type, i as _),
+                )
                 .to_rvalue();
-            let cmp = self.context.new_comparison(None, ComparisonOp::LessThan, acc, elem);
+            let cmp = self.context.new_comparison(self.location, ComparisonOp::LessThan, acc, elem);
             acc = self.select(cmp, acc, elem);
         }
         acc
     }
 
-    #[cfg(not(feature="master"))]
+    #[cfg(not(feature = "master"))]
     pub fn vector_reduce_fmin(&mut self, _src: RValue<'gcc>) -> RValue<'gcc> {
         unimplemented!();
     }
@@ -1836,36 +2224,51 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         self.vector_extremum(a, b, ExtremumOperation::Max)
     }
 
-    #[cfg(feature="master")]
+    #[cfg(feature = "master")]
     pub fn vector_reduce_fmax(&mut self, src: RValue<'gcc>) -> RValue<'gcc> {
         let vector_type = src.get_type().unqualified().dyncast_vector().expect("vector type");
         let element_count = vector_type.get_num_units();
-        let mut acc = self.context.new_vector_access(None, src, self.context.new_rvalue_zero(self.int_type)).to_rvalue();
+        let mut acc = self
+            .context
+            .new_vector_access(self.location, src, self.context.new_rvalue_zero(self.int_type))
+            .to_rvalue();
         for i in 1..element_count {
-            let elem = self.context
-                .new_vector_access(None, src, self.context.new_rvalue_from_int(self.int_type, i as _))
+            let elem = self
+                .context
+                .new_vector_access(
+                    self.location,
+                    src,
+                    self.context.new_rvalue_from_int(self.int_type, i as _),
+                )
                 .to_rvalue();
-            let cmp = self.context.new_comparison(None, ComparisonOp::GreaterThan, acc, elem);
+            let cmp =
+                self.context.new_comparison(self.location, ComparisonOp::GreaterThan, acc, elem);
             acc = self.select(cmp, acc, elem);
         }
         acc
     }
 
-    #[cfg(not(feature="master"))]
+    #[cfg(not(feature = "master"))]
     pub fn vector_reduce_fmax(&mut self, _src: RValue<'gcc>) -> RValue<'gcc> {
         unimplemented!();
     }
 
-    pub fn vector_select(&mut self, cond: RValue<'gcc>, then_val: RValue<'gcc>, else_val: RValue<'gcc>) -> RValue<'gcc> {
+    pub fn vector_select(
+        &mut self,
+        cond: RValue<'gcc>,
+        then_val: RValue<'gcc>,
+        else_val: RValue<'gcc>,
+    ) -> RValue<'gcc> {
         // cond is a vector of integers, not of bools.
         let vector_type = cond.get_type().unqualified().dyncast_vector().expect("vector type");
         let num_units = vector_type.get_num_units();
         let element_type = vector_type.get_element_type();
 
-        #[cfg(feature="master")]
+        #[cfg(feature = "master")]
         let (cond, element_type) = {
             // TODO(antoyo): dyncast_vector should not require a call to unqualified.
-            let then_val_vector_type = then_val.get_type().unqualified().dyncast_vector().expect("vector type");
+            let then_val_vector_type =
+                then_val.get_type().unqualified().dyncast_vector().expect("vector type");
             let then_val_element_type = then_val_vector_type.get_element_type();
             let then_val_element_size = then_val_element_type.get_size();
 
@@ -1873,11 +2276,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
             // operation to work.
             if then_val_element_size != element_type.get_size() {
                 let new_element_type = self.type_ix(then_val_element_size as u64 * 8);
-                let new_vector_type = self.context.new_vector_type(new_element_type, num_units as u64);
-                let cond = self.context.convert_vector(None, cond, new_vector_type);
+                let new_vector_type =
+                    self.context.new_vector_type(new_element_type, num_units as u64);
+                let cond = self.context.convert_vector(self.location, cond, new_vector_type);
                 (cond, new_element_type)
-            }
-            else {
+            } else {
                 (cond, element_type)
             }
         };
@@ -1885,24 +2288,25 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         let cond_type = cond.get_type();
 
         let zeros = vec![self.context.new_rvalue_zero(element_type); num_units];
-        let zeros = self.context.new_rvalue_from_vector(None, cond_type, &zeros);
+        let zeros = self.context.new_rvalue_from_vector(self.location, cond_type, &zeros);
 
         let result_type = then_val.get_type();
 
-        let masks = self.context.new_comparison(None, ComparisonOp::NotEquals, cond, zeros);
+        let masks =
+            self.context.new_comparison(self.location, ComparisonOp::NotEquals, cond, zeros);
         // NOTE: masks is a vector of integers, but the values can be vectors of floats, so use bitcast to make
         // the & operation work.
         let then_val = self.bitcast_if_needed(then_val, masks.get_type());
         let then_vals = masks & then_val;
 
         let minus_ones = vec![self.context.new_rvalue_from_int(element_type, -1); num_units];
-        let minus_ones = self.context.new_rvalue_from_vector(None, cond_type, &minus_ones);
+        let minus_ones = self.context.new_rvalue_from_vector(self.location, cond_type, &minus_ones);
         let inverted_masks = masks ^ minus_ones;
         // NOTE: sometimes, the type of else_val can be different than the type of then_val in
         // libgccjit (vector of int vs vector of int32_t), but they should be the same for the AND
         // operation to work.
         // TODO: remove bitcast now that vector types can be compared?
-        let else_val = self.context.new_bitcast(None, else_val, then_val.get_type());
+        let else_val = self.context.new_bitcast(self.location, else_val, then_val.get_type());
         let else_vals = inverted_masks & else_val;
 
         let res = then_vals | else_vals;
@@ -1910,26 +2314,26 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
     }
 }
 
-fn difference_or_zero<'gcc>(a: RValue<'gcc>, b: RValue<'gcc>, context: &'gcc Context<'gcc>) -> RValue<'gcc> {
+fn difference_or_zero<'gcc>(
+    loc: Option<Location<'gcc>>,
+    a: RValue<'gcc>,
+    b: RValue<'gcc>,
+    context: &'gcc Context<'gcc>,
+) -> RValue<'gcc> {
     let difference = a - b;
-    let masks = context.new_comparison(None, ComparisonOp::GreaterThanEquals, b, a);
+    let masks = context.new_comparison(loc, ComparisonOp::GreaterThanEquals, b, a);
     // NOTE: masks is a vector of integers, but the values can be vectors of floats, so use bitcast to make
     // the & operation work.
     let a_type = a.get_type();
     let masks =
-        if masks.get_type() != a_type {
-            context.new_bitcast(None, masks, a_type)
-        }
-        else {
-            masks
-        };
+        if masks.get_type() != a_type { context.new_bitcast(loc, masks, a_type) } else { masks };
     difference & masks
 }
 
 impl<'a, 'gcc, 'tcx> StaticBuilderMethods for Builder<'a, 'gcc, 'tcx> {
     fn get_static(&mut self, def_id: DefId) -> RValue<'gcc> {
         // Forward to the `get_static` method of `CodegenCx`
-        self.cx().get_static(def_id).get_address(None)
+        self.cx().get_static(def_id).get_address(self.location)
     }
 }
 
@@ -2009,15 +2413,14 @@ impl ToGccOrdering for AtomicOrdering {
     fn to_gcc(self) -> i32 {
         use MemOrdering::*;
 
-        let ordering =
-            match self {
-                AtomicOrdering::Unordered => __ATOMIC_RELAXED,
-                AtomicOrdering::Relaxed => __ATOMIC_RELAXED, // TODO(antoyo): check if that's the same.
-                AtomicOrdering::Acquire => __ATOMIC_ACQUIRE,
-                AtomicOrdering::Release => __ATOMIC_RELEASE,
-                AtomicOrdering::AcquireRelease => __ATOMIC_ACQ_REL,
-                AtomicOrdering::SequentiallyConsistent => __ATOMIC_SEQ_CST,
-            };
+        let ordering = match self {
+            AtomicOrdering::Unordered => __ATOMIC_RELAXED,
+            AtomicOrdering::Relaxed => __ATOMIC_RELAXED, // TODO(antoyo): check if that's the same.
+            AtomicOrdering::Acquire => __ATOMIC_ACQUIRE,
+            AtomicOrdering::Release => __ATOMIC_RELEASE,
+            AtomicOrdering::AcquireRelease => __ATOMIC_ACQ_REL,
+            AtomicOrdering::SequentiallyConsistent => __ATOMIC_SEQ_CST,
+        };
         ordering as i32
     }
 }
diff --git a/compiler/rustc_codegen_gcc/src/callee.rs b/compiler/rustc_codegen_gcc/src/callee.rs
index 9fc77627b1b..84f49b6856d 100644
--- a/compiler/rustc_codegen_gcc/src/callee.rs
+++ b/compiler/rustc_codegen_gcc/src/callee.rs
@@ -1,8 +1,8 @@
-#[cfg(feature="master")]
+#[cfg(feature = "master")]
 use gccjit::{FnAttribute, Visibility};
-use gccjit::{FunctionType, Function};
-use rustc_middle::ty::{self, Instance, TypeVisitableExt};
+use gccjit::{Function, FunctionType};
 use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
+use rustc_middle::ty::{self, Instance, TypeVisitableExt};
 
 use crate::attributes;
 use crate::context::CodegenCx;
@@ -28,145 +28,144 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>)
 
     let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
 
-    let func =
-        if let Some(_func) = cx.get_declared_value(&sym) {
-            // FIXME(antoyo): we never reach this because get_declared_value only returns global variables
-            // and here we try to get a function.
-            unreachable!();
-            /*
-            // Create a fn pointer with the new signature.
-            let ptrty = fn_abi.ptr_to_gcc_type(cx);
-
-            // This is subtle and surprising, but sometimes we have to bitcast
-            // the resulting fn pointer.  The reason has to do with external
-            // functions.  If you have two crates that both bind the same C
-            // library, they may not use precisely the same types: for
-            // example, they will probably each declare their own structs,
-            // which are distinct types from LLVM's point of view (nominal
-            // types).
-            //
-            // Now, if those two crates are linked into an application, and
-            // they contain inlined code, you can wind up with a situation
-            // where both of those functions wind up being loaded into this
-            // application simultaneously. In that case, the same function
-            // (from LLVM's point of view) requires two types. But of course
-            // LLVM won't allow one function to have two types.
-            //
-            // What we currently do, therefore, is declare the function with
-            // one of the two types (whichever happens to come first) and then
-            // bitcast as needed when the function is referenced to make sure
-            // it has the type we expect.
-            //
-            // This can occur on either a crate-local or crate-external
-            // reference. It also occurs when testing libcore and in some
-            // other weird situations. Annoying.
-            if cx.val_ty(func) != ptrty {
-                // TODO(antoyo): cast the pointer.
-                func
-            }
-            else {
-                func
-            }*/
+    let func = if let Some(_func) = cx.get_declared_value(&sym) {
+        // FIXME(antoyo): we never reach this because get_declared_value only returns global variables
+        // and here we try to get a function.
+        unreachable!();
+        /*
+        // Create a fn pointer with the new signature.
+        let ptrty = fn_abi.ptr_to_gcc_type(cx);
+
+        // This is subtle and surprising, but sometimes we have to bitcast
+        // the resulting fn pointer.  The reason has to do with external
+        // functions.  If you have two crates that both bind the same C
+        // library, they may not use precisely the same types: for
+        // example, they will probably each declare their own structs,
+        // which are distinct types from LLVM's point of view (nominal
+        // types).
+        //
+        // Now, if those two crates are linked into an application, and
+        // they contain inlined code, you can wind up with a situation
+        // where both of those functions wind up being loaded into this
+        // application simultaneously. In that case, the same function
+        // (from LLVM's point of view) requires two types. But of course
+        // LLVM won't allow one function to have two types.
+        //
+        // What we currently do, therefore, is declare the function with
+        // one of the two types (whichever happens to come first) and then
+        // bitcast as needed when the function is referenced to make sure
+        // it has the type we expect.
+        //
+        // This can occur on either a crate-local or crate-external
+        // reference. It also occurs when testing libcore and in some
+        // other weird situations. Annoying.
+        if cx.val_ty(func) != ptrty {
+            // TODO(antoyo): cast the pointer.
+            func
         }
         else {
-            cx.linkage.set(FunctionType::Extern);
-            let func = cx.declare_fn(&sym, &fn_abi);
-
-            attributes::from_fn_attrs(cx, func, instance);
-
-            let instance_def_id = instance.def_id();
-
-            // TODO(antoyo): set linkage and attributes.
-
-            // Apply an appropriate linkage/visibility value to our item that we
-            // just declared.
-            //
-            // This is sort of subtle. Inside our codegen unit we started off
-            // compilation by predefining all our own `MonoItem` instances. That
-            // is, everything we're codegenning ourselves is already defined. That
-            // means that anything we're actually codegenning in this codegen unit
-            // will have hit the above branch in `get_declared_value`. As a result,
-            // we're guaranteed here that we're declaring a symbol that won't get
-            // defined, or in other words we're referencing a value from another
-            // codegen unit or even another crate.
-            //
-            // So because this is a foreign value we blanket apply an external
-            // linkage directive because it's coming from a different object file.
-            // The visibility here is where it gets tricky. This symbol could be
-            // referencing some foreign crate or foreign library (an `extern`
-            // block) in which case we want to leave the default visibility. We may
-            // also, though, have multiple codegen units. It could be a
-            // monomorphization, in which case its expected visibility depends on
-            // whether we are sharing generics or not. The important thing here is
-            // that the visibility we apply to the declaration is the same one that
-            // has been applied to the definition (wherever that definition may be).
-            let is_generic = instance.args.non_erasable_generics(tcx, instance.def_id()).next().is_some();
-
-            if is_generic {
-                // This is a monomorphization. Its expected visibility depends
-                // on whether we are in share-generics mode.
-
-                if cx.tcx.sess.opts.share_generics() {
-                    // We are in share_generics mode.
-
-                    if let Some(instance_def_id) = instance_def_id.as_local() {
-                        // This is a definition from the current crate. If the
-                        // definition is unreachable for downstream crates or
-                        // the current crate does not re-export generics, the
-                        // definition of the instance will have been declared
-                        // as `hidden`.
-                        if cx.tcx.is_unreachable_local_definition(instance_def_id)
-                            || !cx.tcx.local_crate_exports_generics()
-                        {
-                            #[cfg(feature="master")]
-                            func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
-                        }
+            func
+        }*/
+    } else {
+        cx.linkage.set(FunctionType::Extern);
+        let func = cx.declare_fn(&sym, &fn_abi);
+
+        attributes::from_fn_attrs(cx, func, instance);
+
+        let instance_def_id = instance.def_id();
+
+        // TODO(antoyo): set linkage and attributes.
+
+        // Apply an appropriate linkage/visibility value to our item that we
+        // just declared.
+        //
+        // This is sort of subtle. Inside our codegen unit we started off
+        // compilation by predefining all our own `MonoItem` instances. That
+        // is, everything we're codegenning ourselves is already defined. That
+        // means that anything we're actually codegenning in this codegen unit
+        // will have hit the above branch in `get_declared_value`. As a result,
+        // we're guaranteed here that we're declaring a symbol that won't get
+        // defined, or in other words we're referencing a value from another
+        // codegen unit or even another crate.
+        //
+        // So because this is a foreign value we blanket apply an external
+        // linkage directive because it's coming from a different object file.
+        // The visibility here is where it gets tricky. This symbol could be
+        // referencing some foreign crate or foreign library (an `extern`
+        // block) in which case we want to leave the default visibility. We may
+        // also, though, have multiple codegen units. It could be a
+        // monomorphization, in which case its expected visibility depends on
+        // whether we are sharing generics or not. The important thing here is
+        // that the visibility we apply to the declaration is the same one that
+        // has been applied to the definition (wherever that definition may be).
+        let is_generic =
+            instance.args.non_erasable_generics(tcx, instance.def_id()).next().is_some();
+
+        if is_generic {
+            // This is a monomorphization. Its expected visibility depends
+            // on whether we are in share-generics mode.
+
+            if cx.tcx.sess.opts.share_generics() {
+                // We are in share_generics mode.
+
+                if let Some(instance_def_id) = instance_def_id.as_local() {
+                    // This is a definition from the current crate. If the
+                    // definition is unreachable for downstream crates or
+                    // the current crate does not re-export generics, the
+                    // definition of the instance will have been declared
+                    // as `hidden`.
+                    if cx.tcx.is_unreachable_local_definition(instance_def_id)
+                        || !cx.tcx.local_crate_exports_generics()
+                    {
+                        #[cfg(feature = "master")]
+                        func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
+                    }
+                } else {
+                    // This is a monomorphization of a generic function
+                    // defined in an upstream crate.
+                    if instance.upstream_monomorphization(tcx).is_some() {
+                        // This is instantiated in another crate. It cannot
+                        // be `hidden`.
                     } else {
-                        // This is a monomorphization of a generic function
-                        // defined in an upstream crate.
-                        if instance.upstream_monomorphization(tcx).is_some() {
-                            // This is instantiated in another crate. It cannot
-                            // be `hidden`.
-                        } else {
-                            // This is a local instantiation of an upstream definition.
-                            // If the current crate does not re-export it
-                            // (because it is a C library or an executable), it
-                            // will have been declared `hidden`.
-                            if !cx.tcx.local_crate_exports_generics() {
-                                #[cfg(feature="master")]
-                                func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
-                            }
+                        // This is a local instantiation of an upstream definition.
+                        // If the current crate does not re-export it
+                        // (because it is a C library or an executable), it
+                        // will have been declared `hidden`.
+                        if !cx.tcx.local_crate_exports_generics() {
+                            #[cfg(feature = "master")]
+                            func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
                         }
                     }
-                } else {
-                    // When not sharing generics, all instances are in the same
-                    // crate and have hidden visibility
-                    #[cfg(feature="master")]
-                    func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
                 }
             } else {
-                // This is a non-generic function
-                if cx.tcx.is_codegened_item(instance_def_id) {
-                    // This is a function that is instantiated in the local crate
-
-                    if instance_def_id.is_local() {
-                        // This is function that is defined in the local crate.
-                        // If it is not reachable, it is hidden.
-                        if !cx.tcx.is_reachable_non_generic(instance_def_id) {
-                            #[cfg(feature="master")]
-                            func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
-                        }
-                    } else {
-                        // This is a function from an upstream crate that has
-                        // been instantiated here. These are always hidden.
-                        #[cfg(feature="master")]
+                // When not sharing generics, all instances are in the same
+                // crate and have hidden visibility
+                #[cfg(feature = "master")]
+                func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
+            }
+        } else {
+            // This is a non-generic function
+            if cx.tcx.is_codegened_item(instance_def_id) {
+                // This is a function that is instantiated in the local crate
+
+                if instance_def_id.is_local() {
+                    // This is function that is defined in the local crate.
+                    // If it is not reachable, it is hidden.
+                    if !cx.tcx.is_reachable_non_generic(instance_def_id) {
+                        #[cfg(feature = "master")]
                         func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
                     }
+                } else {
+                    // This is a function from an upstream crate that has
+                    // been instantiated here. These are always hidden.
+                    #[cfg(feature = "master")]
+                    func.add_attribute(FnAttribute::Visibility(Visibility::Hidden));
                 }
             }
+        }
 
-            func
-        };
+        func
+    };
 
     cx.function_instances.borrow_mut().insert(instance, func);
 
diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs
index c6edd52d1e4..d243d7088ad 100644
--- a/compiler/rustc_codegen_gcc/src/common.rs
+++ b/compiler/rustc_codegen_gcc/src/common.rs
@@ -1,14 +1,9 @@
 use gccjit::LValue;
-use gccjit::{RValue, Type, ToRValue};
-use rustc_codegen_ssa::traits::{
-    BaseTypeMethods,
-    ConstMethods,
-    MiscMethods,
-    StaticMethods,
-};
-use rustc_middle::mir::Mutability;
-use rustc_middle::ty::layout::{LayoutOf};
+use gccjit::{RValue, ToRValue, Type};
+use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods, MiscMethods, StaticMethods};
 use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
+use rustc_middle::mir::Mutability;
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_target::abi::{self, HasDataLayout, Pointer};
 
 use crate::consts::const_alloc_to_gcc;
@@ -40,9 +35,7 @@ pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) ->
     let byte_type = context.new_type::<u8>();
     let typ = context.new_array_type(None, byte_type, bytes.len() as u64);
     let elements: Vec<_> =
-        bytes.iter()
-        .map(|&byte| context.new_rvalue_from_int(byte_type, byte as i32))
-        .collect();
+        bytes.iter().map(|&byte| context.new_rvalue_from_int(byte_type, byte as i32)).collect();
     context.new_array_constructor(None, typ, &elements)
 }
 
@@ -54,23 +47,20 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     fn const_null(&self, typ: Type<'gcc>) -> RValue<'gcc> {
         if type_is_pointer(typ) {
             self.context.new_null(typ)
-        }
-        else {
+        } else {
             self.const_int(typ, 0)
         }
     }
 
     fn const_undef(&self, typ: Type<'gcc>) -> RValue<'gcc> {
-        let local = self.current_func.borrow().expect("func")
-            .new_local(None, typ, "undefined");
+        let local = self.current_func.borrow().expect("func").new_local(None, typ, "undefined");
         if typ.is_struct().is_some() {
             // NOTE: hack to workaround a limitation of the rustc API: see comment on
             // CodegenCx.structs_as_pointer
             let pointer = local.get_address(None);
             self.structs_as_pointer.borrow_mut().insert(pointer);
             pointer
-        }
-        else {
+        } else {
             local.to_rvalue()
         }
     }
@@ -143,16 +133,15 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
             .or_insert_with(|| (s.to_owned(), self.global_string(s)))
             .1;
         let len = s.len();
-        let cs = self.const_ptrcast(str_global.get_address(None),
+        let cs = self.const_ptrcast(
+            str_global.get_address(None),
             self.type_ptr_to(self.layout_of(self.tcx.types.str_).gcc_type(self)),
         );
         (cs, self.const_usize(len as u64))
     }
 
     fn const_struct(&self, values: &[RValue<'gcc>], packed: bool) -> RValue<'gcc> {
-        let fields: Vec<_> = values.iter()
-            .map(|value| value.get_type())
-            .collect();
+        let fields: Vec<_> = values.iter().map(|value| value.get_type()).collect();
         // TODO(antoyo): cache the type? It's anonymous, so probably not.
         let typ = self.type_struct(&fields, packed);
         let struct_type = typ.is_struct().expect("struct type");
@@ -178,9 +167,10 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
                 // FIXME(antoyo): there's some issues with using the u128 code that follows, so hard-code
                 // the paths for floating-point values.
                 if ty == self.float_type {
-                    return self.context.new_rvalue_from_double(ty, f32::from_bits(data as u32) as f64);
-                }
-                else if ty == self.double_type {
+                    return self
+                        .context
+                        .new_rvalue_from_double(ty, f32::from_bits(data as u32) as f64);
+                } else if ty == self.double_type {
                     return self.context.new_rvalue_from_double(ty, f64::from_bits(data as u64));
                 }
 
@@ -192,8 +182,7 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
                     // FIXME(antoyo): fix bitcast to work in constant contexts.
                     // TODO(antoyo): perhaps only use bitcast for pointers?
                     self.context.new_cast(None, value, ty)
-                }
-                else {
+                } else {
                     // TODO(bjorn3): assert size is correct
                     self.const_bitcast(value, ty)
                 }
@@ -201,42 +190,41 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
             Scalar::Ptr(ptr, _size) => {
                 let (prov, offset) = ptr.into_parts(); // we know the `offset` is relative
                 let alloc_id = prov.alloc_id();
-                let base_addr =
-                    match self.tcx.global_alloc(alloc_id) {
-                        GlobalAlloc::Memory(alloc) => {
-                            let init = const_alloc_to_gcc(self, alloc);
-                            let alloc = alloc.inner();
-                            let value =
-                                match alloc.mutability {
-                                    Mutability::Mut => self.static_addr_of_mut(init, alloc.align, None),
-                                    _ => self.static_addr_of(init, alloc.align, None),
-                                };
-                            if !self.sess().fewer_names() {
-                                // TODO(antoyo): set value name.
-                            }
-                            value
-                        },
-                        GlobalAlloc::Function(fn_instance) => {
-                            self.get_fn_addr(fn_instance)
-                        },
-                        GlobalAlloc::VTable(ty, trait_ref) => {
-                            let alloc = self.tcx.global_alloc(self.tcx.vtable_allocation((ty, trait_ref))).unwrap_memory();
-                            let init = const_alloc_to_gcc(self, alloc);
-                            self.static_addr_of(init, alloc.inner().align, None)
+                let base_addr = match self.tcx.global_alloc(alloc_id) {
+                    GlobalAlloc::Memory(alloc) => {
+                        let init = const_alloc_to_gcc(self, alloc);
+                        let alloc = alloc.inner();
+                        let value = match alloc.mutability {
+                            Mutability::Mut => self.static_addr_of_mut(init, alloc.align, None),
+                            _ => self.static_addr_of(init, alloc.align, None),
+                        };
+                        if !self.sess().fewer_names() {
+                            // TODO(antoyo): set value name.
                         }
-                        GlobalAlloc::Static(def_id) => {
-                            assert!(self.tcx.is_static(def_id));
-                            self.get_static(def_id).get_address(None)
-                        },
-                    };
+                        value
+                    }
+                    GlobalAlloc::Function(fn_instance) => self.get_fn_addr(fn_instance),
+                    GlobalAlloc::VTable(ty, trait_ref) => {
+                        let alloc = self
+                            .tcx
+                            .global_alloc(self.tcx.vtable_allocation((ty, trait_ref)))
+                            .unwrap_memory();
+                        let init = const_alloc_to_gcc(self, alloc);
+                        self.static_addr_of(init, alloc.inner().align, None)
+                    }
+                    GlobalAlloc::Static(def_id) => {
+                        assert!(self.tcx.is_static(def_id));
+                        self.get_static(def_id).get_address(None)
+                    }
+                };
                 let ptr_type = base_addr.get_type();
                 let base_addr = self.const_bitcast(base_addr, self.usize_type);
-                let offset = self.context.new_rvalue_from_long(self.usize_type, offset.bytes() as i64);
+                let offset =
+                    self.context.new_rvalue_from_long(self.usize_type, offset.bytes() as i64);
                 let ptr = self.const_bitcast(base_addr + offset, ptr_type);
                 if !matches!(layout.primitive(), Pointer(_)) {
                     self.const_bitcast(ptr.dereference(None).to_rvalue(), ty)
-                }
-                else {
+                } else {
                     self.const_bitcast(ptr, ty)
                 }
             }
@@ -261,7 +249,9 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     }
 
     fn const_ptr_byte_offset(&self, base_addr: Self::Value, offset: abi::Size) -> Self::Value {
-        self.context.new_array_access(None, base_addr, self.const_usize(offset.bytes())).get_address(None)
+        self.context
+            .new_array_access(None, base_addr, self.const_usize(offset.bytes()))
+            .get_address(None)
     }
 }
 
@@ -284,35 +274,25 @@ impl<'gcc, 'tcx> SignType<'gcc, 'tcx> for Type<'gcc> {
     fn to_signed(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> {
         if self.is_u8(cx) {
             cx.i8_type
-        }
-        else if self.is_u16(cx) {
+        } else if self.is_u16(cx) {
             cx.i16_type
-        }
-        else if self.is_u32(cx) {
+        } else if self.is_u32(cx) {
             cx.i32_type
-        }
-        else if self.is_u64(cx) {
+        } else if self.is_u64(cx) {
             cx.i64_type
-        }
-        else if self.is_u128(cx) {
+        } else if self.is_u128(cx) {
             cx.i128_type
-        }
-        else if self.is_uchar(cx) {
+        } else if self.is_uchar(cx) {
             cx.char_type
-        }
-        else if self.is_ushort(cx) {
+        } else if self.is_ushort(cx) {
             cx.short_type
-        }
-        else if self.is_uint(cx) {
+        } else if self.is_uint(cx) {
             cx.int_type
-        }
-        else if self.is_ulong(cx) {
+        } else if self.is_ulong(cx) {
             cx.long_type
-        }
-        else if self.is_ulonglong(cx) {
+        } else if self.is_ulonglong(cx) {
             cx.longlong_type
-        }
-        else {
+        } else {
             self.clone()
         }
     }
@@ -320,41 +300,31 @@ impl<'gcc, 'tcx> SignType<'gcc, 'tcx> for Type<'gcc> {
     fn to_unsigned(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc> {
         if self.is_i8(cx) {
             cx.u8_type
-        }
-        else if self.is_i16(cx) {
+        } else if self.is_i16(cx) {
             cx.u16_type
-        }
-        else if self.is_i32(cx) {
+        } else if self.is_i32(cx) {
             cx.u32_type
-        }
-        else if self.is_i64(cx) {
+        } else if self.is_i64(cx) {
             cx.u64_type
-        }
-        else if self.is_i128(cx) {
+        } else if self.is_i128(cx) {
             cx.u128_type
-        }
-        else if self.is_char(cx) {
+        } else if self.is_char(cx) {
             cx.uchar_type
-        }
-        else if self.is_short(cx) {
+        } else if self.is_short(cx) {
             cx.ushort_type
-        }
-        else if self.is_int(cx) {
+        } else if self.is_int(cx) {
             cx.uint_type
-        }
-        else if self.is_long(cx) {
+        } else if self.is_long(cx) {
             cx.ulong_type
-        }
-        else if self.is_longlong(cx) {
+        } else if self.is_longlong(cx) {
             cx.ulonglong_type
-        }
-        else {
+        } else {
             self.clone()
         }
     }
 }
 
-pub trait TypeReflection<'gcc, 'tcx>  {
+pub trait TypeReflection<'gcc, 'tcx> {
     fn is_uchar(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool;
     fn is_ushort(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool;
     fn is_uint(&self, cx: &CodegenCx<'gcc, 'tcx>) -> bool;
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs
index 70d8db02247..327c9bdada9 100644
--- a/compiler/rustc_codegen_gcc/src/consts.rs
+++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -2,12 +2,14 @@
 use gccjit::{FnAttribute, VarAttribute, Visibility};
 use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue};
 use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods, DerivedTypeMethods, StaticMethods};
-use rustc_middle::span_bug;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
+use rustc_middle::mir::interpret::{
+    self, read_target_uint, ConstAllocation, ErrorHandled, Scalar as InterpScalar,
+};
 use rustc_middle::mir::mono::MonoItem;
-use rustc_middle::ty::{self, Instance, Ty};
+use rustc_middle::span_bug;
 use rustc_middle::ty::layout::LayoutOf;
-use rustc_middle::mir::interpret::{self, ConstAllocation, ErrorHandled, Scalar as InterpScalar, read_target_uint};
+use rustc_middle::ty::{self, Instance, Ty};
 use rustc_span::def_id::DefId;
 use rustc_target::abi::{self, Align, HasDataLayout, Primitive, Size, WrappingRange};
 
@@ -16,7 +18,11 @@ use crate::context::CodegenCx;
 use crate::errors::InvalidMinimumAlignment;
 use crate::type_of::LayoutGccExt;
 
-fn set_global_alignment<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, gv: LValue<'gcc>, mut align: Align) {
+fn set_global_alignment<'gcc, 'tcx>(
+    cx: &CodegenCx<'gcc, 'tcx>,
+    gv: LValue<'gcc>,
+    mut align: Align,
+) {
     // The target may require greater alignment for globals than the type does.
     // Note: GCC and Clang also allow `__attribute__((aligned))` on variables,
     // which can force it to be smaller. Rust doesn't support this yet.
@@ -48,7 +54,9 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
         }
         let global_value = self.static_addr_of_mut(cv, align, kind);
         #[cfg(feature = "master")]
-        self.global_lvalues.borrow().get(&global_value)
+        self.global_lvalues
+            .borrow()
+            .get(&global_value)
             .expect("`static_addr_of_mut` did not add the global to `self.global_lvalues`")
             .global_set_readonly();
         self.const_globals.borrow_mut().insert(cv, global_value);
@@ -58,25 +66,20 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
     fn codegen_static(&self, def_id: DefId, is_mutable: bool) {
         let attrs = self.tcx.codegen_fn_attrs(def_id);
 
-        let value =
-            match codegen_static_initializer(&self, def_id) {
-                Ok((value, _)) => value,
-                // Error has already been reported
-                Err(_) => return,
-            };
+        let value = match codegen_static_initializer(&self, def_id) {
+            Ok((value, _)) => value,
+            // Error has already been reported
+            Err(_) => return,
+        };
 
         let global = self.get_static(def_id);
 
         // boolean SSA values are i1, but they have to be stored in i8 slots,
         // otherwise some LLVM optimization passes don't work as expected
         let val_llty = self.val_ty(value);
-        let value =
-            if val_llty == self.type_i1() {
-                unimplemented!();
-            }
-            else {
-                value
-            };
+        if val_llty == self.type_i1() {
+            unimplemented!();
+        };
 
         let instance = Instance::mono(self.tcx, def_id);
         let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all());
@@ -89,11 +92,9 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
 
         // As an optimization, all shared statics which do not have interior
         // mutability are placed into read-only memory.
-        if !is_mutable {
-            if self.type_is_freeze(ty) {
-                #[cfg(feature = "master")]
-                global.global_set_readonly();
-            }
+        if !is_mutable && self.type_is_freeze(ty) {
+            #[cfg(feature = "master")]
+            global.global_set_readonly();
         }
 
         if attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) {
@@ -149,7 +150,9 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
             // TODO(antoyo): set link section.
         }
 
-        if attrs.flags.contains(CodegenFnAttrFlags::USED) || attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) {
+        if attrs.flags.contains(CodegenFnAttrFlags::USED)
+            || attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
+        {
             self.add_used_global(global.to_rvalue());
         }
     }
@@ -166,29 +169,33 @@ impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
 }
 
 impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
-    #[cfg_attr(not(feature="master"), allow(unused_variables))]
+    #[cfg_attr(not(feature = "master"), allow(unused_variables))]
     pub fn add_used_function(&self, function: Function<'gcc>) {
         #[cfg(feature = "master")]
         function.add_attribute(FnAttribute::Used);
     }
 
-    pub fn static_addr_of_mut(&self, cv: RValue<'gcc>, align: Align, kind: Option<&str>) -> RValue<'gcc> {
-        let global =
-            match kind {
-                Some(kind) if !self.tcx.sess.fewer_names() => {
-                    let name = self.generate_local_symbol_name(kind);
-                    // TODO(antoyo): check if it's okay that no link_section is set.
-
-                    let typ = self.val_ty(cv).get_aligned(align.bytes());
-                    let global = self.declare_private_global(&name[..], typ);
-                    global
-                }
-                _ => {
-                    let typ = self.val_ty(cv).get_aligned(align.bytes());
-                    let global = self.declare_unnamed_global(typ);
-                    global
-                },
-            };
+    pub fn static_addr_of_mut(
+        &self,
+        cv: RValue<'gcc>,
+        align: Align,
+        kind: Option<&str>,
+    ) -> RValue<'gcc> {
+        let global = match kind {
+            Some(kind) if !self.tcx.sess.fewer_names() => {
+                let name = self.generate_local_symbol_name(kind);
+                // TODO(antoyo): check if it's okay that no link_section is set.
+
+                let typ = self.val_ty(cv).get_aligned(align.bytes());
+                let global = self.declare_private_global(&name[..], typ);
+                global
+            }
+            _ => {
+                let typ = self.val_ty(cv).get_aligned(align.bytes());
+                let global = self.declare_unnamed_global(typ);
+                global
+            }
+        };
         global.global_set_initializer_rvalue(cv);
         // TODO(antoyo): set unnamed address.
         let rvalue = global.get_address(None);
@@ -215,8 +222,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all());
         let sym = self.tcx.symbol_name(instance).name;
 
-        let global =
-            if def_id.is_local() && !self.tcx.is_foreign_item(def_id) {
+        let global = if def_id.is_local() && !self.tcx.is_foreign_item(def_id) {
             let llty = self.layout_of(ty).gcc_type(self);
             if let Some(global) = self.get_declared_value(sym) {
                 if self.val_ty(global) != self.type_ptr_to(llty) {
@@ -235,7 +241,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
 
             if !self.tcx.is_reachable_non_generic(def_id) {
                 #[cfg(feature = "master")]
-                global.add_attribute(VarAttribute::Visibility(Visibility::Hidden));
+                global.add_string_attribute(VarAttribute::Visibility(Visibility::Hidden));
             }
 
             global
@@ -278,7 +284,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
     }
 }
 
-pub fn const_alloc_to_gcc<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, alloc: ConstAllocation<'tcx>) -> RValue<'gcc> {
+pub fn const_alloc_to_gcc<'gcc, 'tcx>(
+    cx: &CodegenCx<'gcc, 'tcx>,
+    alloc: ConstAllocation<'tcx>,
+) -> RValue<'gcc> {
     let alloc = alloc.inner();
     let mut llvals = Vec::with_capacity(alloc.provenance().ptrs().len() + 1);
     let dl = cx.data_layout();
@@ -300,14 +309,14 @@ pub fn const_alloc_to_gcc<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, alloc: ConstAl
             let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(next_offset..offset);
             llvals.push(cx.const_bytes(bytes));
         }
-        let ptr_offset =
-            read_target_uint( dl.endian,
-                // This `inspect` is okay since it is within the bounds of the allocation, it doesn't
-                // affect interpreter execution (we inspect the result after interpreter execution),
-                // and we properly interpret the provenance as a relocation pointer offset.
-                alloc.inspect_with_uninit_and_ptr_outside_interpreter(offset..(offset + pointer_size)),
-            )
-            .expect("const_alloc_to_llvm: could not read relocation pointer")
+        let ptr_offset = read_target_uint(
+            dl.endian,
+            // This `inspect` is okay since it is within the bounds of the allocation, it doesn't
+            // affect interpreter execution (we inspect the result after interpreter execution),
+            // and we properly interpret the provenance as a relocation pointer offset.
+            alloc.inspect_with_uninit_and_ptr_outside_interpreter(offset..(offset + pointer_size)),
+        )
+        .expect("const_alloc_to_llvm: could not read relocation pointer")
             as u64;
 
         let address_space = cx.tcx.global_alloc(alloc_id).address_space(cx);
@@ -317,7 +326,10 @@ pub fn const_alloc_to_gcc<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, alloc: ConstAl
                 interpret::Pointer::new(prov, Size::from_bytes(ptr_offset)),
                 &cx.tcx,
             ),
-            abi::Scalar::Initialized { value: Primitive::Pointer(address_space), valid_range: WrappingRange::full(dl.pointer_size) },
+            abi::Scalar::Initialized {
+                value: Primitive::Pointer(address_space),
+                valid_range: WrappingRange::full(dl.pointer_size),
+            },
             cx.type_i8p_ext(address_space),
         ));
         next_offset = offset + pointer_size;
@@ -337,17 +349,29 @@ pub fn const_alloc_to_gcc<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, alloc: ConstAl
     cx.const_struct(&llvals, true)
 }
 
-pub fn codegen_static_initializer<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, def_id: DefId) -> Result<(RValue<'gcc>, ConstAllocation<'tcx>), ErrorHandled> {
+pub fn codegen_static_initializer<'gcc, 'tcx>(
+    cx: &CodegenCx<'gcc, 'tcx>,
+    def_id: DefId,
+) -> Result<(RValue<'gcc>, ConstAllocation<'tcx>), ErrorHandled> {
     let alloc = cx.tcx.eval_static_initializer(def_id)?;
     Ok((const_alloc_to_gcc(cx, alloc), alloc))
 }
 
-fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &CodegenFnAttrs, ty: Ty<'tcx>, sym: &str) -> LValue<'gcc> {
+fn check_and_apply_linkage<'gcc, 'tcx>(
+    cx: &CodegenCx<'gcc, 'tcx>,
+    attrs: &CodegenFnAttrs,
+    ty: Ty<'tcx>,
+    sym: &str,
+) -> LValue<'gcc> {
     let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL);
     let gcc_type = cx.layout_of(ty).gcc_type(cx);
     if let Some(linkage) = attrs.import_linkage {
         // Declare a symbol `foo` with the desired linkage.
-        let global1 = cx.declare_global_with_linkage(&sym, cx.type_i8(), base::global_linkage_to_gcc(linkage));
+        let global1 = cx.declare_global_with_linkage(
+            &sym,
+            cx.type_i8(),
+            base::global_linkage_to_gcc(linkage),
+        );
 
         // Declare an internal global `extern_with_linkage_foo` which
         // is initialized with the address of `foo`.  If `foo` is
@@ -363,8 +387,7 @@ fn check_and_apply_linkage<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, attrs: &Codeg
         global2.global_set_initializer_rvalue(value);
         // TODO(antoyo): use global_set_initializer() when it will work.
         global2
-    }
-    else {
+    } else {
         // Generate an external declaration.
         // FIXME(nagisa): investigate whether it can be changed into define_global
 
diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs
index 5760d96165d..8f643c7db72 100644
--- a/compiler/rustc_codegen_gcc/src/context.rs
+++ b/compiler/rustc_codegen_gcc/src/context.rs
@@ -1,22 +1,25 @@
 use std::cell::{Cell, RefCell};
 
-use gccjit::{Block, CType, Context, Function, FunctionPtrType, FunctionType, LValue, RValue, Type};
-use rustc_codegen_ssa::base::wants_msvc_seh;
-use rustc_codegen_ssa::traits::{
-    BackendTypes,
-    BaseTypeMethods,
-    MiscMethods,
+use gccjit::{
+    Block, CType, Context, Function, FunctionPtrType, FunctionType, LValue, Location, RValue, Type,
 };
+use rustc_codegen_ssa::base::wants_msvc_seh;
 use rustc_codegen_ssa::errors as ssa_errors;
+use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeMethods, MiscMethods};
 use rustc_data_structures::base_n;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_middle::span_bug;
 use rustc_middle::mir::mono::CodegenUnit;
+use rustc_middle::span_bug;
+use rustc_middle::ty::layout::{
+    FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError,
+    LayoutOfHelpers, TyAndLayout,
+};
 use rustc_middle::ty::{self, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt};
-use rustc_middle::ty::layout::{FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, HasTyCtxt, LayoutError, TyAndLayout, LayoutOfHelpers};
 use rustc_session::Session;
-use rustc_span::{Span, source_map::respan};
-use rustc_target::abi::{call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
+use rustc_span::{source_map::respan, Span};
+use rustc_target::abi::{
+    call::FnAbi, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx,
+};
 use rustc_target::spec::{HasTargetSpec, Target, TlsModel};
 
 use crate::callee::get_fn;
@@ -81,7 +84,8 @@ pub struct CodegenCx<'gcc, 'tcx> {
     /// Cache function instances of monomorphic and polymorphic items
     pub function_instances: RefCell<FxHashMap<Instance<'tcx>, Function<'gcc>>>,
     /// Cache generated vtables
-    pub vtables: RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>>,
+    pub vtables:
+        RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>>,
 
     // TODO(antoyo): improve the SSA API to not require those.
     /// Mapping from function pointer type to indexes of on stack parameters.
@@ -121,24 +125,28 @@ pub struct CodegenCx<'gcc, 'tcx> {
 }
 
 impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
-    pub fn new(context: &'gcc Context<'gcc>, codegen_unit: &'tcx CodegenUnit<'tcx>, tcx: TyCtxt<'tcx>, supports_128bit_integers: bool) -> Self {
+    pub fn new(
+        context: &'gcc Context<'gcc>,
+        codegen_unit: &'tcx CodegenUnit<'tcx>,
+        tcx: TyCtxt<'tcx>,
+        supports_128bit_integers: bool,
+    ) -> Self {
         let check_overflow = tcx.sess.overflow_checks();
 
         let create_type = |ctype, rust_type| {
             let layout = tcx.layout_of(ParamEnv::reveal_all().and(rust_type)).unwrap();
             let align = layout.align.abi.bytes();
-            #[cfg(feature="master")]
+            #[cfg(feature = "master")]
             {
                 context.new_c_type(ctype).get_aligned(align)
             }
-            #[cfg(not(feature="master"))]
+            #[cfg(not(feature = "master"))]
             {
                 // Since libgccjit 12 doesn't contain the fix to compare aligned integer types,
                 // only align u128 and i128.
                 if layout.ty.int_size_and_signed(tcx).0.bytes() == 16 {
                     context.new_c_type(ctype).get_aligned(align)
-                }
-                else {
+                } else {
                     context.new_c_type(ctype)
                 }
             }
@@ -153,24 +161,22 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         let u32_type = create_type(CType::UInt32t, tcx.types.u32);
         let u64_type = create_type(CType::UInt64t, tcx.types.u64);
 
-        let (i128_type, u128_type) =
-            if supports_128bit_integers {
-                let i128_type = create_type(CType::Int128t, tcx.types.i128);
-                let u128_type = create_type(CType::UInt128t, tcx.types.u128);
-                (i128_type, u128_type)
-            }
-            else {
-                /*let layout = tcx.layout_of(ParamEnv::reveal_all().and(tcx.types.i128)).unwrap();
-                let i128_align = layout.align.abi.bytes();
-                let layout = tcx.layout_of(ParamEnv::reveal_all().and(tcx.types.u128)).unwrap();
-                let u128_align = layout.align.abi.bytes();*/
-
-                // TODO(antoyo): re-enable the alignment when libgccjit fixed the issue in
-                // gcc_jit_context_new_array_constructor (it should not use reinterpret_cast).
-                let i128_type = context.new_array_type(None, i64_type, 2)/*.get_aligned(i128_align)*/;
-                let u128_type = context.new_array_type(None, u64_type, 2)/*.get_aligned(u128_align)*/;
-                (i128_type, u128_type)
-            };
+        let (i128_type, u128_type) = if supports_128bit_integers {
+            let i128_type = create_type(CType::Int128t, tcx.types.i128);
+            let u128_type = create_type(CType::UInt128t, tcx.types.u128);
+            (i128_type, u128_type)
+        } else {
+            /*let layout = tcx.layout_of(ParamEnv::reveal_all().and(tcx.types.i128)).unwrap();
+            let i128_align = layout.align.abi.bytes();
+            let layout = tcx.layout_of(ParamEnv::reveal_all().and(tcx.types.u128)).unwrap();
+            let u128_align = layout.align.abi.bytes();*/
+
+            // TODO(antoyo): re-enable the alignment when libgccjit fixed the issue in
+            // gcc_jit_context_new_array_constructor (it should not use reinterpret_cast).
+            let i128_type = context.new_array_type(None, i64_type, 2)/*.get_aligned(i128_align)*/;
+            let u128_type = context.new_array_type(None, u64_type, 2)/*.get_aligned(u128_align)*/;
+            (i128_type, u128_type)
+        };
 
         let tls_model = to_gcc_tls_mode(tcx.sess.tls_model());
 
@@ -196,16 +202,65 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
 
         let mut functions = FxHashMap::default();
         let builtins = [
-            "__builtin_unreachable", "abort", "__builtin_expect", /*"__builtin_expect_with_probability",*/
-            "__builtin_constant_p", "__builtin_add_overflow", "__builtin_mul_overflow", "__builtin_saddll_overflow",
-            /*"__builtin_sadd_overflow",*/ "__builtin_smulll_overflow", /*"__builtin_smul_overflow",*/
-            "__builtin_ssubll_overflow", /*"__builtin_ssub_overflow",*/ "__builtin_sub_overflow", "__builtin_uaddll_overflow",
-            "__builtin_uadd_overflow", "__builtin_umulll_overflow", "__builtin_umul_overflow", "__builtin_usubll_overflow",
-            "__builtin_usub_overflow", "sqrtf", "sqrt", "__builtin_powif", "__builtin_powi", "sinf", "sin", "cosf", "cos",
-            "powf", "pow", "expf", "exp", "exp2f", "exp2", "logf", "log", "log10f", "log10", "log2f", "log2", "fmaf",
-            "fma", "fabsf", "fabs", "fminf", "fmin", "fmaxf", "fmax", "copysignf", "copysign", "floorf", "floor", "ceilf",
-            "ceil", "truncf", "trunc", "rintf", "rint", "nearbyintf", "nearbyint", "roundf", "round",
-           
+            "__builtin_unreachable",
+            "abort",
+            "__builtin_expect", /*"__builtin_expect_with_probability",*/
+            "__builtin_constant_p",
+            "__builtin_add_overflow",
+            "__builtin_mul_overflow",
+            "__builtin_saddll_overflow",
+            /*"__builtin_sadd_overflow",*/
+            "__builtin_smulll_overflow", /*"__builtin_smul_overflow",*/
+            "__builtin_ssubll_overflow",
+            /*"__builtin_ssub_overflow",*/ "__builtin_sub_overflow",
+            "__builtin_uaddll_overflow",
+            "__builtin_uadd_overflow",
+            "__builtin_umulll_overflow",
+            "__builtin_umul_overflow",
+            "__builtin_usubll_overflow",
+            "__builtin_usub_overflow",
+            "sqrtf",
+            "sqrt",
+            "__builtin_powif",
+            "__builtin_powi",
+            "sinf",
+            "sin",
+            "cosf",
+            "cos",
+            "powf",
+            "pow",
+            "expf",
+            "exp",
+            "exp2f",
+            "exp2",
+            "logf",
+            "log",
+            "log10f",
+            "log10",
+            "log2f",
+            "log2",
+            "fmaf",
+            "fma",
+            "fabsf",
+            "fabs",
+            "fminf",
+            "fmin",
+            "fmaxf",
+            "fmax",
+            "copysignf",
+            "copysign",
+            "floorf",
+            "floor",
+            "ceilf",
+            "ceil",
+            "truncf",
+            "trunc",
+            "rintf",
+            "rint",
+            "nearbyintf",
+            "nearbyint",
+            "roundf",
+            "round",
         ];
 
         for builtin in builtins.iter() {
@@ -282,8 +337,12 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
 
     pub fn rvalue_as_function(&self, value: RValue<'gcc>) -> Function<'gcc> {
         let function: Function<'gcc> = unsafe { std::mem::transmute(value) };
-        debug_assert!(self.functions.borrow().values().any(|value| *value == function),
-            "{:?} ({:?}) is not a function", value, value.get_type());
+        debug_assert!(
+            self.functions.borrow().values().any(|value| *value == function),
+            "{:?} ({:?}) is not a function",
+            value,
+            value.get_type()
+        );
         function
     }
 
@@ -305,13 +364,13 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
             }
         }
 
-        self.supports_128bit_integers &&
-            (self.u128_type.is_compatible_with(typ) || self.i128_type.is_compatible_with(typ))
+        self.supports_128bit_integers
+            && (self.u128_type.is_compatible_with(typ) || self.i128_type.is_compatible_with(typ))
     }
 
     pub fn is_non_native_int_type(&self, typ: Type<'gcc>) -> bool {
-        !self.supports_128bit_integers &&
-            (self.u128_type.is_compatible_with(typ) || self.i128_type.is_compatible_with(typ))
+        !self.supports_128bit_integers
+            && (self.u128_type.is_compatible_with(typ) || self.i128_type.is_compatible_with(typ))
     }
 
     pub fn is_native_int_type_or_bool(&self, typ: Type<'gcc>) -> bool {
@@ -319,18 +378,23 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
     }
 
     pub fn is_int_type_or_bool(&self, typ: Type<'gcc>) -> bool {
-        self.is_native_int_type(typ) || self.is_non_native_int_type(typ) || typ.is_compatible_with(self.bool_type)
+        self.is_native_int_type(typ)
+            || self.is_non_native_int_type(typ)
+            || typ.is_compatible_with(self.bool_type)
     }
 
     pub fn sess(&self) -> &'tcx Session {
         &self.tcx.sess
     }
 
-    pub fn bitcast_if_needed(&self, value: RValue<'gcc>, expected_type: Type<'gcc>) -> RValue<'gcc> {
+    pub fn bitcast_if_needed(
+        &self,
+        value: RValue<'gcc>,
+        expected_type: Type<'gcc>,
+    ) -> RValue<'gcc> {
         if value.get_type() != expected_type {
             self.context.new_bitcast(None, value, expected_type)
-        }
-        else {
+        } else {
             value
         }
     }
@@ -345,12 +409,14 @@ impl<'gcc, 'tcx> BackendTypes for CodegenCx<'gcc, 'tcx> {
     type Funclet = (); // TODO(antoyo)
 
     type DIScope = (); // TODO(antoyo)
-    type DILocation = (); // TODO(antoyo)
+    type DILocation = Location<'gcc>;
     type DIVariable = (); // TODO(antoyo)
 }
 
 impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
-    fn vtables(&self) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>> {
+    fn vtables(
+        &self,
+    ) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>> {
         &self.vtables
     }
 
@@ -364,13 +430,11 @@ impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     fn get_fn_addr(&self, instance: Instance<'tcx>) -> RValue<'gcc> {
         let func_name = self.tcx.symbol_name(instance).name;
 
-        let func =
-            if self.intrinsics.borrow().contains_key(func_name) {
-                self.intrinsics.borrow()[func_name].clone()
-            }
-            else {
-                get_fn(self, instance)
-            };
+        let func = if self.intrinsics.borrow().contains_key(func_name) {
+            self.intrinsics.borrow()[func_name].clone()
+        } else {
+            get_fn(self, instance)
+        };
         let ptr = func.get_address(None);
 
         // TODO(antoyo): don't do this twice: i.e. in declare_fn and here.
@@ -407,37 +471,32 @@ impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
             return llpersonality;
         }
         let tcx = self.tcx;
-        let func =
-            match tcx.lang_items().eh_personality() {
-                Some(def_id) if !wants_msvc_seh(self.sess()) => {
-                    let instance =
-                        ty::Instance::resolve(
-                            tcx,
-                            ty::ParamEnv::reveal_all(),
-                            def_id,
-                            ty::List::empty(),
-                        )
-                        .unwrap().unwrap();
-
-                    let symbol_name = tcx.symbol_name(instance).name;
-                    let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
-                    self.linkage.set(FunctionType::Extern);
-                    let func = self.declare_fn(symbol_name, &fn_abi);
-                    let func: RValue<'gcc> = unsafe { std::mem::transmute(func) };
-                    func
-                },
-                _ => {
-                    let name =
-                        if wants_msvc_seh(self.sess()) {
-                            "__CxxFrameHandler3"
-                        }
-                        else {
-                            "rust_eh_personality"
-                        };
-                    let func = self.declare_func(name, self.type_i32(), &[], true);
-                    unsafe { std::mem::transmute(func) }
-                }
-            };
+        let func = match tcx.lang_items().eh_personality() {
+            Some(def_id) if !wants_msvc_seh(self.sess()) => {
+                let instance = ty::Instance::expect_resolve(
+                    tcx,
+                    ty::ParamEnv::reveal_all(),
+                    def_id,
+                    ty::List::empty(),
+                );
+
+                let symbol_name = tcx.symbol_name(instance).name;
+                let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
+                self.linkage.set(FunctionType::Extern);
+                let func = self.declare_fn(symbol_name, &fn_abi);
+                let func: RValue<'gcc> = unsafe { std::mem::transmute(func) };
+                func
+            }
+            _ => {
+                let name = if wants_msvc_seh(self.sess()) {
+                    "__CxxFrameHandler3"
+                } else {
+                    "rust_eh_personality"
+                };
+                let func = self.declare_func(name, self.type_i32(), &[], true);
+                unsafe { std::mem::transmute(func) }
+            }
+        };
         // TODO(antoyo): apply target cpu attributes.
         self.eh_personality.set(Some(func));
         func
@@ -467,8 +526,7 @@ impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         let entry_name = self.sess().target.entry_name.as_ref();
         if self.get_declared_value(entry_name).is_none() {
             Some(self.declare_entry_fn(entry_name, fn_type, ()))
-        }
-        else {
+        } else {
             // If the symbol already exists, it is an error: for example, the user wrote
             // #[no_mangle] extern "C" fn main(..) {..}
             // instead of #[start]
diff --git a/compiler/rustc_codegen_gcc/src/debuginfo.rs b/compiler/rustc_codegen_gcc/src/debuginfo.rs
index d1bfd833cd8..aed15769025 100644
--- a/compiler/rustc_codegen_gcc/src/debuginfo.rs
+++ b/compiler/rustc_codegen_gcc/src/debuginfo.rs
@@ -1,9 +1,14 @@
-use gccjit::RValue;
-use rustc_codegen_ssa::mir::debuginfo::{FunctionDebugContext, VariableKind};
+use crate::rustc_index::Idx;
+use gccjit::{Location, RValue};
+use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind};
 use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoMethods};
-use rustc_middle::mir;
+use rustc_data_structures::sync::Lrc;
+use rustc_index::bit_set::BitSet;
+use rustc_index::IndexVec;
+use rustc_middle::mir::{self, Body, SourceScope};
 use rustc_middle::ty::{Instance, PolyExistentialTraitRef, Ty};
-use rustc_span::{SourceFile, Span, Symbol};
+use rustc_session::config::DebugInfo;
+use rustc_span::{BytePos, Pos, SourceFile, SourceFileAndLine, Span, Symbol};
 use rustc_target::abi::call::FnAbi;
 use rustc_target::abi::Size;
 use std::ops::Range;
@@ -11,31 +16,183 @@ use std::ops::Range;
 use crate::builder::Builder;
 use crate::context::CodegenCx;
 
+pub(super) const UNKNOWN_LINE_NUMBER: u32 = 0;
+pub(super) const UNKNOWN_COLUMN_NUMBER: u32 = 0;
+
 impl<'a, 'gcc, 'tcx> DebugInfoBuilderMethods for Builder<'a, 'gcc, 'tcx> {
     // FIXME(eddyb) find a common convention for all of the debuginfo-related
     // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
     fn dbg_var_addr(
         &mut self,
         _dbg_var: Self::DIVariable,
-        _scope_metadata: Self::DIScope,
+        _dbg_loc: Self::DILocation,
         _variable_alloca: Self::Value,
         _direct_offset: Size,
         _indirect_offsets: &[Size],
         _fragment: Option<Range<Size>>,
     ) {
-        unimplemented!();
+        // FIXME(tempdragon): Not sure if this is correct, probably wrong but still keep it here.
+        #[cfg(feature = "master")]
+        _variable_alloca.set_location(_dbg_loc);
     }
 
     fn insert_reference_to_gdb_debug_scripts_section_global(&mut self) {
         // TODO(antoyo): insert reference to gdb debug scripts section global.
     }
 
-    fn set_var_name(&mut self, _value: RValue<'gcc>, _name: &str) {
-        unimplemented!();
+    /// FIXME(tempdragon): Currently, this function is not yet implemented. It seems that the
+    /// debug name and the mangled name should both be included in the LValues.
+    /// Besides, a function to get the rvalue type(m_is_lvalue) should also be included.
+    fn set_var_name(&mut self, _value: RValue<'gcc>, _name: &str) {}
+
+    fn set_dbg_loc(&mut self, dbg_loc: Self::DILocation) {
+        self.location = Some(dbg_loc);
+    }
+}
+
+/// Generate the `debug_context` in an MIR Body.
+/// # Souce of Origin
+/// Copied from `create_scope_map.rs` of rustc_codegen_llvm
+fn compute_mir_scopes<'gcc, 'tcx>(
+    cx: &CodegenCx<'gcc, 'tcx>,
+    instance: Instance<'tcx>,
+    mir: &Body<'tcx>,
+    debug_context: &mut FunctionDebugContext<'tcx, (), Location<'gcc>>,
+) {
+    // Find all scopes with variables defined in them.
+    let variables = if cx.sess().opts.debuginfo == DebugInfo::Full {
+        let mut vars = BitSet::new_empty(mir.source_scopes.len());
+        // FIXME(eddyb) take into account that arguments always have debuginfo,
+        // irrespective of their name (assuming full debuginfo is enabled).
+        // NOTE(eddyb) actually, on second thought, those are always in the
+        // function scope, which always exists.
+        for var_debug_info in &mir.var_debug_info {
+            vars.insert(var_debug_info.source_info.scope);
+        }
+        Some(vars)
+    } else {
+        // Nothing to emit, of course.
+        None
+    };
+    let mut instantiated = BitSet::new_empty(mir.source_scopes.len());
+    // Instantiate all scopes.
+    for idx in 0..mir.source_scopes.len() {
+        let scope = SourceScope::new(idx);
+        make_mir_scope(cx, instance, mir, &variables, debug_context, &mut instantiated, scope);
+    }
+    assert!(instantiated.count() == mir.source_scopes.len());
+}
+
+/// Update the `debug_context`, adding new scope to it,
+/// if it's not added as is denoted in `instantiated`.
+///
+/// # Souce of Origin
+/// Copied from `create_scope_map.rs` of rustc_codegen_llvm
+/// FIXME(tempdragon/?): Add Scope Support Here.
+fn make_mir_scope<'gcc, 'tcx>(
+    cx: &CodegenCx<'gcc, 'tcx>,
+    instance: Instance<'tcx>,
+    mir: &Body<'tcx>,
+    variables: &Option<BitSet<SourceScope>>,
+    debug_context: &mut FunctionDebugContext<'tcx, (), Location<'gcc>>,
+    instantiated: &mut BitSet<SourceScope>,
+    scope: SourceScope,
+) {
+    if instantiated.contains(scope) {
+        return;
+    }
+
+    let scope_data = &mir.source_scopes[scope];
+    let parent_scope = if let Some(parent) = scope_data.parent_scope {
+        make_mir_scope(cx, instance, mir, variables, debug_context, instantiated, parent);
+        debug_context.scopes[parent]
+    } else {
+        // The root is the function itself.
+        let file = cx.sess().source_map().lookup_source_file(mir.span.lo());
+        debug_context.scopes[scope] = DebugScope {
+            file_start_pos: file.start_pos,
+            file_end_pos: file.end_position(),
+            ..debug_context.scopes[scope]
+        };
+        instantiated.insert(scope);
+        return;
+    };
+
+    if let Some(vars) = variables {
+        if !vars.contains(scope) && scope_data.inlined.is_none() {
+            // Do not create a DIScope if there are no variables defined in this
+            // MIR `SourceScope`, and it's not `inlined`, to avoid debuginfo bloat.
+            debug_context.scopes[scope] = parent_scope;
+            instantiated.insert(scope);
+            return;
+        }
     }
 
-    fn set_dbg_loc(&mut self, _dbg_loc: Self::DILocation) {
-        unimplemented!();
+    let loc = cx.lookup_debug_loc(scope_data.span.lo());
+
+    // FIXME(tempdragon): Add the scope related code here if the scope is supported.
+    let dbg_scope = ();
+
+    let inlined_at = scope_data.inlined.map(|(_, callsite_span)| {
+        // FIXME(eddyb) this doesn't account for the macro-related
+        // `Span` fixups that `rustc_codegen_ssa::mir::debuginfo` does.
+        let callsite_scope = parent_scope.adjust_dbg_scope_for_span(cx, callsite_span);
+        cx.dbg_loc(callsite_scope, parent_scope.inlined_at, callsite_span)
+    });
+    let p_inlined_at = parent_scope.inlined_at;
+    // TODO(tempdragon): dbg_scope: Add support for scope extension here.
+    inlined_at.or(p_inlined_at);
+
+    debug_context.scopes[scope] = DebugScope {
+        dbg_scope,
+        inlined_at,
+        file_start_pos: loc.file.start_pos,
+        file_end_pos: loc.file.end_position(),
+    };
+    instantiated.insert(scope);
+}
+
+/// A source code location used to generate debug information.
+// FIXME(eddyb) rename this to better indicate it's a duplicate of
+// `rustc_span::Loc` rather than `DILocation`, perhaps by making
+// `lookup_char_pos` return the right information instead.
+pub struct DebugLoc {
+    /// Information about the original source file.
+    pub file: Lrc<SourceFile>,
+    /// The (1-based) line number.
+    pub line: u32,
+    /// The (1-based) column number.
+    pub col: u32,
+}
+
+impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
+    /// Looks up debug source information about a `BytePos`.
+    // FIXME(eddyb) rename this to better indicate it's a duplicate of
+    // `lookup_char_pos` rather than `dbg_loc`, perhaps by making
+    // `lookup_char_pos` return the right information instead.
+    // Source of Origin: cg_llvm
+    pub fn lookup_debug_loc(&self, pos: BytePos) -> DebugLoc {
+        let (file, line, col) = match self.sess().source_map().lookup_line(pos) {
+            Ok(SourceFileAndLine { sf: file, line }) => {
+                let line_pos = file.lines()[line];
+
+                // Use 1-based indexing.
+                let line = (line + 1) as u32;
+                let col = (file.relative_position(pos) - line_pos).to_u32() + 1;
+
+                (file, line, col)
+            }
+            Err(file) => (file, UNKNOWN_LINE_NUMBER, UNKNOWN_COLUMN_NUMBER),
+        };
+
+        // For MSVC, omit the column number.
+        // Otherwise, emit it. This mimics clang behaviour.
+        // See discussion in https://github.com/rust-lang/rust/issues/42921
+        if self.sess().target.is_like_msvc {
+            DebugLoc { file, line, col: UNKNOWN_COLUMN_NUMBER }
+        } else {
+            DebugLoc { file, line, col }
+        }
     }
 }
 
@@ -51,13 +208,31 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
 
     fn create_function_debug_context(
         &self,
-        _instance: Instance<'tcx>,
-        _fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
-        _llfn: RValue<'gcc>,
-        _mir: &mir::Body<'tcx>,
+        instance: Instance<'tcx>,
+        fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
+        llfn: RValue<'gcc>,
+        mir: &mir::Body<'tcx>,
     ) -> Option<FunctionDebugContext<'tcx, Self::DIScope, Self::DILocation>> {
-        // TODO(antoyo)
-        None
+        if self.sess().opts.debuginfo == DebugInfo::None {
+            return None;
+        }
+
+        // Initialize fn debug context (including scopes).
+        let empty_scope = DebugScope {
+            dbg_scope: self.dbg_scope_fn(instance, fn_abi, Some(llfn)),
+            inlined_at: None,
+            file_start_pos: BytePos(0),
+            file_end_pos: BytePos(0),
+        };
+        let mut fn_debug_context = FunctionDebugContext {
+            scopes: IndexVec::from_elem(empty_scope, &mir.source_scopes.as_slice()),
+            inlined_function_scopes: Default::default(),
+        };
+
+        // Fill in all the scopes, with the information from the MIR body.
+        compute_mir_scopes(self, instance, mir, &mut fn_debug_context);
+
+        Some(fn_debug_context)
     }
 
     fn extend_scope_to_file(
@@ -65,11 +240,11 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         _scope_metadata: Self::DIScope,
         _file: &SourceFile,
     ) -> Self::DIScope {
-        unimplemented!();
+        // TODO(antoyo): implement.
     }
 
     fn debuginfo_finalize(&self) {
-        // TODO(antoyo)
+        self.context.set_debug_info(true)
     }
 
     fn create_dbg_var(
@@ -80,7 +255,6 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         _variable_kind: VariableKind,
         _span: Span,
     ) -> Self::DIVariable {
-        unimplemented!();
     }
 
     fn dbg_scope_fn(
@@ -89,15 +263,40 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         _fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
         _maybe_definition_llfn: Option<RValue<'gcc>>,
     ) -> Self::DIScope {
-        unimplemented!();
+        // TODO(antoyo): implement.
     }
 
     fn dbg_loc(
         &self,
         _scope: Self::DIScope,
         _inlined_at: Option<Self::DILocation>,
-        _span: Span,
+        span: Span,
     ) -> Self::DILocation {
-        unimplemented!();
+        let pos = span.lo();
+        let DebugLoc { file, line, col } = self.lookup_debug_loc(pos);
+        let loc = match &file.name {
+            rustc_span::FileName::Real(name) => match name {
+                rustc_span::RealFileName::LocalPath(name) => {
+                    if let Some(name) = name.to_str() {
+                        self.context.new_location(name, line as i32, col as i32)
+                    } else {
+                        Location::null()
+                    }
+                }
+                rustc_span::RealFileName::Remapped { local_path, virtual_name: _ } => {
+                    if let Some(name) = local_path.as_ref() {
+                        if let Some(name) = name.to_str() {
+                            self.context.new_location(name, line as i32, col as i32)
+                        } else {
+                            Location::null()
+                        }
+                    } else {
+                        Location::null()
+                    }
+                }
+            },
+            _ => Location::null(),
+        };
+        loc
     }
 }
diff --git a/compiler/rustc_codegen_gcc/src/declare.rs b/compiler/rustc_codegen_gcc/src/declare.rs
index 247454fa58e..db6edbab12d 100644
--- a/compiler/rustc_codegen_gcc/src/declare.rs
+++ b/compiler/rustc_codegen_gcc/src/declare.rs
@@ -1,6 +1,6 @@
-use gccjit::{Function, FunctionType, GlobalKind, LValue, RValue, Type};
-#[cfg(feature="master")]
+#[cfg(feature = "master")]
 use gccjit::{FnAttribute, ToRValue};
+use gccjit::{Function, FunctionType, GlobalKind, LValue, RValue, Type};
 use rustc_codegen_ssa::traits::BaseTypeMethods;
 use rustc_middle::ty::Ty;
 use rustc_span::Symbol;
@@ -11,7 +11,13 @@ use crate::context::CodegenCx;
 use crate::intrinsic::llvm;
 
 impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
-    pub fn get_or_insert_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option<Symbol>) -> LValue<'gcc> {
+    pub fn get_or_insert_global(
+        &self,
+        name: &str,
+        ty: Type<'gcc>,
+        is_tls: bool,
+        link_section: Option<Symbol>,
+    ) -> LValue<'gcc> {
         if self.globals.borrow().contains_key(name) {
             let typ = self.globals.borrow()[name].get_type();
             let global = self.context.new_global(None, GlobalKind::Imported, typ, name);
@@ -22,8 +28,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
                 global.set_link_section(link_section.as_str());
             }
             global
-        }
-        else {
+        } else {
             self.declare_global(name, ty, GlobalKind::Exported, is_tls, link_section)
         }
     }
@@ -33,19 +38,37 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         self.context.new_global(None, GlobalKind::Internal, ty, &name)
     }
 
-    pub fn declare_global_with_linkage(&self, name: &str, ty: Type<'gcc>, linkage: GlobalKind) -> LValue<'gcc> {
+    pub fn declare_global_with_linkage(
+        &self,
+        name: &str,
+        ty: Type<'gcc>,
+        linkage: GlobalKind,
+    ) -> LValue<'gcc> {
         let global = self.context.new_global(None, linkage, ty, name);
         let global_address = global.get_address(None);
         self.globals.borrow_mut().insert(name.to_string(), global_address);
         global
     }
 
-    pub fn declare_func(&self, name: &str, return_type: Type<'gcc>, params: &[Type<'gcc>], variadic: bool) -> Function<'gcc> {
+    pub fn declare_func(
+        &self,
+        name: &str,
+        return_type: Type<'gcc>,
+        params: &[Type<'gcc>],
+        variadic: bool,
+    ) -> Function<'gcc> {
         self.linkage.set(FunctionType::Extern);
         declare_raw_fn(self, name, () /*llvm::CCallConv*/, return_type, params, variadic)
     }
 
-    pub fn declare_global(&self, name: &str, ty: Type<'gcc>, global_kind: GlobalKind, is_tls: bool, link_section: Option<Symbol>) -> LValue<'gcc> {
+    pub fn declare_global(
+        &self,
+        name: &str,
+        ty: Type<'gcc>,
+        global_kind: GlobalKind,
+        is_tls: bool,
+        link_section: Option<Symbol>,
+    ) -> LValue<'gcc> {
         let global = self.context.new_global(None, global_kind, ty, name);
         if is_tls {
             global.set_tls_model(self.tls_model);
@@ -65,13 +88,25 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         global
     }
 
-    pub fn declare_entry_fn(&self, name: &str, _fn_type: Type<'gcc>, callconv: () /*llvm::CCallConv*/) -> RValue<'gcc> {
+    pub fn declare_entry_fn(
+        &self,
+        name: &str,
+        _fn_type: Type<'gcc>,
+        callconv: (), /*llvm::CCallConv*/
+    ) -> RValue<'gcc> {
         // TODO(antoyo): use the fn_type parameter.
         let const_string = self.context.new_type::<u8>().make_pointer().make_pointer();
         let return_type = self.type_i32();
         let variadic = false;
         self.linkage.set(FunctionType::Exported);
-        let func = declare_raw_fn(self, name, callconv, return_type, &[self.type_i32(), const_string], variadic);
+        let func = declare_raw_fn(
+            self,
+            name,
+            callconv,
+            return_type,
+            &[self.type_i32(), const_string],
+            variadic,
+        );
         // NOTE: it is needed to set the current_func here as well, because get_fn() is not called
         // for the main function.
         *self.current_func.borrow_mut() = Some(func);
@@ -85,19 +120,32 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
             arguments_type,
             is_c_variadic,
             on_stack_param_indices,
-            #[cfg(feature="master")]
+            #[cfg(feature = "master")]
             fn_attributes,
         } = fn_abi.gcc_type(self);
-        let func = declare_raw_fn(self, name, () /*fn_abi.llvm_cconv()*/, return_type, &arguments_type, is_c_variadic);
+        let func = declare_raw_fn(
+            self,
+            name,
+            (), /*fn_abi.llvm_cconv()*/
+            return_type,
+            &arguments_type,
+            is_c_variadic,
+        );
         self.on_stack_function_params.borrow_mut().insert(func, on_stack_param_indices);
-        #[cfg(feature="master")]
+        #[cfg(feature = "master")]
         for fn_attr in fn_attributes {
             func.add_attribute(fn_attr);
         }
         func
     }
 
-    pub fn define_global(&self, name: &str, ty: Type<'gcc>, is_tls: bool, link_section: Option<Symbol>) -> LValue<'gcc> {
+    pub fn define_global(
+        &self,
+        name: &str,
+        ty: Type<'gcc>,
+        is_tls: bool,
+        link_section: Option<Symbol>,
+    ) -> LValue<'gcc> {
         self.get_or_insert_global(name, ty, is_tls, link_section)
     }
 
@@ -111,62 +159,84 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
 ///
 /// If there’s a value with the same name already declared, the function will
 /// update the declaration and return existing Value instead.
-fn declare_raw_fn<'gcc>(cx: &CodegenCx<'gcc, '_>, name: &str, _callconv: () /*llvm::CallConv*/, return_type: Type<'gcc>, param_types: &[Type<'gcc>], variadic: bool) -> Function<'gcc> {
+fn declare_raw_fn<'gcc>(
+    cx: &CodegenCx<'gcc, '_>,
+    name: &str,
+    _callconv: (), /*llvm::CallConv*/
+    return_type: Type<'gcc>,
+    param_types: &[Type<'gcc>],
+    variadic: bool,
+) -> Function<'gcc> {
     if name.starts_with("llvm.") {
         let intrinsic = llvm::intrinsic(name, cx);
         cx.intrinsics.borrow_mut().insert(name.to_string(), intrinsic);
         return intrinsic;
     }
-    let func =
-        if cx.functions.borrow().contains_key(name) {
-            cx.functions.borrow()[name]
-        }
-        else {
-            let params: Vec<_> = param_types.into_iter().enumerate()
-                .map(|(index, param)| cx.context.new_parameter(None, *param, &format!("param{}", index))) // TODO(antoyo): set name.
+    let func = if cx.functions.borrow().contains_key(name) {
+        cx.functions.borrow()[name]
+    } else {
+        let params: Vec<_> = param_types
+            .into_iter()
+            .enumerate()
+            .map(|(index, param)| {
+                cx.context.new_parameter(None, *param, &format!("param{}", index))
+            }) // TODO(antoyo): set name.
+            .collect();
+        #[cfg(not(feature = "master"))]
+        let name = mangle_name(name);
+        let func =
+            cx.context.new_function(None, cx.linkage.get(), return_type, &params, &name, variadic);
+        cx.functions.borrow_mut().insert(name.to_string(), func);
+
+        #[cfg(feature = "master")]
+        if name == "rust_eh_personality" {
+            // NOTE: GCC will sometimes change the personality function set on a function from
+            // rust_eh_personality to __gcc_personality_v0 as an optimization.
+            // As such, we need to create a weak alias from __gcc_personality_v0 to
+            // rust_eh_personality in order to avoid a linker error.
+            // This needs to be weak in order to still allow using the standard
+            // __gcc_personality_v0 when the linking to it.
+            // Since aliases don't work (maybe because of a bug in LTO partitioning?), we
+            // create a wrapper function that calls rust_eh_personality.
+
+            let params: Vec<_> = param_types
+                .into_iter()
+                .enumerate()
+                .map(|(index, param)| {
+                    cx.context.new_parameter(None, *param, &format!("param{}", index))
+                }) // TODO(antoyo): set name.
                 .collect();
-            let func = cx.context.new_function(None, cx.linkage.get(), return_type, &params, mangle_name(name), variadic);
-            cx.functions.borrow_mut().insert(name.to_string(), func);
-
-            #[cfg(feature="master")]
-            if name == "rust_eh_personality" {
-                // NOTE: GCC will sometimes change the personality function set on a function from
-                // rust_eh_personality to __gcc_personality_v0 as an optimization.
-                // As such, we need to create a weak alias from __gcc_personality_v0 to
-                // rust_eh_personality in order to avoid a linker error.
-                // This needs to be weak in order to still allow using the standard
-                // __gcc_personality_v0 when the linking to it.
-                // Since aliases don't work (maybe because of a bug in LTO partitioning?), we
-                // create a wrapper function that calls rust_eh_personality.
-
-                let params: Vec<_> = param_types.into_iter().enumerate()
-                    .map(|(index, param)| cx.context.new_parameter(None, *param, &format!("param{}", index))) // TODO(antoyo): set name.
-                    .collect();
-                let gcc_func = cx.context.new_function(None, FunctionType::Exported, return_type, &params, "__gcc_personality_v0", variadic);
-
-                // We need a normal extern function for the crates that access rust_eh_personality
-                // without defining it, otherwise we'll get a compiler error.
-                //
-                // For the crate defining it, that needs to be a weak alias instead.
-                gcc_func.add_attribute(FnAttribute::Weak);
-
-                let block = gcc_func.new_block("start");
-                let mut args = vec![];
-                for param in &params {
-                    args.push(param.to_rvalue());
-                }
-                let call = cx.context.new_call(None, func, &args);
-                if return_type == cx.type_void() {
-                    block.add_eval(None, call);
-                    block.end_with_void_return(None);
-                }
-                else {
-                    block.end_with_return(None, call);
-                }
+            let gcc_func = cx.context.new_function(
+                None,
+                FunctionType::Exported,
+                return_type,
+                &params,
+                "__gcc_personality_v0",
+                variadic,
+            );
+
+            // We need a normal extern function for the crates that access rust_eh_personality
+            // without defining it, otherwise we'll get a compiler error.
+            //
+            // For the crate defining it, that needs to be a weak alias instead.
+            gcc_func.add_attribute(FnAttribute::Weak);
+
+            let block = gcc_func.new_block("start");
+            let mut args = vec![];
+            for param in &params {
+                args.push(param.to_rvalue());
             }
+            let call = cx.context.new_call(None, func, &args);
+            if return_type == cx.type_void() {
+                block.add_eval(None, call);
+                block.end_with_void_return(None);
+            } else {
+                block.end_with_return(None, call);
+            }
+        }
 
-            func
-        };
+        func
+    };
 
     // TODO(antoyo): set function calling convention.
     // TODO(antoyo): set unnamed address.
@@ -179,15 +249,24 @@ fn declare_raw_fn<'gcc>(cx: &CodegenCx<'gcc, '_>, name: &str, _callconv: () /*ll
 }
 
 // FIXME(antoyo): this is a hack because libgccjit currently only supports alpha, num and _.
-// Unsupported characters: `$` and `.`.
-pub fn mangle_name(name: &str) -> String {
-    name.replace(|char: char| {
-        if !char.is_alphanumeric() && char != '_' {
-            debug_assert!("$.*".contains(char), "Unsupported char in function name {}: {}", name, char);
-            true
-        }
-        else {
-            false
-        }
-    }, "_")
+// Unsupported characters: `$`, `.` and `*`.
+// FIXME(antoyo): `*` might not be expected: https://github.com/rust-lang/rust/issues/116979#issuecomment-1840926865
+#[cfg(not(feature = "master"))]
+fn mangle_name(name: &str) -> String {
+    name.replace(
+        |char: char| {
+            if !char.is_alphanumeric() && char != '_' {
+                debug_assert!(
+                    "$.*".contains(char),
+                    "Unsupported char in function name {}: {}",
+                    name,
+                    char
+                );
+                true
+            } else {
+                false
+            }
+        },
+        "_",
+    )
 }
diff --git a/compiler/rustc_codegen_gcc/src/errors.rs b/compiler/rustc_codegen_gcc/src/errors.rs
index 988a7e1033e..aee2b077dba 100644
--- a/compiler/rustc_codegen_gcc/src/errors.rs
+++ b/compiler/rustc_codegen_gcc/src/errors.rs
@@ -1,9 +1,6 @@
-use rustc_errors::{
-    DiagCtxt, DiagArgValue, Diag, EmissionGuarantee, IntoDiagnostic, IntoDiagnosticArg, Level,
-};
+use rustc_errors::{Diag, DiagCtxt, Diagnostic, EmissionGuarantee, Level};
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::Span;
-use std::borrow::Cow;
 
 use crate::fluent_generated as fluent;
 
@@ -31,18 +28,6 @@ pub(crate) enum PossibleFeature<'a> {
     None,
 }
 
-struct ExitCode(Option<i32>);
-
-impl IntoDiagnosticArg for ExitCode {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
-        let ExitCode(exit_code) = self;
-        match exit_code {
-            Some(t) => t.into_diagnostic_arg(),
-            None => DiagArgValue::Str(Cow::Borrowed("<signal>")),
-        }
-    }
-}
-
 #[derive(Diagnostic)]
 #[diag(codegen_gcc_lto_not_supported)]
 pub(crate) struct LTONotSupported;
@@ -81,12 +66,6 @@ pub(crate) struct CopyBitcode {
 pub(crate) struct DynamicLinkingWithLTO;
 
 #[derive(Diagnostic)]
-#[diag(codegen_gcc_load_bitcode)]
-pub(crate) struct LoadBitcode {
-    name: String,
-}
-
-#[derive(Diagnostic)]
 #[diag(codegen_gcc_lto_disallowed)]
 pub(crate) struct LtoDisallowed;
 
@@ -110,8 +89,8 @@ pub(crate) struct TargetFeatureDisableOrEnable<'a> {
 #[help(codegen_gcc_missing_features)]
 pub(crate) struct MissingFeatures;
 
-impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> {
-    fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> Diag<'_, G> {
+impl<G: EmissionGuarantee> Diagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> {
+    fn into_diag(self, dcx: &'_ DiagCtxt, level: Level) -> Diag<'_, G> {
         let mut diag = Diag::new(dcx, level, fluent::codegen_gcc_target_feature_disable_or_enable);
         if let Some(span) = self.span {
             diag.span(span);
diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs
index 4babe5bfb81..53877e8ff7f 100644
--- a/compiler/rustc_codegen_gcc/src/gcc_util.rs
+++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs
@@ -1,4 +1,4 @@
-#[cfg(feature="master")]
+#[cfg(feature = "master")]
 use gccjit::Context;
 use smallvec::{smallvec, SmallVec};
 
@@ -7,7 +7,10 @@ use rustc_middle::bug;
 use rustc_session::Session;
 use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES;
 
-use crate::errors::{PossibleFeature, TargetFeatureDisableOrEnable, UnknownCTargetFeature, UnknownCTargetFeaturePrefix};
+use crate::errors::{
+    PossibleFeature, TargetFeatureDisableOrEnable, UnknownCTargetFeature,
+    UnknownCTargetFeaturePrefix,
+};
 
 /// The list of GCC features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`,
 /// `--target` and similar).
@@ -44,7 +47,10 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
     // -Ctarget-features
     let supported_features = sess.target.supported_target_features();
     let mut featsmap = FxHashMap::default();
-    let feats = sess.opts.cg.target_feature
+    let feats = sess
+        .opts
+        .cg
+        .target_feature
         .split(',')
         .filter_map(|s| {
             let enable_disable = match s.chars().next() {
@@ -69,16 +75,14 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
                         None
                     }
                 });
-                let unknown_feature =
-                    if let Some(rust_feature) = rust_feature {
-                        UnknownCTargetFeature {
-                            feature,
-                            rust_feature: PossibleFeature::Some { rust_feature },
-                        }
+                let unknown_feature = if let Some(rust_feature) = rust_feature {
+                    UnknownCTargetFeature {
+                        feature,
+                        rust_feature: PossibleFeature::Some { rust_feature },
                     }
-                    else {
-                        UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None }
-                    };
+                } else {
+                    UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None }
+                };
                 sess.dcx().emit_warn(unknown_feature);
             }
 
@@ -95,18 +99,18 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
             // passing requests down to GCC. This means that all in-language
             // features also work on the command line instead of having two
             // different names when the GCC name and the Rust name differ.
-            Some(to_gcc_features(sess, feature)
-                .iter()
-                .flat_map(|feat| to_gcc_features(sess, feat).into_iter())
-                .map(|feature| {
-                    if enable_disable == '-' {
-                        format!("-{}", feature)
-                    }
-                    else {
-                        feature.to_string()
-                    }
-                })
-                .collect::<Vec<_>>(),
+            Some(
+                to_gcc_features(sess, feature)
+                    .iter()
+                    .flat_map(|feat| to_gcc_features(sess, feat).into_iter())
+                    .map(|feature| {
+                        if enable_disable == '-' {
+                            format!("-{}", feature)
+                        } else {
+                            feature.to_string()
+                        }
+                    })
+                    .collect::<Vec<_>>(),
             )
         })
         .flatten();
@@ -184,7 +188,10 @@ pub fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]>
 
 // Given a map from target_features to whether they are enabled or disabled,
 // ensure only valid combinations are allowed.
-pub fn check_tied_features(sess: &Session, features: &FxHashMap<&str, bool>) -> Option<&'static [&'static str]> {
+pub fn check_tied_features(
+    sess: &Session,
+    features: &FxHashMap<&str, bool>,
+) -> Option<&'static [&'static str]> {
     for tied in sess.target.tied_target_features() {
         // Tied features must be set to the same value, or not set at all
         let mut tied_iter = tied.iter();
@@ -199,7 +206,7 @@ pub fn check_tied_features(sess: &Session, features: &FxHashMap<&str, bool>) ->
 fn arch_to_gcc(name: &str) -> &str {
     match name {
         "M68020" => "68020",
-         _ => name,
+        _ => name,
     }
 }
 
@@ -208,15 +215,13 @@ fn handle_native(name: &str) -> &str {
         return arch_to_gcc(name);
     }
 
-    #[cfg(feature="master")]
+    #[cfg(feature = "master")]
     {
         // Get the native arch.
         let context = Context::default();
-        context.get_target_info().arch().unwrap()
-            .to_str()
-            .unwrap()
+        context.get_target_info().arch().unwrap().to_str().unwrap()
     }
-    #[cfg(not(feature="master"))]
+    #[cfg(not(feature = "master"))]
     unimplemented!();
 }
 
diff --git a/compiler/rustc_codegen_gcc/src/int.rs b/compiler/rustc_codegen_gcc/src/int.rs
index 9b9b3ea4f87..841bcf592e4 100644
--- a/compiler/rustc_codegen_gcc/src/int.rs
+++ b/compiler/rustc_codegen_gcc/src/int.rs
@@ -4,15 +4,22 @@
 
 use std::convert::TryFrom;
 
-use gccjit::{ComparisonOp, FunctionType, RValue, ToRValue, Type, UnaryOp, BinaryOp};
+use gccjit::{BinaryOp, ComparisonOp, FunctionType, Location, RValue, ToRValue, Type, UnaryOp};
 use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
 use rustc_codegen_ssa::traits::{BackendTypes, BaseTypeMethods, BuilderMethods, OverflowOp};
 use rustc_middle::ty::{ParamEnv, Ty};
-use rustc_target::abi::{Endian, call::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode}};
+use rustc_target::abi::{
+    call::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode},
+    Endian,
+};
 use rustc_target::spec;
 
 use crate::builder::ToGccComp;
-use crate::{builder::Builder, common::{SignType, TypeReflection}, context::CodegenCx};
+use crate::{
+    builder::Builder,
+    common::{SignType, TypeReflection},
+    context::CodegenCx,
+};
 
 impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
     pub fn gcc_urem(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
@@ -29,35 +36,39 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         let typ = a.get_type();
         if self.is_native_int_type_or_bool(typ) {
             let operation =
-                if typ.is_bool() {
-                    UnaryOp::LogicalNegate
-                }
-                else {
-                    UnaryOp::BitwiseNegate
-                };
-            self.cx.context.new_unary_op(None, operation, typ, a)
-        }
-        else {
+                if typ.is_bool() { UnaryOp::LogicalNegate } else { UnaryOp::BitwiseNegate };
+            self.cx.context.new_unary_op(self.location, operation, typ, a)
+        } else {
             let element_type = typ.dyncast_array().expect("element type");
-            self.from_low_high_rvalues(typ,
-                self.cx.context.new_unary_op(None, UnaryOp::BitwiseNegate, element_type, self.low(a)),
-                self.cx.context.new_unary_op(None, UnaryOp::BitwiseNegate, element_type, self.high(a)),
+            self.from_low_high_rvalues(
+                typ,
+                self.cx.context.new_unary_op(
+                    self.location,
+                    UnaryOp::BitwiseNegate,
+                    element_type,
+                    self.low(a),
+                ),
+                self.cx.context.new_unary_op(
+                    self.location,
+                    UnaryOp::BitwiseNegate,
+                    element_type,
+                    self.high(a),
+                ),
             )
         }
     }
 
     pub fn gcc_neg(&self, a: RValue<'gcc>) -> RValue<'gcc> {
         let a_type = a.get_type();
-        if self.is_native_int_type(a_type) {
-            self.cx.context.new_unary_op(None, UnaryOp::Minus, a.get_type(), a)
-        }
-        else {
+        if self.is_native_int_type(a_type) || a_type.is_vector() {
+            self.cx.context.new_unary_op(self.location, UnaryOp::Minus, a.get_type(), a)
+        } else {
             self.gcc_add(self.gcc_not(a), self.gcc_int(a_type, 1))
         }
     }
 
     pub fn gcc_and(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        self.cx.bitwise_operation(BinaryOp::BitwiseAnd, a, b)
+        self.cx.bitwise_operation(BinaryOp::BitwiseAnd, a, b, self.location)
     }
 
     pub fn gcc_lshr(&mut self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
@@ -69,20 +80,16 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
             // FIXME(antoyo): remove the casts when libgccjit can shift an unsigned number by a signed number.
             // TODO(antoyo): cast to unsigned to do a logical shift if that does not work.
             if a_type.is_signed(self) != b_type.is_signed(self) {
-                let b = self.context.new_cast(None, b, a_type);
+                let b = self.context.new_cast(self.location, b, a_type);
                 a >> b
-            }
-            else {
+            } else {
                 a >> b
             }
-        }
-        else if a_type.is_vector() && a_type.is_vector() {
+        } else if a_type.is_vector() && a_type.is_vector() {
             a >> b
-        }
-        else if a_native && !b_native {
+        } else if a_native && !b_native {
             self.gcc_lshr(a, self.gcc_int_cast(b, a_type))
-        }
-        else {
+        } else {
             // NOTE: we cannot use the lshr builtin because it's calling hi() (to get the most
             // significant half of the number) which uses lshr.
 
@@ -95,46 +102,38 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
             let b0_block = func.new_block("b0");
             let actual_else_block = func.new_block("actual_else");
 
-            let result = func.new_local(None, a_type, "shiftResult");
+            let result = func.new_local(self.location, a_type, "shiftResult");
 
             let sixty_four = self.gcc_int(native_int_type, 64);
             let sixty_three = self.gcc_int(native_int_type, 63);
             let zero = self.gcc_zero(native_int_type);
             let b = self.gcc_int_cast(b, native_int_type);
             let condition = self.gcc_icmp(IntPredicate::IntNE, self.gcc_and(b, sixty_four), zero);
-            self.llbb().end_with_conditional(None, condition, then_block, else_block);
+            self.llbb().end_with_conditional(self.location, condition, then_block, else_block);
 
             let shift_value = self.gcc_sub(b, sixty_four);
             let high = self.high(a);
-            let sign =
-                if a_type.is_signed(self) {
-                    high >> sixty_three
-                }
-                else {
-                    zero
-                };
+            let sign = if a_type.is_signed(self) { high >> sixty_three } else { zero };
             let array_value = self.from_low_high_rvalues(a_type, high >> shift_value, sign);
-            then_block.add_assignment(None, result, array_value);
-            then_block.end_with_jump(None, after_block);
+            then_block.add_assignment(self.location, result, array_value);
+            then_block.end_with_jump(self.location, after_block);
 
             let condition = self.gcc_icmp(IntPredicate::IntEQ, b, zero);
-            else_block.end_with_conditional(None, condition, b0_block, actual_else_block);
+            else_block.end_with_conditional(self.location, condition, b0_block, actual_else_block);
 
-            b0_block.add_assignment(None, result, a);
-            b0_block.end_with_jump(None, after_block);
+            b0_block.add_assignment(self.location, result, a);
+            b0_block.end_with_jump(self.location, after_block);
 
             let shift_value = self.gcc_sub(sixty_four, b);
             // NOTE: cast low to its unsigned type in order to perform a logical right shift.
             let unsigned_type = native_int_type.to_unsigned(&self.cx);
-            let casted_low = self.context.new_cast(None, self.low(a), unsigned_type);
-            let shifted_low = casted_low >> self.context.new_cast(None, b, unsigned_type);
-            let shifted_low = self.context.new_cast(None, shifted_low, native_int_type);
-            let array_value = self.from_low_high_rvalues(a_type,
-                (high << shift_value) | shifted_low,
-                high >> b,
-            );
-            actual_else_block.add_assignment(None, result, array_value);
-            actual_else_block.end_with_jump(None, after_block);
+            let casted_low = self.context.new_cast(self.location, self.low(a), unsigned_type);
+            let shifted_low = casted_low >> self.context.new_cast(self.location, b, unsigned_type);
+            let shifted_low = self.context.new_cast(self.location, shifted_low, native_int_type);
+            let array_value =
+                self.from_low_high_rvalues(a_type, (high << shift_value) | shifted_low, high >> b);
+            actual_else_block.add_assignment(self.location, result, array_value);
+            actual_else_block.end_with_jump(self.location, after_block);
 
             // NOTE: since jumps were added in a place rustc does not expect, the current block in the
             // state need to be updated.
@@ -144,38 +143,49 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         }
     }
 
-    fn additive_operation(&self, operation: BinaryOp, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> {
+    fn additive_operation(
+        &self,
+        operation: BinaryOp,
+        a: RValue<'gcc>,
+        mut b: RValue<'gcc>,
+    ) -> RValue<'gcc> {
         let a_type = a.get_type();
         let b_type = b.get_type();
-        if (self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type)) || (a_type.is_vector() && b_type.is_vector()) {
+        if (self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type))
+            || (a_type.is_vector() && b_type.is_vector())
+        {
             if a_type != b_type {
                 if a_type.is_vector() {
                     // Vector types need to be bitcast.
                     // TODO(antoyo): perhaps use __builtin_convertvector for vector casting.
-                    b = self.context.new_bitcast(None, b, a.get_type());
-                }
-                else {
-                    b = self.context.new_cast(None, b, a.get_type());
+                    b = self.context.new_bitcast(self.location, b, a.get_type());
+                } else {
+                    b = self.context.new_cast(self.location, b, a.get_type());
                 }
             }
-            self.context.new_binary_op(None, operation, a_type, a, b)
-        }
-        else {
+            self.context.new_binary_op(self.location, operation, a_type, a, b)
+        } else {
             debug_assert!(a_type.dyncast_array().is_some());
             debug_assert!(b_type.dyncast_array().is_some());
             let signed = a_type.is_compatible_with(self.i128_type);
-            let func_name =
-                match (operation, signed) {
-                    (BinaryOp::Plus, true) => "__rust_i128_add",
-                    (BinaryOp::Plus, false) => "__rust_u128_add",
-                    (BinaryOp::Minus, true) => "__rust_i128_sub",
-                    (BinaryOp::Minus, false) => "__rust_u128_sub",
-                    _ => unreachable!("unexpected additive operation {:?}", operation),
-                };
-            let param_a = self.context.new_parameter(None, a_type, "a");
-            let param_b = self.context.new_parameter(None, b_type, "b");
-            let func = self.context.new_function(None, FunctionType::Extern, a_type, &[param_a, param_b], func_name, false);
-            self.context.new_call(None, func, &[a, b])
+            let func_name = match (operation, signed) {
+                (BinaryOp::Plus, true) => "__rust_i128_add",
+                (BinaryOp::Plus, false) => "__rust_u128_add",
+                (BinaryOp::Minus, true) => "__rust_i128_sub",
+                (BinaryOp::Minus, false) => "__rust_u128_sub",
+                _ => unreachable!("unexpected additive operation {:?}", operation),
+            };
+            let param_a = self.context.new_parameter(self.location, a_type, "a");
+            let param_b = self.context.new_parameter(self.location, b_type, "b");
+            let func = self.context.new_function(
+                self.location,
+                FunctionType::Extern,
+                a_type,
+                &[param_a, param_b],
+                func_name,
+                false,
+            );
+            self.context.new_call(self.location, func, &[a, b])
         }
     }
 
@@ -191,27 +201,36 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         self.additive_operation(BinaryOp::Minus, a, b)
     }
 
-    fn multiplicative_operation(&self, operation: BinaryOp, operation_name: &str, signed: bool, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
+    fn multiplicative_operation(
+        &self,
+        operation: BinaryOp,
+        operation_name: &str,
+        signed: bool,
+        a: RValue<'gcc>,
+        b: RValue<'gcc>,
+    ) -> RValue<'gcc> {
         let a_type = a.get_type();
         let b_type = b.get_type();
-        if (self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type)) || (a_type.is_vector() && b_type.is_vector()) {
-            self.context.new_binary_op(None, operation, a_type, a, b)
-        }
-        else {
+        if (self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type))
+            || (a_type.is_vector() && b_type.is_vector())
+        {
+            self.context.new_binary_op(self.location, operation, a_type, a, b)
+        } else {
             debug_assert!(a_type.dyncast_array().is_some());
             debug_assert!(b_type.dyncast_array().is_some());
-            let sign =
-                if signed {
-                    ""
-                }
-                else {
-                    "u"
-                };
+            let sign = if signed { "" } else { "u" };
             let func_name = format!("__{}{}ti3", sign, operation_name);
-            let param_a = self.context.new_parameter(None, a_type, "a");
-            let param_b = self.context.new_parameter(None, b_type, "b");
-            let func = self.context.new_function(None, FunctionType::Extern, a_type, &[param_a, param_b], func_name, false);
-            self.context.new_call(None, func, &[a, b])
+            let param_a = self.context.new_parameter(self.location, a_type, "a");
+            let param_b = self.context.new_parameter(self.location, b_type, "b");
+            let func = self.context.new_function(
+                self.location,
+                FunctionType::Extern,
+                a_type,
+                &[param_a, param_b],
+                func_name,
+                false,
+            );
+            self.context.new_call(self.location, func, &[a, b])
         }
     }
 
@@ -227,137 +246,133 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         self.multiplicative_operation(BinaryOp::Divide, "div", false, a, b)
     }
 
-    pub fn gcc_checked_binop(&self, oop: OverflowOp, typ: Ty<'_>, lhs: <Self as BackendTypes>::Value, rhs: <Self as BackendTypes>::Value) -> (<Self as BackendTypes>::Value, <Self as BackendTypes>::Value) {
+    pub fn gcc_checked_binop(
+        &self,
+        oop: OverflowOp,
+        typ: Ty<'_>,
+        lhs: <Self as BackendTypes>::Value,
+        rhs: <Self as BackendTypes>::Value,
+    ) -> (<Self as BackendTypes>::Value, <Self as BackendTypes>::Value) {
         use rustc_middle::ty::{Int, IntTy::*, Uint, UintTy::*};
 
-        let new_kind =
-            match typ.kind() {
-                Int(t @ Isize) => Int(t.normalize(self.tcx.sess.target.pointer_width)),
-                Uint(t @ Usize) => Uint(t.normalize(self.tcx.sess.target.pointer_width)),
-                t @ (Uint(_) | Int(_)) => t.clone(),
-                _ => panic!("tried to get overflow intrinsic for op applied to non-int type"),
-            };
+        let new_kind = match typ.kind() {
+            Int(t @ Isize) => Int(t.normalize(self.tcx.sess.target.pointer_width)),
+            Uint(t @ Usize) => Uint(t.normalize(self.tcx.sess.target.pointer_width)),
+            t @ (Uint(_) | Int(_)) => t.clone(),
+            _ => panic!("tried to get overflow intrinsic for op applied to non-int type"),
+        };
 
         // TODO(antoyo): remove duplication with intrinsic?
-        let name =
-            if self.is_native_int_type(lhs.get_type()) {
-                match oop {
-                    OverflowOp::Add =>
-                        match new_kind {
-                            Int(I8) => "__builtin_add_overflow",
-                            Int(I16) => "__builtin_add_overflow",
-                            Int(I32) => "__builtin_sadd_overflow",
-                            Int(I64) => "__builtin_saddll_overflow",
-                            Int(I128) => "__builtin_add_overflow",
-
-                            Uint(U8) => "__builtin_add_overflow",
-                            Uint(U16) => "__builtin_add_overflow",
-                            Uint(U32) => "__builtin_uadd_overflow",
-                            Uint(U64) => "__builtin_uaddll_overflow",
-                            Uint(U128) => "__builtin_add_overflow",
-
+        let name = if self.is_native_int_type(lhs.get_type()) {
+            match oop {
+                OverflowOp::Add => match new_kind {
+                    Int(I8) => "__builtin_add_overflow",
+                    Int(I16) => "__builtin_add_overflow",
+                    Int(I32) => "__builtin_sadd_overflow",
+                    Int(I64) => "__builtin_saddll_overflow",
+                    Int(I128) => "__builtin_add_overflow",
+
+                    Uint(U8) => "__builtin_add_overflow",
+                    Uint(U16) => "__builtin_add_overflow",
+                    Uint(U32) => "__builtin_uadd_overflow",
+                    Uint(U64) => "__builtin_uaddll_overflow",
+                    Uint(U128) => "__builtin_add_overflow",
+
+                    _ => unreachable!(),
+                },
+                OverflowOp::Sub => match new_kind {
+                    Int(I8) => "__builtin_sub_overflow",
+                    Int(I16) => "__builtin_sub_overflow",
+                    Int(I32) => "__builtin_ssub_overflow",
+                    Int(I64) => "__builtin_ssubll_overflow",
+                    Int(I128) => "__builtin_sub_overflow",
+
+                    Uint(U8) => "__builtin_sub_overflow",
+                    Uint(U16) => "__builtin_sub_overflow",
+                    Uint(U32) => "__builtin_usub_overflow",
+                    Uint(U64) => "__builtin_usubll_overflow",
+                    Uint(U128) => "__builtin_sub_overflow",
+
+                    _ => unreachable!(),
+                },
+                OverflowOp::Mul => match new_kind {
+                    Int(I8) => "__builtin_mul_overflow",
+                    Int(I16) => "__builtin_mul_overflow",
+                    Int(I32) => "__builtin_smul_overflow",
+                    Int(I64) => "__builtin_smulll_overflow",
+                    Int(I128) => "__builtin_mul_overflow",
+
+                    Uint(U8) => "__builtin_mul_overflow",
+                    Uint(U16) => "__builtin_mul_overflow",
+                    Uint(U32) => "__builtin_umul_overflow",
+                    Uint(U64) => "__builtin_umulll_overflow",
+                    Uint(U128) => "__builtin_mul_overflow",
+
+                    _ => unreachable!(),
+                },
+            }
+        } else {
+            match new_kind {
+                Int(I128) | Uint(U128) => {
+                    let func_name = match oop {
+                        OverflowOp::Add => match new_kind {
+                            Int(I128) => "__rust_i128_addo",
+                            Uint(U128) => "__rust_u128_addo",
                             _ => unreachable!(),
                         },
-                    OverflowOp::Sub =>
-                        match new_kind {
-                            Int(I8) => "__builtin_sub_overflow",
-                            Int(I16) => "__builtin_sub_overflow",
-                            Int(I32) => "__builtin_ssub_overflow",
-                            Int(I64) => "__builtin_ssubll_overflow",
-                            Int(I128) => "__builtin_sub_overflow",
-
-                            Uint(U8) => "__builtin_sub_overflow",
-                            Uint(U16) => "__builtin_sub_overflow",
-                            Uint(U32) => "__builtin_usub_overflow",
-                            Uint(U64) => "__builtin_usubll_overflow",
-                            Uint(U128) => "__builtin_sub_overflow",
-
+                        OverflowOp::Sub => match new_kind {
+                            Int(I128) => "__rust_i128_subo",
+                            Uint(U128) => "__rust_u128_subo",
                             _ => unreachable!(),
                         },
-                    OverflowOp::Mul =>
-                        match new_kind {
-                            Int(I8) => "__builtin_mul_overflow",
-                            Int(I16) => "__builtin_mul_overflow",
-                            Int(I32) => "__builtin_smul_overflow",
-                            Int(I64) => "__builtin_smulll_overflow",
-                            Int(I128) => "__builtin_mul_overflow",
-
-                            Uint(U8) => "__builtin_mul_overflow",
-                            Uint(U16) => "__builtin_mul_overflow",
-                            Uint(U32) => "__builtin_umul_overflow",
-                            Uint(U64) => "__builtin_umulll_overflow",
-                            Uint(U128) => "__builtin_mul_overflow",
-
+                        OverflowOp::Mul => match new_kind {
+                            Int(I128) => "__rust_i128_mulo", // TODO(antoyo): use __muloti4d instead?
+                            Uint(U128) => "__rust_u128_mulo",
                             _ => unreachable!(),
                         },
+                    };
+                    return self.operation_with_overflow(func_name, lhs, rhs);
                 }
-            }
-            else {
-                match new_kind {
-                    Int(I128) | Uint(U128) => {
-                        let func_name =
-                            match oop {
-                                OverflowOp::Add =>
-                                    match new_kind {
-                                        Int(I128) => "__rust_i128_addo",
-                                        Uint(U128) => "__rust_u128_addo",
-                                        _ => unreachable!(),
-                                    },
-                                OverflowOp::Sub =>
-                                    match new_kind {
-                                        Int(I128) => "__rust_i128_subo",
-                                        Uint(U128) => "__rust_u128_subo",
-                                        _ => unreachable!(),
-                                    },
-                                OverflowOp::Mul =>
-                                    match new_kind {
-                                        Int(I128) => "__rust_i128_mulo", // TODO(antoyo): use __muloti4d instead?
-                                        Uint(U128) => "__rust_u128_mulo",
-                                        _ => unreachable!(),
-                                    },
-                            };
-                        return self.operation_with_overflow(func_name, lhs, rhs);
+                _ => match oop {
+                    OverflowOp::Mul => match new_kind {
+                        Int(I32) => "__mulosi4",
+                        Int(I64) => "__mulodi4",
+                        _ => unreachable!(),
                     },
-                    _ => {
-                        match oop {
-                            OverflowOp::Mul =>
-                                match new_kind {
-                                    Int(I32) => "__mulosi4",
-                                    Int(I64) => "__mulodi4",
-                                    _ => unreachable!(),
-                                },
-                            _ => unimplemented!("overflow operation for {:?}", new_kind),
-                        }
-                    }
-                }
-            };
+                    _ => unimplemented!("overflow operation for {:?}", new_kind),
+                },
+            }
+        };
 
         let intrinsic = self.context.get_builtin_function(&name);
-        let res = self.current_func()
+        let res = self
+            .current_func()
             // TODO(antoyo): is it correct to use rhs type instead of the parameter typ?
-            .new_local(None, rhs.get_type(), "binopResult")
-            .get_address(None);
+            .new_local(self.location, rhs.get_type(), "binopResult")
+            .get_address(self.location);
         let overflow = self.overflow_call(intrinsic, &[lhs, rhs, res], None);
-        (res.dereference(None).to_rvalue(), overflow)
+        (res.dereference(self.location).to_rvalue(), overflow)
     }
 
-    pub fn operation_with_overflow(&self, func_name: &str, lhs: RValue<'gcc>, rhs: RValue<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) {
+    pub fn operation_with_overflow(
+        &self,
+        func_name: &str,
+        lhs: RValue<'gcc>,
+        rhs: RValue<'gcc>,
+    ) -> (RValue<'gcc>, RValue<'gcc>) {
         let a_type = lhs.get_type();
         let b_type = rhs.get_type();
         debug_assert!(a_type.dyncast_array().is_some());
         debug_assert!(b_type.dyncast_array().is_some());
-        let param_a = self.context.new_parameter(None, a_type, "a");
-        let param_b = self.context.new_parameter(None, b_type, "b");
-        let result_field = self.context.new_field(None, a_type, "result");
-        let overflow_field = self.context.new_field(None, self.bool_type, "overflow");
+        let param_a = self.context.new_parameter(self.location, a_type, "a");
+        let param_b = self.context.new_parameter(self.location, b_type, "b");
+        let result_field = self.context.new_field(self.location, a_type, "result");
+        let overflow_field = self.context.new_field(self.location, self.bool_type, "overflow");
 
         let ret_ty = Ty::new_tup(self.tcx, &[self.tcx.types.i128, self.tcx.types.bool]);
         let layout = self.tcx.layout_of(ParamEnv::reveal_all().and(ret_ty)).unwrap();
 
-        let arg_abi = ArgAbi {
-            layout,
-            mode: PassMode::Direct(ArgAttributes::new()),
-        };
+        let arg_abi = ArgAbi { layout, mode: PassMode::Direct(ArgAttributes::new()) };
         let mut fn_abi = FnAbi {
             args: vec![arg_abi.clone(), arg_abi.clone()].into_boxed_slice(),
             ret: arg_abi,
@@ -366,38 +381,66 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
             conv: Conv::C,
             can_unwind: false,
         };
-        fn_abi.adjust_for_foreign_abi(self.cx, spec::abi::Abi::C {
-            unwind: false,
-        }).unwrap();
+        fn_abi.adjust_for_foreign_abi(self.cx, spec::abi::Abi::C { unwind: false }).unwrap();
 
         let indirect = matches!(fn_abi.ret.mode, PassMode::Indirect { .. });
 
-        let return_type = self.context.new_struct_type(None, "result_overflow", &[result_field, overflow_field]);
-        let result =
-            if indirect {
-                let return_value = self.current_func().new_local(None, return_type.as_type(), "return_value");
-                let return_param_type = return_type.as_type().make_pointer();
-                let return_param = self.context.new_parameter(None, return_param_type, "return_value");
-                let func = self.context.new_function(None, FunctionType::Extern, self.type_void(), &[return_param, param_a, param_b], func_name, false);
-                self.llbb().add_eval(None, self.context.new_call(None, func, &[return_value.get_address(None), lhs, rhs]));
-                return_value.to_rvalue()
-            }
-            else {
-                let func = self.context.new_function(None, FunctionType::Extern, return_type.as_type(), &[param_a, param_b], func_name, false);
-                self.context.new_call(None, func, &[lhs, rhs])
-            };
-        let overflow = result.access_field(None, overflow_field);
-        let int_result = result.access_field(None, result_field);
-        return (int_result, overflow);
+        let return_type = self.context.new_struct_type(
+            self.location,
+            "result_overflow",
+            &[result_field, overflow_field],
+        );
+        let result = if indirect {
+            let return_value =
+                self.current_func().new_local(self.location, return_type.as_type(), "return_value");
+            let return_param_type = return_type.as_type().make_pointer();
+            let return_param =
+                self.context.new_parameter(self.location, return_param_type, "return_value");
+            let func = self.context.new_function(
+                self.location,
+                FunctionType::Extern,
+                self.type_void(),
+                &[return_param, param_a, param_b],
+                func_name,
+                false,
+            );
+            self.llbb().add_eval(
+                self.location,
+                self.context.new_call(
+                    self.location,
+                    func,
+                    &[return_value.get_address(self.location), lhs, rhs],
+                ),
+            );
+            return_value.to_rvalue()
+        } else {
+            let func = self.context.new_function(
+                self.location,
+                FunctionType::Extern,
+                return_type.as_type(),
+                &[param_a, param_b],
+                func_name,
+                false,
+            );
+            self.context.new_call(self.location, func, &[lhs, rhs])
+        };
+        let overflow = result.access_field(self.location, overflow_field);
+        let int_result = result.access_field(self.location, result_field);
+        (int_result, overflow)
     }
 
-    pub fn gcc_icmp(&mut self, op: IntPredicate, mut lhs: RValue<'gcc>, mut rhs: RValue<'gcc>) -> RValue<'gcc> {
+    pub fn gcc_icmp(
+        &mut self,
+        op: IntPredicate,
+        mut lhs: RValue<'gcc>,
+        mut rhs: RValue<'gcc>,
+    ) -> RValue<'gcc> {
         let a_type = lhs.get_type();
         let b_type = rhs.get_type();
         if self.is_non_native_int_type(a_type) || self.is_non_native_int_type(b_type) {
             // This algorithm is based on compiler-rt's __cmpti2:
             // https://github.com/llvm-mirror/compiler-rt/blob/f0745e8476f069296a7c71accedd061dce4cdf79/lib/builtins/cmpti2.c#L21
-            let result = self.current_func().new_local(None, self.int_type, "icmp_result");
+            let result = self.current_func().new_local(self.location, self.int_type, "icmp_result");
             let block1 = self.current_func().new_block("block1");
             let block2 = self.current_func().new_block("block2");
             let block3 = self.current_func().new_block("block3");
@@ -413,92 +456,149 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
             // the sign is only on high).
             let unsigned_type = native_int_type.to_unsigned(&self.cx);
 
-            let lhs_low = self.context.new_cast(None, self.low(lhs), unsigned_type);
-            let rhs_low = self.context.new_cast(None, self.low(rhs), unsigned_type);
+            let lhs_low = self.context.new_cast(self.location, self.low(lhs), unsigned_type);
+            let rhs_low = self.context.new_cast(self.location, self.low(rhs), unsigned_type);
 
-            let condition = self.context.new_comparison(None, ComparisonOp::LessThan, self.high(lhs), self.high(rhs));
-            self.llbb().end_with_conditional(None, condition, block1, block2);
+            let condition = self.context.new_comparison(
+                self.location,
+                ComparisonOp::LessThan,
+                self.high(lhs),
+                self.high(rhs),
+            );
+            self.llbb().end_with_conditional(self.location, condition, block1, block2);
 
-            block1.add_assignment(None, result, self.context.new_rvalue_zero(self.int_type));
-            block1.end_with_jump(None, after);
+            block1.add_assignment(
+                self.location,
+                result,
+                self.context.new_rvalue_zero(self.int_type),
+            );
+            block1.end_with_jump(self.location, after);
 
-            let condition = self.context.new_comparison(None, ComparisonOp::GreaterThan, self.high(lhs), self.high(rhs));
-            block2.end_with_conditional(None, condition, block3, block4);
+            let condition = self.context.new_comparison(
+                self.location,
+                ComparisonOp::GreaterThan,
+                self.high(lhs),
+                self.high(rhs),
+            );
+            block2.end_with_conditional(self.location, condition, block3, block4);
 
-            block3.add_assignment(None, result, self.context.new_rvalue_from_int(self.int_type, 2));
-            block3.end_with_jump(None, after);
+            block3.add_assignment(
+                self.location,
+                result,
+                self.context.new_rvalue_from_int(self.int_type, 2),
+            );
+            block3.end_with_jump(self.location, after);
 
-            let condition = self.context.new_comparison(None, ComparisonOp::LessThan, lhs_low, rhs_low);
-            block4.end_with_conditional(None, condition, block5, block6);
+            let condition = self.context.new_comparison(
+                self.location,
+                ComparisonOp::LessThan,
+                lhs_low,
+                rhs_low,
+            );
+            block4.end_with_conditional(self.location, condition, block5, block6);
 
-            block5.add_assignment(None, result, self.context.new_rvalue_zero(self.int_type));
-            block5.end_with_jump(None, after);
+            block5.add_assignment(
+                self.location,
+                result,
+                self.context.new_rvalue_zero(self.int_type),
+            );
+            block5.end_with_jump(self.location, after);
 
-            let condition = self.context.new_comparison(None, ComparisonOp::GreaterThan, lhs_low, rhs_low);
-            block6.end_with_conditional(None, condition, block7, block8);
+            let condition = self.context.new_comparison(
+                self.location,
+                ComparisonOp::GreaterThan,
+                lhs_low,
+                rhs_low,
+            );
+            block6.end_with_conditional(self.location, condition, block7, block8);
 
-            block7.add_assignment(None, result, self.context.new_rvalue_from_int(self.int_type, 2));
-            block7.end_with_jump(None, after);
+            block7.add_assignment(
+                self.location,
+                result,
+                self.context.new_rvalue_from_int(self.int_type, 2),
+            );
+            block7.end_with_jump(self.location, after);
 
-            block8.add_assignment(None, result, self.context.new_rvalue_one(self.int_type));
-            block8.end_with_jump(None, after);
+            block8.add_assignment(
+                self.location,
+                result,
+                self.context.new_rvalue_one(self.int_type),
+            );
+            block8.end_with_jump(self.location, after);
 
             // NOTE: since jumps were added in a place rustc does not expect, the current block in the
             // state need to be updated.
             self.switch_to_block(after);
 
             let cmp = result.to_rvalue();
-            let (op, limit) =
-                match op {
-                    IntPredicate::IntEQ => {
-                        return self.context.new_comparison(None, ComparisonOp::Equals, cmp, self.context.new_rvalue_one(self.int_type));
-                    },
-                    IntPredicate::IntNE => {
-                        return self.context.new_comparison(None, ComparisonOp::NotEquals, cmp, self.context.new_rvalue_one(self.int_type));
-                    },
-                    // TODO(antoyo): cast to u128 for unsigned comparison. See below.
-                    IntPredicate::IntUGT => (ComparisonOp::Equals, 2),
-                    IntPredicate::IntUGE => (ComparisonOp::GreaterThanEquals, 1),
-                    IntPredicate::IntULT => (ComparisonOp::Equals, 0),
-                    IntPredicate::IntULE => (ComparisonOp::LessThanEquals, 1),
-                    IntPredicate::IntSGT => (ComparisonOp::Equals, 2),
-                    IntPredicate::IntSGE => (ComparisonOp::GreaterThanEquals, 1),
-                    IntPredicate::IntSLT => (ComparisonOp::Equals, 0),
-                    IntPredicate::IntSLE => (ComparisonOp::LessThanEquals, 1),
-                };
-            self.context.new_comparison(None, op, cmp, self.context.new_rvalue_from_int(self.int_type, limit))
-        }
-        else if a_type.get_pointee().is_some() && b_type.get_pointee().is_some() {
+            let (op, limit) = match op {
+                IntPredicate::IntEQ => {
+                    return self.context.new_comparison(
+                        self.location,
+                        ComparisonOp::Equals,
+                        cmp,
+                        self.context.new_rvalue_one(self.int_type),
+                    );
+                }
+                IntPredicate::IntNE => {
+                    return self.context.new_comparison(
+                        self.location,
+                        ComparisonOp::NotEquals,
+                        cmp,
+                        self.context.new_rvalue_one(self.int_type),
+                    );
+                }
+                // TODO(antoyo): cast to u128 for unsigned comparison. See below.
+                IntPredicate::IntUGT => (ComparisonOp::Equals, 2),
+                IntPredicate::IntUGE => (ComparisonOp::GreaterThanEquals, 1),
+                IntPredicate::IntULT => (ComparisonOp::Equals, 0),
+                IntPredicate::IntULE => (ComparisonOp::LessThanEquals, 1),
+                IntPredicate::IntSGT => (ComparisonOp::Equals, 2),
+                IntPredicate::IntSGE => (ComparisonOp::GreaterThanEquals, 1),
+                IntPredicate::IntSLT => (ComparisonOp::Equals, 0),
+                IntPredicate::IntSLE => (ComparisonOp::LessThanEquals, 1),
+            };
+            self.context.new_comparison(
+                self.location,
+                op,
+                cmp,
+                self.context.new_rvalue_from_int(self.int_type, limit),
+            )
+        } else if a_type.get_pointee().is_some() && b_type.get_pointee().is_some() {
             // NOTE: gcc cannot compare pointers to different objects, but rustc does that, so cast them to usize.
-            lhs = self.context.new_bitcast(None, lhs, self.usize_type);
-            rhs = self.context.new_bitcast(None, rhs, self.usize_type);
-            self.context.new_comparison(None, op.to_gcc_comparison(), lhs, rhs)
-        }
-        else {
+            lhs = self.context.new_bitcast(self.location, lhs, self.usize_type);
+            rhs = self.context.new_bitcast(self.location, rhs, self.usize_type);
+            self.context.new_comparison(self.location, op.to_gcc_comparison(), lhs, rhs)
+        } else {
             if a_type != b_type {
                 // NOTE: because libgccjit cannot compare function pointers.
-                if a_type.dyncast_function_ptr_type().is_some() && b_type.dyncast_function_ptr_type().is_some() {
-                    lhs = self.context.new_cast(None, lhs, self.usize_type.make_pointer());
-                    rhs = self.context.new_cast(None, rhs, self.usize_type.make_pointer());
+                if a_type.dyncast_function_ptr_type().is_some()
+                    && b_type.dyncast_function_ptr_type().is_some()
+                {
+                    lhs = self.context.new_cast(self.location, lhs, self.usize_type.make_pointer());
+                    rhs = self.context.new_cast(self.location, rhs, self.usize_type.make_pointer());
                 }
                 // NOTE: hack because we try to cast a vector type to the same vector type.
                 else if format!("{:?}", a_type) != format!("{:?}", b_type) {
-                    rhs = self.context.new_cast(None, rhs, a_type);
+                    rhs = self.context.new_cast(self.location, rhs, a_type);
                 }
             }
             match op {
-                IntPredicate::IntUGT | IntPredicate::IntUGE | IntPredicate::IntULT | IntPredicate::IntULE => {
+                IntPredicate::IntUGT
+                | IntPredicate::IntUGE
+                | IntPredicate::IntULT
+                | IntPredicate::IntULE => {
                     if !a_type.is_vector() {
                         let unsigned_type = a_type.to_unsigned(&self.cx);
-                        lhs = self.context.new_cast(None, lhs, unsigned_type);
-                        rhs = self.context.new_cast(None, rhs, unsigned_type);
+                        lhs = self.context.new_cast(self.location, lhs, unsigned_type);
+                        rhs = self.context.new_cast(self.location, rhs, unsigned_type);
                     }
-                },
+                }
                 // TODO(antoyo): we probably need to handle signed comparison for unsigned
                 // integers.
                 _ => (),
             }
-            self.context.new_comparison(None, op.to_gcc_comparison(), lhs, rhs)
+            self.context.new_comparison(self.location, op.to_gcc_comparison(), lhs, rhs)
         }
     }
 
@@ -508,12 +608,12 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         if a_type.is_vector() && b_type.is_vector() {
             let b = self.bitcast_if_needed(b, a_type);
             a ^ b
-        }
-        else if self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type) {
+        } else if self.is_native_int_type_or_bool(a_type) && self.is_native_int_type_or_bool(b_type)
+        {
             a ^ b
-        }
-        else {
-            self.from_low_high_rvalues(a_type,
+        } else {
+            self.from_low_high_rvalues(
+                a_type,
                 self.low(a) ^ self.low(b),
                 self.high(a) ^ self.high(b),
             )
@@ -528,25 +628,20 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         if a_native && b_native {
             // FIXME(antoyo): remove the casts when libgccjit can shift an unsigned number by an unsigned number.
             if a_type.is_unsigned(self) && b_type.is_signed(self) {
-                let a = self.context.new_cast(None, a, b_type);
+                let a = self.context.new_cast(self.location, a, b_type);
                 let result = a << b;
-                self.context.new_cast(None, result, a_type)
-            }
-            else if a_type.is_signed(self) && b_type.is_unsigned(self) {
-                let b = self.context.new_cast(None, b, a_type);
+                self.context.new_cast(self.location, result, a_type)
+            } else if a_type.is_signed(self) && b_type.is_unsigned(self) {
+                let b = self.context.new_cast(self.location, b, a_type);
                 a << b
-            }
-            else {
+            } else {
                 a << b
             }
-        }
-        else if a_type.is_vector() && a_type.is_vector() {
+        } else if a_type.is_vector() && a_type.is_vector() {
             a << b
-        }
-        else if a_native && !b_native {
+        } else if a_native && !b_native {
             self.gcc_shl(a, self.gcc_int_cast(b, a_type))
-        }
-        else {
+        } else {
             // NOTE: we cannot use the ashl builtin because it's calling widen_hi() which uses ashl.
             let native_int_type = a_type.dyncast_array().expect("get element type");
 
@@ -557,40 +652,40 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
             let b0_block = func.new_block("b0");
             let actual_else_block = func.new_block("actual_else");
 
-            let result = func.new_local(None, a_type, "shiftResult");
+            let result = func.new_local(self.location, a_type, "shiftResult");
 
             let b = self.gcc_int_cast(b, native_int_type);
             let sixty_four = self.gcc_int(native_int_type, 64);
             let zero = self.gcc_zero(native_int_type);
             let condition = self.gcc_icmp(IntPredicate::IntNE, self.gcc_and(b, sixty_four), zero);
-            self.llbb().end_with_conditional(None, condition, then_block, else_block);
+            self.llbb().end_with_conditional(self.location, condition, then_block, else_block);
 
-            let array_value = self.from_low_high_rvalues(a_type,
-                zero,
-                self.low(a) << (b - sixty_four),
-            );
-            then_block.add_assignment(None, result, array_value);
-            then_block.end_with_jump(None, after_block);
+            let array_value =
+                self.from_low_high_rvalues(a_type, zero, self.low(a) << (b - sixty_four));
+            then_block.add_assignment(self.location, result, array_value);
+            then_block.end_with_jump(self.location, after_block);
 
             let condition = self.gcc_icmp(IntPredicate::IntEQ, b, zero);
-            else_block.end_with_conditional(None, condition, b0_block, actual_else_block);
+            else_block.end_with_conditional(self.location, condition, b0_block, actual_else_block);
 
-            b0_block.add_assignment(None, result, a);
-            b0_block.end_with_jump(None, after_block);
+            b0_block.add_assignment(self.location, result, a);
+            b0_block.end_with_jump(self.location, after_block);
 
             // NOTE: cast low to its unsigned type in order to perform a logical right shift.
             // TODO(antoyo): adjust this ^ comment.
             let unsigned_type = native_int_type.to_unsigned(&self.cx);
-            let casted_low = self.context.new_cast(None, self.low(a), unsigned_type);
-            let shift_value = self.context.new_cast(None, sixty_four - b, unsigned_type);
-            let high_low = self.context.new_cast(None, casted_low >> shift_value, native_int_type);
+            let casted_low = self.context.new_cast(self.location, self.low(a), unsigned_type);
+            let shift_value = self.context.new_cast(self.location, sixty_four - b, unsigned_type);
+            let high_low =
+                self.context.new_cast(self.location, casted_low >> shift_value, native_int_type);
 
-            let array_value = self.from_low_high_rvalues(a_type,
+            let array_value = self.from_low_high_rvalues(
+                a_type,
                 self.low(a) << b,
                 (self.high(a) << b) | high_low,
             );
-            actual_else_block.add_assignment(None, result, array_value);
-            actual_else_block.end_with_jump(None, after_block);
+            actual_else_block.add_assignment(self.location, result, array_value);
+            actual_else_block.end_with_jump(self.location, after_block);
 
             // NOTE: since jumps were added in a place rustc does not expect, the current block in the
             // state need to be updated.
@@ -606,10 +701,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
             let native_int_type = arg_type.dyncast_array().expect("get element type");
             let lsb = self.low(arg);
             let swapped_lsb = self.gcc_bswap(lsb, width / 2);
-            let swapped_lsb = self.context.new_cast(None, swapped_lsb, native_int_type);
+            let swapped_lsb = self.context.new_cast(self.location, swapped_lsb, native_int_type);
             let msb = self.high(arg);
             let swapped_msb = self.gcc_bswap(msb, width / 2);
-            let swapped_msb = self.context.new_cast(None, swapped_msb, native_int_type);
+            let swapped_msb = self.context.new_cast(self.location, swapped_msb, native_int_type);
 
             // NOTE: we also need to swap the two elements here, in addition to swapping inside
             // the elements themselves like done above.
@@ -625,7 +720,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         if param_type != arg_type {
             arg = self.bitcast(arg, param_type);
         }
-        self.cx.context.new_call(None, bswap, &[arg])
+        self.cx.context.new_call(self.location, bswap, &[arg])
     }
 }
 
@@ -633,8 +728,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
     pub fn gcc_int(&self, typ: Type<'gcc>, int: i64) -> RValue<'gcc> {
         if self.is_native_int_type_or_bool(typ) {
             self.context.new_rvalue_from_long(typ, i64::try_from(int).expect("i64::try_from"))
-        }
-        else {
+        } else {
             // NOTE: set the sign in high.
             self.from_low_high(typ, int, -(int.is_negative() as i64))
         }
@@ -645,11 +739,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
             // FIXME(antoyo): libgccjit cannot create 128-bit values yet.
             let num = self.context.new_rvalue_from_long(self.u64_type, int as i64);
             self.gcc_int_cast(num, typ)
-        }
-        else if self.is_native_int_type_or_bool(typ) {
-            self.context.new_rvalue_from_long(typ, u64::try_from(int).expect("u64::try_from") as i64)
-        }
-        else {
+        } else if self.is_native_int_type_or_bool(typ) {
+            self.context
+                .new_rvalue_from_long(typ, u64::try_from(int).expect("u64::try_from") as i64)
+        } else {
             self.from_low_high(typ, int as i64, 0)
         }
     }
@@ -666,17 +759,14 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
                 let sixty_four = self.context.new_rvalue_from_long(typ, 64);
                 let shift = high << sixty_four;
                 shift | self.context.new_cast(None, low, typ)
-            }
-            else {
+            } else {
                 self.from_low_high(typ, low as i64, high as i64)
             }
-        }
-        else if typ.is_i128(self) {
+        } else if typ.is_i128(self) {
             // FIXME(antoyo): libgccjit cannot create 128-bit values yet.
             let num = self.context.new_rvalue_from_long(self.u64_type, num as u64 as i64);
             self.gcc_int_cast(num, typ)
-        }
-        else {
+        } else {
             self.gcc_uint(typ, num as u64)
         }
     }
@@ -684,8 +774,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
     pub fn gcc_zero(&self, typ: Type<'gcc>) -> RValue<'gcc> {
         if self.is_native_int_type_or_bool(typ) {
             self.context.new_rvalue_zero(typ)
-        }
-        else {
+        } else {
             self.from_low_high(typ, 0, 0)
         }
     }
@@ -693,64 +782,88 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
     pub fn gcc_int_width(&self, typ: Type<'gcc>) -> u64 {
         if self.is_native_int_type_or_bool(typ) {
             typ.get_size() as u64 * 8
-        }
-        else {
+        } else {
             // NOTE: the only unsupported types are u128 and i128.
             128
         }
     }
 
-    fn bitwise_operation(&self, operation: BinaryOp, a: RValue<'gcc>, mut b: RValue<'gcc>) -> RValue<'gcc> {
+    fn bitwise_operation(
+        &self,
+        operation: BinaryOp,
+        a: RValue<'gcc>,
+        mut b: RValue<'gcc>,
+        loc: Option<Location<'gcc>>,
+    ) -> RValue<'gcc> {
         let a_type = a.get_type();
         let b_type = b.get_type();
         let a_native = self.is_native_int_type_or_bool(a_type);
         let b_native = self.is_native_int_type_or_bool(b_type);
         if a_type.is_vector() && b_type.is_vector() {
             let b = self.bitcast_if_needed(b, a_type);
-            self.context.new_binary_op(None, operation, a_type, a, b)
-        }
-        else if a_native && b_native {
+            self.context.new_binary_op(loc, operation, a_type, a, b)
+        } else if a_native && b_native {
             if a_type != b_type {
-                b = self.context.new_cast(None, b, a_type);
+                b = self.context.new_cast(loc, b, a_type);
             }
-            self.context.new_binary_op(None, operation, a_type, a, b)
-        }
-        else {
-            assert!(!a_native && !b_native, "both types should either be native or non-native for or operation");
+            self.context.new_binary_op(loc, operation, a_type, a, b)
+        } else {
+            assert!(
+                !a_native && !b_native,
+                "both types should either be native or non-native for or operation"
+            );
             let native_int_type = a_type.dyncast_array().expect("get element type");
-            self.from_low_high_rvalues(a_type,
-                self.context.new_binary_op(None, operation, native_int_type, self.low(a), self.low(b)),
-                self.context.new_binary_op(None, operation, native_int_type, self.high(a), self.high(b)),
+            self.from_low_high_rvalues(
+                a_type,
+                self.context.new_binary_op(
+                    loc,
+                    operation,
+                    native_int_type,
+                    self.low(a),
+                    self.low(b),
+                ),
+                self.context.new_binary_op(
+                    loc,
+                    operation,
+                    native_int_type,
+                    self.high(a),
+                    self.high(b),
+                ),
             )
         }
     }
 
-    pub fn gcc_or(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> {
-        self.bitwise_operation(BinaryOp::BitwiseOr, a, b)
+    pub fn gcc_or(
+        &self,
+        a: RValue<'gcc>,
+        b: RValue<'gcc>,
+        loc: Option<Location<'gcc>>,
+    ) -> RValue<'gcc> {
+        self.bitwise_operation(BinaryOp::BitwiseOr, a, b, loc)
     }
 
     // TODO(antoyo): can we use https://github.com/rust-lang/compiler-builtins/blob/master/src/int/mod.rs#L379 instead?
     pub fn gcc_int_cast(&self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> {
         let value_type = value.get_type();
-        if self.is_native_int_type_or_bool(dest_typ) && self.is_native_int_type_or_bool(value_type) {
+        if self.is_native_int_type_or_bool(dest_typ) && self.is_native_int_type_or_bool(value_type)
+        {
             self.context.new_cast(None, value, dest_typ)
-        }
-        else if self.is_native_int_type_or_bool(dest_typ) {
+        } else if self.is_native_int_type_or_bool(dest_typ) {
             self.context.new_cast(None, self.low(value), dest_typ)
-        }
-        else if self.is_native_int_type_or_bool(value_type) {
+        } else if self.is_native_int_type_or_bool(value_type) {
             let dest_element_type = dest_typ.dyncast_array().expect("get element type");
 
             // NOTE: set the sign of the value.
             let zero = self.context.new_rvalue_zero(value_type);
-            let is_negative = self.context.new_comparison(None, ComparisonOp::LessThan, value, zero);
+            let is_negative =
+                self.context.new_comparison(None, ComparisonOp::LessThan, value, zero);
             let is_negative = self.gcc_int_cast(is_negative, dest_element_type);
-            self.from_low_high_rvalues(dest_typ,
+            self.from_low_high_rvalues(
+                dest_typ,
                 self.context.new_cast(None, value, dest_element_type),
                 self.context.new_unary_op(None, UnaryOp::Minus, dest_element_type, is_negative),
             )
-        }
-        else {
+        } else {
             // Since u128 and i128 are the only types that can be unsupported, we know the type of
             // value and the destination type have the same size, so a bitcast is fine.
 
@@ -759,29 +872,34 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         }
     }
 
-    fn int_to_float_cast(&self, signed: bool, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> {
+    fn int_to_float_cast(
+        &self,
+        signed: bool,
+        value: RValue<'gcc>,
+        dest_typ: Type<'gcc>,
+    ) -> RValue<'gcc> {
         let value_type = value.get_type();
         if self.is_native_int_type_or_bool(value_type) {
             return self.context.new_cast(None, value, dest_typ);
         }
 
         debug_assert!(value_type.dyncast_array().is_some());
-        let name_suffix =
-            match self.type_kind(dest_typ) {
-                TypeKind::Float => "tisf",
-                TypeKind::Double => "tidf",
-                kind => panic!("cannot cast a non-native integer to type {:?}", kind),
-            };
-        let sign =
-            if signed {
-                ""
-            }
-            else {
-                "un"
-            };
+        let name_suffix = match self.type_kind(dest_typ) {
+            TypeKind::Float => "tisf",
+            TypeKind::Double => "tidf",
+            kind => panic!("cannot cast a non-native integer to type {:?}", kind),
+        };
+        let sign = if signed { "" } else { "un" };
         let func_name = format!("__float{}{}", sign, name_suffix);
         let param = self.context.new_parameter(None, value_type, "n");
-        let func = self.context.new_function(None, FunctionType::Extern, dest_typ, &[param], func_name, false);
+        let func = self.context.new_function(
+            None,
+            FunctionType::Extern,
+            dest_typ,
+            &[param],
+            func_name,
+            false,
+        );
         self.context.new_call(None, func, &[value])
     }
 
@@ -789,33 +907,42 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         self.int_to_float_cast(true, value, dest_typ)
     }
 
-    pub fn gcc_uint_to_float_cast(&self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> {
+    pub fn gcc_uint_to_float_cast(
+        &self,
+        value: RValue<'gcc>,
+        dest_typ: Type<'gcc>,
+    ) -> RValue<'gcc> {
         self.int_to_float_cast(false, value, dest_typ)
     }
 
-    fn float_to_int_cast(&self, signed: bool, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> {
+    fn float_to_int_cast(
+        &self,
+        signed: bool,
+        value: RValue<'gcc>,
+        dest_typ: Type<'gcc>,
+    ) -> RValue<'gcc> {
         let value_type = value.get_type();
         if self.is_native_int_type_or_bool(dest_typ) {
             return self.context.new_cast(None, value, dest_typ);
         }
 
         debug_assert!(value_type.dyncast_array().is_some());
-        let name_suffix =
-            match self.type_kind(value_type) {
-                TypeKind::Float => "sfti",
-                TypeKind::Double => "dfti",
-                kind => panic!("cannot cast a {:?} to non-native integer", kind),
-            };
-        let sign =
-            if signed {
-                ""
-            }
-            else {
-                "uns"
-            };
+        let name_suffix = match self.type_kind(value_type) {
+            TypeKind::Float => "sfti",
+            TypeKind::Double => "dfti",
+            kind => panic!("cannot cast a {:?} to non-native integer", kind),
+        };
+        let sign = if signed { "" } else { "uns" };
         let func_name = format!("__fix{}{}", sign, name_suffix);
         let param = self.context.new_parameter(None, value_type, "n");
-        let func = self.context.new_function(None, FunctionType::Extern, dest_typ, &[param], func_name, false);
+        let func = self.context.new_function(
+            None,
+            FunctionType::Extern,
+            dest_typ,
+            &[param],
+            func_name,
+            false,
+        );
         self.context.new_call(None, func, &[value])
     }
 
@@ -823,47 +950,54 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         self.float_to_int_cast(true, value, dest_typ)
     }
 
-    pub fn gcc_float_to_uint_cast(&self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> {
+    pub fn gcc_float_to_uint_cast(
+        &self,
+        value: RValue<'gcc>,
+        dest_typ: Type<'gcc>,
+    ) -> RValue<'gcc> {
         self.float_to_int_cast(false, value, dest_typ)
     }
 
     fn high(&self, value: RValue<'gcc>) -> RValue<'gcc> {
-        let index =
-            match self.sess().target.options.endian {
-                Endian::Little => 1,
-                Endian::Big => 0,
-            };
-        self.context.new_array_access(None, value, self.context.new_rvalue_from_int(self.int_type, index))
+        let index = match self.sess().target.options.endian {
+            Endian::Little => 1,
+            Endian::Big => 0,
+        };
+        self.context
+            .new_array_access(None, value, self.context.new_rvalue_from_int(self.int_type, index))
             .to_rvalue()
     }
 
     fn low(&self, value: RValue<'gcc>) -> RValue<'gcc> {
-        let index =
-            match self.sess().target.options.endian {
-                Endian::Little => 0,
-                Endian::Big => 1,
-            };
-        self.context.new_array_access(None, value, self.context.new_rvalue_from_int(self.int_type, index))
+        let index = match self.sess().target.options.endian {
+            Endian::Little => 0,
+            Endian::Big => 1,
+        };
+        self.context
+            .new_array_access(None, value, self.context.new_rvalue_from_int(self.int_type, index))
             .to_rvalue()
     }
 
-    fn from_low_high_rvalues(&self, typ: Type<'gcc>, low: RValue<'gcc>, high: RValue<'gcc>) -> RValue<'gcc> {
-        let (first, last) =
-            match self.sess().target.options.endian {
-                Endian::Little => (low, high),
-                Endian::Big => (high, low),
-            };
+    fn from_low_high_rvalues(
+        &self,
+        typ: Type<'gcc>,
+        low: RValue<'gcc>,
+        high: RValue<'gcc>,
+    ) -> RValue<'gcc> {
+        let (first, last) = match self.sess().target.options.endian {
+            Endian::Little => (low, high),
+            Endian::Big => (high, low),
+        };
 
         let values = [first, last];
         self.context.new_array_constructor(None, typ, &values)
     }
 
     fn from_low_high(&self, typ: Type<'gcc>, low: i64, high: i64) -> RValue<'gcc> {
-        let (first, last) =
-            match self.sess().target.options.endian {
-                Endian::Little => (low, high),
-                Endian::Big => (high, low),
-            };
+        let (first, last) = match self.sess().target.options.endian {
+            Endian::Little => (low, high),
+            Endian::Big => (high, low),
+        };
 
         let native_int_type = typ.dyncast_array().expect("get element type");
         let values = [
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs b/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs
index 15d67385c3e..c4ae1751fa0 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs
@@ -151,8 +151,10 @@ match name {
     "llvm.amdgcn.msad.u8" => "__builtin_amdgcn_msad_u8",
     "llvm.amdgcn.perm" => "__builtin_amdgcn_perm",
     "llvm.amdgcn.permlane16" => "__builtin_amdgcn_permlane16",
+    "llvm.amdgcn.permlane16.var" => "__builtin_amdgcn_permlane16_var",
     "llvm.amdgcn.permlane64" => "__builtin_amdgcn_permlane64",
     "llvm.amdgcn.permlanex16" => "__builtin_amdgcn_permlanex16",
+    "llvm.amdgcn.permlanex16.var" => "__builtin_amdgcn_permlanex16_var",
     "llvm.amdgcn.qsad.pk.u16.u8" => "__builtin_amdgcn_qsad_pk_u16_u8",
     "llvm.amdgcn.queue.ptr" => "__builtin_amdgcn_queue_ptr",
     "llvm.amdgcn.rcp.legacy" => "__builtin_amdgcn_rcp_legacy",
@@ -160,11 +162,20 @@ match name {
     "llvm.amdgcn.readlane" => "__builtin_amdgcn_readlane",
     "llvm.amdgcn.rsq.legacy" => "__builtin_amdgcn_rsq_legacy",
     "llvm.amdgcn.s.barrier" => "__builtin_amdgcn_s_barrier",
+    "llvm.amdgcn.s.barrier.init" => "__builtin_amdgcn_s_barrier_init",
+    "llvm.amdgcn.s.barrier.join" => "__builtin_amdgcn_s_barrier_join",
+    "llvm.amdgcn.s.barrier.leave" => "__builtin_amdgcn_s_barrier_leave",
+    "llvm.amdgcn.s.barrier.signal" => "__builtin_amdgcn_s_barrier_signal",
+    "llvm.amdgcn.s.barrier.signal.isfirst" => "__builtin_amdgcn_s_barrier_signal_isfirst",
+    "llvm.amdgcn.s.barrier.signal.isfirst.var" => "__builtin_amdgcn_s_barrier_signal_isfirst_var",
+    "llvm.amdgcn.s.barrier.signal.var" => "__builtin_amdgcn_s_barrier_signal_var",
+    "llvm.amdgcn.s.barrier.wait" => "__builtin_amdgcn_s_barrier_wait",
     "llvm.amdgcn.s.dcache.inv" => "__builtin_amdgcn_s_dcache_inv",
     "llvm.amdgcn.s.dcache.inv.vol" => "__builtin_amdgcn_s_dcache_inv_vol",
     "llvm.amdgcn.s.dcache.wb" => "__builtin_amdgcn_s_dcache_wb",
     "llvm.amdgcn.s.dcache.wb.vol" => "__builtin_amdgcn_s_dcache_wb_vol",
     "llvm.amdgcn.s.decperflevel" => "__builtin_amdgcn_s_decperflevel",
+    "llvm.amdgcn.s.get.barrier.state" => "__builtin_amdgcn_s_get_barrier_state",
     "llvm.amdgcn.s.get.waveid.in.workgroup" => "__builtin_amdgcn_s_get_waveid_in_workgroup",
     "llvm.amdgcn.s.getpc" => "__builtin_amdgcn_s_getpc",
     "llvm.amdgcn.s.getreg" => "__builtin_amdgcn_s_getreg",
@@ -176,8 +187,10 @@ match name {
     "llvm.amdgcn.s.setprio" => "__builtin_amdgcn_s_setprio",
     "llvm.amdgcn.s.setreg" => "__builtin_amdgcn_s_setreg",
     "llvm.amdgcn.s.sleep" => "__builtin_amdgcn_s_sleep",
+    "llvm.amdgcn.s.sleep.var" => "__builtin_amdgcn_s_sleep_var",
     "llvm.amdgcn.s.wait.event.export.ready" => "__builtin_amdgcn_s_wait_event_export_ready",
     "llvm.amdgcn.s.waitcnt" => "__builtin_amdgcn_s_waitcnt",
+    "llvm.amdgcn.s.wakeup.barrier" => "__builtin_amdgcn_s_wakeup_barrier",
     "llvm.amdgcn.sad.hi.u8" => "__builtin_amdgcn_sad_hi_u8",
     "llvm.amdgcn.sad.u16" => "__builtin_amdgcn_sad_u16",
     "llvm.amdgcn.sad.u8" => "__builtin_amdgcn_sad_u8",
@@ -314,6 +327,8 @@ match name {
     // bpf
     "llvm.bpf.btf.type.id" => "__builtin_bpf_btf_type_id",
     "llvm.bpf.compare" => "__builtin_bpf_compare",
+    "llvm.bpf.getelementptr.and.load" => "__builtin_bpf_getelementptr_and_load",
+    "llvm.bpf.getelementptr.and.store" => "__builtin_bpf_getelementptr_and_store",
     "llvm.bpf.load.byte" => "__builtin_bpf_load_byte",
     "llvm.bpf.load.half" => "__builtin_bpf_load_half",
     "llvm.bpf.load.word" => "__builtin_bpf_load_word",
@@ -5776,14 +5791,6 @@ match name {
     "llvm.s390.verimf" => "__builtin_s390_verimf",
     "llvm.s390.verimg" => "__builtin_s390_verimg",
     "llvm.s390.verimh" => "__builtin_s390_verimh",
-    "llvm.s390.verllb" => "__builtin_s390_verllb",
-    "llvm.s390.verllf" => "__builtin_s390_verllf",
-    "llvm.s390.verllg" => "__builtin_s390_verllg",
-    "llvm.s390.verllh" => "__builtin_s390_verllh",
-    "llvm.s390.verllvb" => "__builtin_s390_verllvb",
-    "llvm.s390.verllvf" => "__builtin_s390_verllvf",
-    "llvm.s390.verllvg" => "__builtin_s390_verllvg",
-    "llvm.s390.verllvh" => "__builtin_s390_verllvh",
     "llvm.s390.vfaeb" => "__builtin_s390_vfaeb",
     "llvm.s390.vfaef" => "__builtin_s390_vfaef",
     "llvm.s390.vfaeh" => "__builtin_s390_vfaeh",
@@ -5815,7 +5822,7 @@ match name {
     "llvm.s390.vistrh" => "__builtin_s390_vistrh",
     "llvm.s390.vlbb" => "__builtin_s390_vlbb",
     "llvm.s390.vll" => "__builtin_s390_vll",
-    "llvm.s390.vlrl" => "__builtin_s390_vlrl",
+    "llvm.s390.vlrl" => "__builtin_s390_vlrlr",
     "llvm.s390.vmaeb" => "__builtin_s390_vmaeb",
     "llvm.s390.vmaef" => "__builtin_s390_vmaef",
     "llvm.s390.vmaeh" => "__builtin_s390_vmaeh",
@@ -5885,7 +5892,7 @@ match name {
     "llvm.s390.vstrczb" => "__builtin_s390_vstrczb",
     "llvm.s390.vstrczf" => "__builtin_s390_vstrczf",
     "llvm.s390.vstrczh" => "__builtin_s390_vstrczh",
-    "llvm.s390.vstrl" => "__builtin_s390_vstrl",
+    "llvm.s390.vstrl" => "__builtin_s390_vstrlr",
     "llvm.s390.vsumb" => "__builtin_s390_vsumb",
     "llvm.s390.vsumgf" => "__builtin_s390_vsumgf",
     "llvm.s390.vsumgh" => "__builtin_s390_vsumgh",
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs
index 35eb4a11005..ce8dee69a98 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs
@@ -3,94 +3,185 @@ use std::borrow::Cow;
 use gccjit::{Function, FunctionPtrType, RValue, ToRValue, UnaryOp};
 use rustc_codegen_ssa::traits::BuilderMethods;
 
-use crate::{context::CodegenCx, builder::Builder};
+use crate::{builder::Builder, context::CodegenCx};
 
-pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc, 'tcx>, gcc_func: FunctionPtrType<'gcc>, mut args: Cow<'b, [RValue<'gcc>]>, func_name: &str, original_function_name: Option<&String>) -> Cow<'b, [RValue<'gcc>]> {
+pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(
+    builder: &Builder<'a, 'gcc, 'tcx>,
+    gcc_func: FunctionPtrType<'gcc>,
+    mut args: Cow<'b, [RValue<'gcc>]>,
+    func_name: &str,
+    original_function_name: Option<&String>,
+) -> Cow<'b, [RValue<'gcc>]> {
     // Some LLVM intrinsics do not map 1-to-1 to GCC intrinsics, so we add the missing
     // arguments here.
     if gcc_func.get_param_count() != args.len() {
         match &*func_name {
             // NOTE: the following intrinsics have a different number of parameters in LLVM and GCC.
-            "__builtin_ia32_prold512_mask" | "__builtin_ia32_pmuldq512_mask" | "__builtin_ia32_pmuludq512_mask"
-                | "__builtin_ia32_pmaxsd512_mask" | "__builtin_ia32_pmaxsq512_mask" | "__builtin_ia32_pmaxsq256_mask"
-                | "__builtin_ia32_pmaxsq128_mask" | "__builtin_ia32_pmaxud512_mask" | "__builtin_ia32_pmaxuq512_mask"
-                | "__builtin_ia32_pminsd512_mask" | "__builtin_ia32_pminsq512_mask" | "__builtin_ia32_pminsq256_mask"
-                | "__builtin_ia32_pminsq128_mask" | "__builtin_ia32_pminud512_mask" | "__builtin_ia32_pminuq512_mask"
-                | "__builtin_ia32_prolq512_mask" | "__builtin_ia32_prorq512_mask" | "__builtin_ia32_pslldi512_mask"
-                | "__builtin_ia32_psrldi512_mask" | "__builtin_ia32_psllqi512_mask" | "__builtin_ia32_psrlqi512_mask"
-                | "__builtin_ia32_pslld512_mask" | "__builtin_ia32_psrld512_mask" | "__builtin_ia32_psllq512_mask"
-                | "__builtin_ia32_psrlq512_mask" | "__builtin_ia32_psrad512_mask" | "__builtin_ia32_psraq512_mask"
-                | "__builtin_ia32_psradi512_mask" | "__builtin_ia32_psraqi512_mask" | "__builtin_ia32_psrav16si_mask"
-                | "__builtin_ia32_psrav8di_mask" | "__builtin_ia32_prolvd512_mask" | "__builtin_ia32_prorvd512_mask"
-                | "__builtin_ia32_prolvq512_mask" | "__builtin_ia32_prorvq512_mask" | "__builtin_ia32_psllv16si_mask"
-                | "__builtin_ia32_psrlv16si_mask" | "__builtin_ia32_psllv8di_mask" | "__builtin_ia32_psrlv8di_mask"
-                | "__builtin_ia32_permvarsi512_mask" | "__builtin_ia32_vpermilvarps512_mask"
-                | "__builtin_ia32_vpermilvarpd512_mask" | "__builtin_ia32_permvardi512_mask"
-                | "__builtin_ia32_permvarsf512_mask" | "__builtin_ia32_permvarqi512_mask"
-                | "__builtin_ia32_permvarqi256_mask" | "__builtin_ia32_permvarqi128_mask"
-                | "__builtin_ia32_vpmultishiftqb512_mask" | "__builtin_ia32_vpmultishiftqb256_mask"
-                | "__builtin_ia32_vpmultishiftqb128_mask"
-                => {
+            "__builtin_ia32_prold512_mask"
+            | "__builtin_ia32_pmuldq512_mask"
+            | "__builtin_ia32_pmuludq512_mask"
+            | "__builtin_ia32_pmaxsd512_mask"
+            | "__builtin_ia32_pmaxsq512_mask"
+            | "__builtin_ia32_pmaxsq256_mask"
+            | "__builtin_ia32_pmaxsq128_mask"
+            | "__builtin_ia32_pmaxud512_mask"
+            | "__builtin_ia32_pmaxuq512_mask"
+            | "__builtin_ia32_pminsd512_mask"
+            | "__builtin_ia32_pminsq512_mask"
+            | "__builtin_ia32_pminsq256_mask"
+            | "__builtin_ia32_pminsq128_mask"
+            | "__builtin_ia32_pminud512_mask"
+            | "__builtin_ia32_pminuq512_mask"
+            | "__builtin_ia32_prolq512_mask"
+            | "__builtin_ia32_prorq512_mask"
+            | "__builtin_ia32_pslldi512_mask"
+            | "__builtin_ia32_psrldi512_mask"
+            | "__builtin_ia32_psllqi512_mask"
+            | "__builtin_ia32_psrlqi512_mask"
+            | "__builtin_ia32_pslld512_mask"
+            | "__builtin_ia32_psrld512_mask"
+            | "__builtin_ia32_psllq512_mask"
+            | "__builtin_ia32_psrlq512_mask"
+            | "__builtin_ia32_psrad512_mask"
+            | "__builtin_ia32_psraq512_mask"
+            | "__builtin_ia32_psradi512_mask"
+            | "__builtin_ia32_psraqi512_mask"
+            | "__builtin_ia32_psrav16si_mask"
+            | "__builtin_ia32_psrav8di_mask"
+            | "__builtin_ia32_prolvd512_mask"
+            | "__builtin_ia32_prorvd512_mask"
+            | "__builtin_ia32_prolvq512_mask"
+            | "__builtin_ia32_prorvq512_mask"
+            | "__builtin_ia32_psllv16si_mask"
+            | "__builtin_ia32_psrlv16si_mask"
+            | "__builtin_ia32_psllv8di_mask"
+            | "__builtin_ia32_psrlv8di_mask"
+            | "__builtin_ia32_permvarsi512_mask"
+            | "__builtin_ia32_vpermilvarps512_mask"
+            | "__builtin_ia32_vpermilvarpd512_mask"
+            | "__builtin_ia32_permvardi512_mask"
+            | "__builtin_ia32_permvarsf512_mask"
+            | "__builtin_ia32_permvarqi512_mask"
+            | "__builtin_ia32_permvarqi256_mask"
+            | "__builtin_ia32_permvarqi128_mask"
+            | "__builtin_ia32_vpmultishiftqb512_mask"
+            | "__builtin_ia32_vpmultishiftqb256_mask"
+            | "__builtin_ia32_vpmultishiftqb128_mask" => {
                 let mut new_args = args.to_vec();
                 let arg3_type = gcc_func.get_param_type(2);
-                let first_arg = builder.current_func().new_local(None, arg3_type, "undefined_for_intrinsic").to_rvalue();
+                let first_arg = builder
+                    .current_func()
+                    .new_local(None, arg3_type, "undefined_for_intrinsic")
+                    .to_rvalue();
                 new_args.push(first_arg);
                 let arg4_type = gcc_func.get_param_type(3);
                 let minus_one = builder.context.new_rvalue_from_int(arg4_type, -1);
                 new_args.push(minus_one);
                 args = new_args.into();
-            },
-            "__builtin_ia32_pmaxuq256_mask" | "__builtin_ia32_pmaxuq128_mask" | "__builtin_ia32_pminuq256_mask"
-                | "__builtin_ia32_pminuq128_mask" | "__builtin_ia32_prold256_mask" | "__builtin_ia32_prold128_mask"
-                | "__builtin_ia32_prord512_mask" | "__builtin_ia32_prord256_mask" | "__builtin_ia32_prord128_mask"
-                | "__builtin_ia32_prolq256_mask" | "__builtin_ia32_prolq128_mask" | "__builtin_ia32_prorq256_mask"
-                | "__builtin_ia32_prorq128_mask" | "__builtin_ia32_psraq256_mask" | "__builtin_ia32_psraq128_mask"
-                | "__builtin_ia32_psraqi256_mask" | "__builtin_ia32_psraqi128_mask" | "__builtin_ia32_psravq256_mask"
-                | "__builtin_ia32_psravq128_mask" | "__builtin_ia32_prolvd256_mask" | "__builtin_ia32_prolvd128_mask"
-                | "__builtin_ia32_prorvd256_mask" | "__builtin_ia32_prorvd128_mask" | "__builtin_ia32_prolvq256_mask"
-                | "__builtin_ia32_prolvq128_mask" | "__builtin_ia32_prorvq256_mask" | "__builtin_ia32_prorvq128_mask"
-                | "__builtin_ia32_permvardi256_mask" | "__builtin_ia32_permvardf512_mask" | "__builtin_ia32_permvardf256_mask"
-                | "__builtin_ia32_pmulhuw512_mask" | "__builtin_ia32_pmulhw512_mask" | "__builtin_ia32_pmulhrsw512_mask"
-                | "__builtin_ia32_pmaxuw512_mask" | "__builtin_ia32_pmaxub512_mask" | "__builtin_ia32_pmaxsw512_mask"
-                | "__builtin_ia32_pmaxsb512_mask" | "__builtin_ia32_pminuw512_mask" | "__builtin_ia32_pminub512_mask"
-                | "__builtin_ia32_pminsw512_mask" | "__builtin_ia32_pminsb512_mask"
-                | "__builtin_ia32_pmaddwd512_mask" | "__builtin_ia32_pmaddubsw512_mask" | "__builtin_ia32_packssdw512_mask"
-                | "__builtin_ia32_packsswb512_mask" | "__builtin_ia32_packusdw512_mask" | "__builtin_ia32_packuswb512_mask"
-                | "__builtin_ia32_pavgw512_mask" | "__builtin_ia32_pavgb512_mask" | "__builtin_ia32_psllw512_mask"
-                | "__builtin_ia32_psllwi512_mask" | "__builtin_ia32_psllv32hi_mask" | "__builtin_ia32_psrlw512_mask"
-                | "__builtin_ia32_psrlwi512_mask" | "__builtin_ia32_psllv16hi_mask" | "__builtin_ia32_psllv8hi_mask"
-                | "__builtin_ia32_psrlv32hi_mask" | "__builtin_ia32_psraw512_mask" | "__builtin_ia32_psrawi512_mask"
-                | "__builtin_ia32_psrlv16hi_mask" | "__builtin_ia32_psrlv8hi_mask" | "__builtin_ia32_psrav32hi_mask"
-                | "__builtin_ia32_permvarhi512_mask" | "__builtin_ia32_pshufb512_mask" | "__builtin_ia32_psrav16hi_mask"
-                | "__builtin_ia32_psrav8hi_mask" | "__builtin_ia32_permvarhi256_mask" | "__builtin_ia32_permvarhi128_mask"
-                => {
+            }
+            "__builtin_ia32_pmaxuq256_mask"
+            | "__builtin_ia32_pmaxuq128_mask"
+            | "__builtin_ia32_pminuq256_mask"
+            | "__builtin_ia32_pminuq128_mask"
+            | "__builtin_ia32_prold256_mask"
+            | "__builtin_ia32_prold128_mask"
+            | "__builtin_ia32_prord512_mask"
+            | "__builtin_ia32_prord256_mask"
+            | "__builtin_ia32_prord128_mask"
+            | "__builtin_ia32_prolq256_mask"
+            | "__builtin_ia32_prolq128_mask"
+            | "__builtin_ia32_prorq256_mask"
+            | "__builtin_ia32_prorq128_mask"
+            | "__builtin_ia32_psraq256_mask"
+            | "__builtin_ia32_psraq128_mask"
+            | "__builtin_ia32_psraqi256_mask"
+            | "__builtin_ia32_psraqi128_mask"
+            | "__builtin_ia32_psravq256_mask"
+            | "__builtin_ia32_psravq128_mask"
+            | "__builtin_ia32_prolvd256_mask"
+            | "__builtin_ia32_prolvd128_mask"
+            | "__builtin_ia32_prorvd256_mask"
+            | "__builtin_ia32_prorvd128_mask"
+            | "__builtin_ia32_prolvq256_mask"
+            | "__builtin_ia32_prolvq128_mask"
+            | "__builtin_ia32_prorvq256_mask"
+            | "__builtin_ia32_prorvq128_mask"
+            | "__builtin_ia32_permvardi256_mask"
+            | "__builtin_ia32_permvardf512_mask"
+            | "__builtin_ia32_permvardf256_mask"
+            | "__builtin_ia32_pmulhuw512_mask"
+            | "__builtin_ia32_pmulhw512_mask"
+            | "__builtin_ia32_pmulhrsw512_mask"
+            | "__builtin_ia32_pmaxuw512_mask"
+            | "__builtin_ia32_pmaxub512_mask"
+            | "__builtin_ia32_pmaxsw512_mask"
+            | "__builtin_ia32_pmaxsb512_mask"
+            | "__builtin_ia32_pminuw512_mask"
+            | "__builtin_ia32_pminub512_mask"
+            | "__builtin_ia32_pminsw512_mask"
+            | "__builtin_ia32_pminsb512_mask"
+            | "__builtin_ia32_pmaddwd512_mask"
+            | "__builtin_ia32_pmaddubsw512_mask"
+            | "__builtin_ia32_packssdw512_mask"
+            | "__builtin_ia32_packsswb512_mask"
+            | "__builtin_ia32_packusdw512_mask"
+            | "__builtin_ia32_packuswb512_mask"
+            | "__builtin_ia32_pavgw512_mask"
+            | "__builtin_ia32_pavgb512_mask"
+            | "__builtin_ia32_psllw512_mask"
+            | "__builtin_ia32_psllwi512_mask"
+            | "__builtin_ia32_psllv32hi_mask"
+            | "__builtin_ia32_psrlw512_mask"
+            | "__builtin_ia32_psrlwi512_mask"
+            | "__builtin_ia32_psllv16hi_mask"
+            | "__builtin_ia32_psllv8hi_mask"
+            | "__builtin_ia32_psrlv32hi_mask"
+            | "__builtin_ia32_psraw512_mask"
+            | "__builtin_ia32_psrawi512_mask"
+            | "__builtin_ia32_psrlv16hi_mask"
+            | "__builtin_ia32_psrlv8hi_mask"
+            | "__builtin_ia32_psrav32hi_mask"
+            | "__builtin_ia32_permvarhi512_mask"
+            | "__builtin_ia32_pshufb512_mask"
+            | "__builtin_ia32_psrav16hi_mask"
+            | "__builtin_ia32_psrav8hi_mask"
+            | "__builtin_ia32_permvarhi256_mask"
+            | "__builtin_ia32_permvarhi128_mask" => {
                 let mut new_args = args.to_vec();
                 let arg3_type = gcc_func.get_param_type(2);
                 let vector_type = arg3_type.dyncast_vector().expect("vector type");
                 let zero = builder.context.new_rvalue_zero(vector_type.get_element_type());
                 let num_units = vector_type.get_num_units();
-                let first_arg = builder.context.new_rvalue_from_vector(None, arg3_type, &vec![zero; num_units]);
+                let first_arg =
+                    builder.context.new_rvalue_from_vector(None, arg3_type, &vec![zero; num_units]);
                 new_args.push(first_arg);
                 let arg4_type = gcc_func.get_param_type(3);
                 let minus_one = builder.context.new_rvalue_from_int(arg4_type, -1);
                 new_args.push(minus_one);
                 args = new_args.into();
-            },
-            "__builtin_ia32_dbpsadbw512_mask" | "__builtin_ia32_dbpsadbw256_mask" | "__builtin_ia32_dbpsadbw128_mask" => {
+            }
+            "__builtin_ia32_dbpsadbw512_mask"
+            | "__builtin_ia32_dbpsadbw256_mask"
+            | "__builtin_ia32_dbpsadbw128_mask" => {
                 let mut new_args = args.to_vec();
                 let arg4_type = gcc_func.get_param_type(3);
                 let vector_type = arg4_type.dyncast_vector().expect("vector type");
                 let zero = builder.context.new_rvalue_zero(vector_type.get_element_type());
                 let num_units = vector_type.get_num_units();
-                let first_arg = builder.context.new_rvalue_from_vector(None, arg4_type, &vec![zero; num_units]);
+                let first_arg =
+                    builder.context.new_rvalue_from_vector(None, arg4_type, &vec![zero; num_units]);
                 new_args.push(first_arg);
                 let arg5_type = gcc_func.get_param_type(4);
                 let minus_one = builder.context.new_rvalue_from_int(arg5_type, -1);
                 new_args.push(minus_one);
                 args = new_args.into();
-            },
-            "__builtin_ia32_vplzcntd_512_mask" | "__builtin_ia32_vplzcntd_256_mask" | "__builtin_ia32_vplzcntd_128_mask"
-                | "__builtin_ia32_vplzcntq_512_mask" | "__builtin_ia32_vplzcntq_256_mask" | "__builtin_ia32_vplzcntq_128_mask" => {
+            }
+            "__builtin_ia32_vplzcntd_512_mask"
+            | "__builtin_ia32_vplzcntd_256_mask"
+            | "__builtin_ia32_vplzcntd_128_mask"
+            | "__builtin_ia32_vplzcntq_512_mask"
+            | "__builtin_ia32_vplzcntq_256_mask"
+            | "__builtin_ia32_vplzcntq_128_mask" => {
                 let mut new_args = args.to_vec();
                 // Remove last arg as it doesn't seem to be used in GCC and is always false.
                 new_args.pop();
@@ -98,37 +189,45 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc
                 let vector_type = arg2_type.dyncast_vector().expect("vector type");
                 let zero = builder.context.new_rvalue_zero(vector_type.get_element_type());
                 let num_units = vector_type.get_num_units();
-                let first_arg = builder.context.new_rvalue_from_vector(None, arg2_type, &vec![zero; num_units]);
+                let first_arg =
+                    builder.context.new_rvalue_from_vector(None, arg2_type, &vec![zero; num_units]);
                 new_args.push(first_arg);
                 let arg3_type = gcc_func.get_param_type(2);
                 let minus_one = builder.context.new_rvalue_from_int(arg3_type, -1);
                 new_args.push(minus_one);
                 args = new_args.into();
-            },
-            "__builtin_ia32_vpconflictsi_512_mask" | "__builtin_ia32_vpconflictsi_256_mask"
-                | "__builtin_ia32_vpconflictsi_128_mask" | "__builtin_ia32_vpconflictdi_512_mask"
-                | "__builtin_ia32_vpconflictdi_256_mask" | "__builtin_ia32_vpconflictdi_128_mask" => {
+            }
+            "__builtin_ia32_vpconflictsi_512_mask"
+            | "__builtin_ia32_vpconflictsi_256_mask"
+            | "__builtin_ia32_vpconflictsi_128_mask"
+            | "__builtin_ia32_vpconflictdi_512_mask"
+            | "__builtin_ia32_vpconflictdi_256_mask"
+            | "__builtin_ia32_vpconflictdi_128_mask" => {
                 let mut new_args = args.to_vec();
                 let arg2_type = gcc_func.get_param_type(1);
                 let vector_type = arg2_type.dyncast_vector().expect("vector type");
                 let zero = builder.context.new_rvalue_zero(vector_type.get_element_type());
                 let num_units = vector_type.get_num_units();
-                let first_arg = builder.context.new_rvalue_from_vector(None, arg2_type, &vec![zero; num_units]);
+                let first_arg =
+                    builder.context.new_rvalue_from_vector(None, arg2_type, &vec![zero; num_units]);
                 new_args.push(first_arg);
                 let arg3_type = gcc_func.get_param_type(2);
                 let minus_one = builder.context.new_rvalue_from_int(arg3_type, -1);
                 new_args.push(minus_one);
                 args = new_args.into();
-            },
-            "__builtin_ia32_pternlogd512_mask" | "__builtin_ia32_pternlogd256_mask"
-                | "__builtin_ia32_pternlogd128_mask" | "__builtin_ia32_pternlogq512_mask"
-                | "__builtin_ia32_pternlogq256_mask" | "__builtin_ia32_pternlogq128_mask" => {
+            }
+            "__builtin_ia32_pternlogd512_mask"
+            | "__builtin_ia32_pternlogd256_mask"
+            | "__builtin_ia32_pternlogd128_mask"
+            | "__builtin_ia32_pternlogq512_mask"
+            | "__builtin_ia32_pternlogq256_mask"
+            | "__builtin_ia32_pternlogq128_mask" => {
                 let mut new_args = args.to_vec();
                 let arg5_type = gcc_func.get_param_type(4);
                 let minus_one = builder.context.new_rvalue_from_int(arg5_type, -1);
                 new_args.push(minus_one);
                 args = new_args.into();
-            },
+            }
             "__builtin_ia32_vfmaddps512_mask" | "__builtin_ia32_vfmaddpd512_mask" => {
                 let mut new_args = args.to_vec();
 
@@ -154,24 +253,33 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc
                 }
 
                 args = new_args.into();
-            },
-            "__builtin_ia32_addps512_mask" | "__builtin_ia32_addpd512_mask"
-                | "__builtin_ia32_subps512_mask" | "__builtin_ia32_subpd512_mask"
-                | "__builtin_ia32_mulps512_mask" | "__builtin_ia32_mulpd512_mask"
-                | "__builtin_ia32_divps512_mask" | "__builtin_ia32_divpd512_mask"
-                | "__builtin_ia32_maxps512_mask" | "__builtin_ia32_maxpd512_mask"
-                |  "__builtin_ia32_minps512_mask" | "__builtin_ia32_minpd512_mask" => {
+            }
+            "__builtin_ia32_addps512_mask"
+            | "__builtin_ia32_addpd512_mask"
+            | "__builtin_ia32_subps512_mask"
+            | "__builtin_ia32_subpd512_mask"
+            | "__builtin_ia32_mulps512_mask"
+            | "__builtin_ia32_mulpd512_mask"
+            | "__builtin_ia32_divps512_mask"
+            | "__builtin_ia32_divpd512_mask"
+            | "__builtin_ia32_maxps512_mask"
+            | "__builtin_ia32_maxpd512_mask"
+            | "__builtin_ia32_minps512_mask"
+            | "__builtin_ia32_minpd512_mask" => {
                 let mut new_args = args.to_vec();
                 let last_arg = new_args.pop().expect("last arg");
                 let arg3_type = gcc_func.get_param_type(2);
-                let undefined = builder.current_func().new_local(None, arg3_type, "undefined_for_intrinsic").to_rvalue();
+                let undefined = builder
+                    .current_func()
+                    .new_local(None, arg3_type, "undefined_for_intrinsic")
+                    .to_rvalue();
                 new_args.push(undefined);
                 let arg4_type = gcc_func.get_param_type(3);
                 let minus_one = builder.context.new_rvalue_from_int(arg4_type, -1);
                 new_args.push(minus_one);
                 new_args.push(last_arg);
                 args = new_args.into();
-            },
+            }
             "__builtin_ia32_vfmaddsubps512_mask" | "__builtin_ia32_vfmaddsubpd512_mask" => {
                 let mut new_args = args.to_vec();
                 let last_arg = new_args.pop().expect("last arg");
@@ -180,54 +288,72 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc
                 new_args.push(minus_one);
                 new_args.push(last_arg);
                 args = new_args.into();
-            },
-            "__builtin_ia32_vpermi2vard512_mask" | "__builtin_ia32_vpermi2vard256_mask"
-                | "__builtin_ia32_vpermi2vard128_mask" | "__builtin_ia32_vpermi2varq512_mask"
-                | "__builtin_ia32_vpermi2varq256_mask" | "__builtin_ia32_vpermi2varq128_mask"
-                | "__builtin_ia32_vpermi2varps512_mask" | "__builtin_ia32_vpermi2varps256_mask"
-                | "__builtin_ia32_vpermi2varps128_mask" | "__builtin_ia32_vpermi2varpd512_mask"
-                | "__builtin_ia32_vpermi2varpd256_mask" | "__builtin_ia32_vpermi2varpd128_mask" | "__builtin_ia32_vpmadd52huq512_mask"
-                | "__builtin_ia32_vpmadd52luq512_mask" | "__builtin_ia32_vpmadd52huq256_mask" | "__builtin_ia32_vpmadd52luq256_mask"
-                | "__builtin_ia32_vpmadd52huq128_mask"
-                => {
+            }
+            "__builtin_ia32_vpermi2vard512_mask"
+            | "__builtin_ia32_vpermi2vard256_mask"
+            | "__builtin_ia32_vpermi2vard128_mask"
+            | "__builtin_ia32_vpermi2varq512_mask"
+            | "__builtin_ia32_vpermi2varq256_mask"
+            | "__builtin_ia32_vpermi2varq128_mask"
+            | "__builtin_ia32_vpermi2varps512_mask"
+            | "__builtin_ia32_vpermi2varps256_mask"
+            | "__builtin_ia32_vpermi2varps128_mask"
+            | "__builtin_ia32_vpermi2varpd512_mask"
+            | "__builtin_ia32_vpermi2varpd256_mask"
+            | "__builtin_ia32_vpermi2varpd128_mask"
+            | "__builtin_ia32_vpmadd52huq512_mask"
+            | "__builtin_ia32_vpmadd52luq512_mask"
+            | "__builtin_ia32_vpmadd52huq256_mask"
+            | "__builtin_ia32_vpmadd52luq256_mask"
+            | "__builtin_ia32_vpmadd52huq128_mask" => {
                 let mut new_args = args.to_vec();
                 let arg4_type = gcc_func.get_param_type(3);
                 let minus_one = builder.context.new_rvalue_from_int(arg4_type, -1);
                 new_args.push(minus_one);
                 args = new_args.into();
-            },
-            "__builtin_ia32_cvtdq2ps512_mask" | "__builtin_ia32_cvtudq2ps512_mask"
-                | "__builtin_ia32_sqrtps512_mask" | "__builtin_ia32_sqrtpd512_mask" => {
+            }
+            "__builtin_ia32_cvtdq2ps512_mask"
+            | "__builtin_ia32_cvtudq2ps512_mask"
+            | "__builtin_ia32_sqrtps512_mask"
+            | "__builtin_ia32_sqrtpd512_mask" => {
                 let mut new_args = args.to_vec();
                 let last_arg = new_args.pop().expect("last arg");
                 let arg2_type = gcc_func.get_param_type(1);
-                let undefined = builder.current_func().new_local(None, arg2_type, "undefined_for_intrinsic").to_rvalue();
+                let undefined = builder
+                    .current_func()
+                    .new_local(None, arg2_type, "undefined_for_intrinsic")
+                    .to_rvalue();
                 new_args.push(undefined);
                 let arg3_type = gcc_func.get_param_type(2);
                 let minus_one = builder.context.new_rvalue_from_int(arg3_type, -1);
                 new_args.push(minus_one);
                 new_args.push(last_arg);
                 args = new_args.into();
-            },
+            }
             "__builtin_ia32_stmxcsr" => {
                 args = vec![].into();
-            },
-            "__builtin_ia32_addcarryx_u64" | "__builtin_ia32_sbb_u64" | "__builtin_ia32_addcarryx_u32" | "__builtin_ia32_sbb_u32" => {
+            }
+            "__builtin_ia32_addcarryx_u64"
+            | "__builtin_ia32_sbb_u64"
+            | "__builtin_ia32_addcarryx_u32"
+            | "__builtin_ia32_sbb_u32" => {
                 let mut new_args = args.to_vec();
                 let arg2_type = gcc_func.get_param_type(1);
                 let variable = builder.current_func().new_local(None, arg2_type, "addcarryResult");
                 new_args.push(variable.get_address(None));
                 args = new_args.into();
-            },
-            "__builtin_ia32_vpermt2varqi512_mask" | "__builtin_ia32_vpermt2varqi256_mask"
-                | "__builtin_ia32_vpermt2varqi128_mask" | "__builtin_ia32_vpermt2varhi512_mask"
-                | "__builtin_ia32_vpermt2varhi256_mask" | "__builtin_ia32_vpermt2varhi128_mask"
-                => {
+            }
+            "__builtin_ia32_vpermt2varqi512_mask"
+            | "__builtin_ia32_vpermt2varqi256_mask"
+            | "__builtin_ia32_vpermt2varqi128_mask"
+            | "__builtin_ia32_vpermt2varhi512_mask"
+            | "__builtin_ia32_vpermt2varhi256_mask"
+            | "__builtin_ia32_vpermt2varhi128_mask" => {
                 let new_args = args.to_vec();
                 let arg4_type = gcc_func.get_param_type(3);
                 let minus_one = builder.context.new_rvalue_from_int(arg4_type, -1);
                 args = vec![new_args[1], new_args[0], new_args[2], minus_one].into();
-            },
+            }
             "__builtin_ia32_xrstor" | "__builtin_ia32_xsavec" => {
                 let new_args = args.to_vec();
                 let thirty_two = builder.context.new_rvalue_from_int(new_args[1].get_type(), 32);
@@ -235,22 +361,25 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc
                 let arg2_type = gcc_func.get_param_type(1);
                 let arg2 = builder.context.new_cast(None, arg2, arg2_type);
                 args = vec![new_args[0], arg2].into();
-            },
+            }
             // These builtins are sent one more argument than needed.
             "__builtin_prefetch" => {
                 let mut new_args = args.to_vec();
                 new_args.pop();
                 args = new_args.into();
-            },
+            }
             // The GCC version returns one value of the tuple through a pointer.
             "__builtin_ia32_rdrand64_step" => {
-                let arg = builder.current_func().new_local(None, builder.ulonglong_type, "return_rdrand_arg");
+                let arg = builder.current_func().new_local(
+                    None,
+                    builder.ulonglong_type,
+                    "return_rdrand_arg",
+                );
                 args = vec![arg.get_address(None)].into();
-            },
+            }
             _ => (),
         }
-    }
-    else {
+    } else {
         match &*func_name {
             "__builtin_ia32_rndscaless_mask_round" | "__builtin_ia32_rndscalesd_mask_round" => {
                 let new_args = args.to_vec();
@@ -259,10 +388,10 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc
                 let arg4_type = gcc_func.get_param_type(3);
                 let arg4 = builder.context.new_bitcast(None, new_args[2], arg4_type);
                 args = vec![new_args[0], new_args[1], arg3, arg4, new_args[3], new_args[5]].into();
-            },
+            }
             // NOTE: the LLVM intrinsic receives 3 floats, but the GCC builtin requires 3 vectors.
             // FIXME: the intrinsics like _mm_mask_fmadd_sd should probably directly call the GCC
-            // instrinsic to avoid this.
+            // intrinsic to avoid this.
             "__builtin_ia32_vfmaddss3_round" => {
                 let new_args = args.to_vec();
                 let arg1_type = gcc_func.get_param_type(0);
@@ -272,7 +401,7 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc
                 let b = builder.context.new_rvalue_from_vector(None, arg2_type, &[new_args[1]; 4]);
                 let c = builder.context.new_rvalue_from_vector(None, arg3_type, &[new_args[2]; 4]);
                 args = vec![a, b, c, new_args[3]].into();
-            },
+            }
             "__builtin_ia32_vfmaddsd3_round" => {
                 let new_args = args.to_vec();
                 let arg1_type = gcc_func.get_param_type(0);
@@ -282,25 +411,34 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc
                 let b = builder.context.new_rvalue_from_vector(None, arg2_type, &[new_args[1]; 2]);
                 let c = builder.context.new_rvalue_from_vector(None, arg3_type, &[new_args[2]; 2]);
                 args = vec![a, b, c, new_args[3]].into();
-            },
-            "__builtin_ia32_vfmaddsubpd256" | "__builtin_ia32_vfmaddsubps" | "__builtin_ia32_vfmaddsubps256"
-                | "__builtin_ia32_vfmaddsubpd" => {
+            }
+            "__builtin_ia32_vfmaddsubpd256"
+            | "__builtin_ia32_vfmaddsubps"
+            | "__builtin_ia32_vfmaddsubps256"
+            | "__builtin_ia32_vfmaddsubpd" => {
                 if let Some(original_function_name) = original_function_name {
                     match &**original_function_name {
-                        "llvm.x86.fma.vfmsubadd.pd.256" | "llvm.x86.fma.vfmsubadd.ps" | "llvm.x86.fma.vfmsubadd.ps.256"
-                            | "llvm.x86.fma.vfmsubadd.pd" => {
+                        "llvm.x86.fma.vfmsubadd.pd.256"
+                        | "llvm.x86.fma.vfmsubadd.ps"
+                        | "llvm.x86.fma.vfmsubadd.ps.256"
+                        | "llvm.x86.fma.vfmsubadd.pd" => {
                             // NOTE: since both llvm.x86.fma.vfmsubadd.ps and llvm.x86.fma.vfmaddsub.ps maps to
                             // __builtin_ia32_vfmaddsubps, only add minus if this comes from a
                             // subadd LLVM intrinsic, e.g. _mm256_fmsubadd_pd.
                             let mut new_args = args.to_vec();
                             let arg3 = &mut new_args[2];
-                            *arg3 = builder.context.new_unary_op(None, UnaryOp::Minus, arg3.get_type(), *arg3);
+                            *arg3 = builder.context.new_unary_op(
+                                None,
+                                UnaryOp::Minus,
+                                arg3.get_type(),
+                                *arg3,
+                            );
                             args = new_args.into();
-                        },
+                        }
                         _ => (),
                     }
                 }
-            },
+            }
             "__builtin_ia32_ldmxcsr" => {
                 // The builtin __builtin_ia32_ldmxcsr takes an integer value while llvm.x86.sse.ldmxcsr takes a pointer,
                 // so dereference the pointer.
@@ -309,23 +447,31 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc
                 let arg1 = builder.context.new_cast(None, args[0], uint_ptr_type);
                 new_args[0] = arg1.dereference(None).to_rvalue();
                 args = new_args.into();
-            },
-            "__builtin_ia32_rcp14sd_mask" | "__builtin_ia32_rcp14ss_mask" | "__builtin_ia32_rsqrt14sd_mask"
-                | "__builtin_ia32_rsqrt14ss_mask" => {
+            }
+            "__builtin_ia32_rcp14sd_mask"
+            | "__builtin_ia32_rcp14ss_mask"
+            | "__builtin_ia32_rsqrt14sd_mask"
+            | "__builtin_ia32_rsqrt14ss_mask" => {
                 let new_args = args.to_vec();
                 args = vec![new_args[1], new_args[0], new_args[2], new_args[3]].into();
-            },
+            }
             "__builtin_ia32_sqrtsd_mask_round" | "__builtin_ia32_sqrtss_mask_round" => {
                 let new_args = args.to_vec();
                 args = vec![new_args[1], new_args[0], new_args[2], new_args[3], new_args[4]].into();
-            },
-            "__builtin_ia32_vpshrdv_v8di" | "__builtin_ia32_vpshrdv_v4di" | "__builtin_ia32_vpshrdv_v2di" |
-                "__builtin_ia32_vpshrdv_v16si" | "__builtin_ia32_vpshrdv_v8si" | "__builtin_ia32_vpshrdv_v4si" |
-                "__builtin_ia32_vpshrdv_v32hi" | "__builtin_ia32_vpshrdv_v16hi" | "__builtin_ia32_vpshrdv_v8hi" => {
+            }
+            "__builtin_ia32_vpshrdv_v8di"
+            | "__builtin_ia32_vpshrdv_v4di"
+            | "__builtin_ia32_vpshrdv_v2di"
+            | "__builtin_ia32_vpshrdv_v16si"
+            | "__builtin_ia32_vpshrdv_v8si"
+            | "__builtin_ia32_vpshrdv_v4si"
+            | "__builtin_ia32_vpshrdv_v32hi"
+            | "__builtin_ia32_vpshrdv_v16hi"
+            | "__builtin_ia32_vpshrdv_v8hi" => {
                 // The first two arguments are reversed, compared to LLVM.
                 let new_args = args.to_vec();
                 args = vec![new_args[1], new_args[0], new_args[2]].into();
-            },
+            }
             _ => (),
         }
     }
@@ -333,16 +479,27 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc
     args
 }
 
-pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc, 'tcx>, mut return_value: RValue<'gcc>, func_name: &str, args: &[RValue<'gcc>], args_adjusted: bool, orig_args: &[RValue<'gcc>]) -> RValue<'gcc> {
+pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>(
+    builder: &Builder<'a, 'gcc, 'tcx>,
+    mut return_value: RValue<'gcc>,
+    func_name: &str,
+    args: &[RValue<'gcc>],
+    args_adjusted: bool,
+    orig_args: &[RValue<'gcc>],
+) -> RValue<'gcc> {
     match func_name {
         "__builtin_ia32_vfmaddss3_round" | "__builtin_ia32_vfmaddsd3_round" => {
-            #[cfg(feature="master")]
+            #[cfg(feature = "master")]
             {
                 let zero = builder.context.new_rvalue_zero(builder.int_type);
-                return_value = builder.context.new_vector_access(None, return_value, zero).to_rvalue();
+                return_value =
+                    builder.context.new_vector_access(None, return_value, zero).to_rvalue();
             }
-        },
-        "__builtin_ia32_addcarryx_u64" | "__builtin_ia32_sbb_u64" | "__builtin_ia32_addcarryx_u32" | "__builtin_ia32_sbb_u32" => {
+        }
+        "__builtin_ia32_addcarryx_u64"
+        | "__builtin_ia32_sbb_u64"
+        | "__builtin_ia32_addcarryx_u32"
+        | "__builtin_ia32_sbb_u32" => {
             // Both llvm.x86.addcarry.32 and llvm.x86.addcarryx.u32 points to the same GCC builtin,
             // but only the former requires adjusting the return value.
             // Those 2 LLVM intrinsics differ by their argument count, that's why we check if the
@@ -351,10 +508,16 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc,
                 let last_arg = args.last().expect("last arg");
                 let field1 = builder.context.new_field(None, builder.u8_type, "carryFlag");
                 let field2 = builder.context.new_field(None, args[1].get_type(), "carryResult");
-                let struct_type = builder.context.new_struct_type(None, "addcarryResult", &[field1, field2]);
-                return_value = builder.context.new_struct_constructor(None, struct_type.as_type(), None, &[return_value, last_arg.dereference(None).to_rvalue()]);
+                let struct_type =
+                    builder.context.new_struct_type(None, "addcarryResult", &[field1, field2]);
+                return_value = builder.context.new_struct_constructor(
+                    None,
+                    struct_type.as_type(),
+                    None,
+                    &[return_value, last_arg.dereference(None).to_rvalue()],
+                );
             }
-        },
+        }
         "__builtin_ia32_stmxcsr" => {
             // The builtin __builtin_ia32_stmxcsr returns a value while llvm.x86.sse.stmxcsr writes
             // the result in its pointer argument.
@@ -366,20 +529,24 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>(builder: &Builder<'a, 'gcc,
             // The return value was assigned to the result pointer above. In order to not call the
             // builtin twice, we overwrite the return value with a dummy value.
             return_value = builder.context.new_rvalue_zero(builder.int_type);
-        },
+        }
         "__builtin_ia32_rdrand64_step" => {
             let random_number = args[0].dereference(None).to_rvalue();
-            let success_variable = builder.current_func().new_local(None, return_value.get_type(), "success");
+            let success_variable =
+                builder.current_func().new_local(None, return_value.get_type(), "success");
             builder.llbb().add_assignment(None, success_variable, return_value);
 
             let field1 = builder.context.new_field(None, random_number.get_type(), "random_number");
             let field2 = builder.context.new_field(None, return_value.get_type(), "success");
-            let struct_type = builder.context.new_struct_type(None, "rdrand_result", &[field1, field2]);
-            return_value = builder.context.new_struct_constructor(None, struct_type.as_type(), None, &[
-                random_number,
-                success_variable.to_rvalue(),
-            ]);
-        },
+            let struct_type =
+                builder.context.new_struct_type(None, "rdrand_result", &[field1, field2]);
+            return_value = builder.context.new_struct_constructor(
+                None,
+                struct_type.as_type(),
+                None,
+                &[random_number, success_variable.to_rvalue()],
+            );
+        }
         _ => (),
     }
 
@@ -391,23 +558,33 @@ pub fn ignore_arg_cast(func_name: &str, index: usize, args_len: usize) -> bool {
     match func_name {
         // NOTE: these intrinsics have missing parameters before the last one, so ignore the
         // last argument type check.
-        "__builtin_ia32_maxps512_mask" | "__builtin_ia32_maxpd512_mask"
-            | "__builtin_ia32_minps512_mask" | "__builtin_ia32_minpd512_mask" | "__builtin_ia32_sqrtps512_mask"
-            | "__builtin_ia32_sqrtpd512_mask" | "__builtin_ia32_addps512_mask" | "__builtin_ia32_addpd512_mask"
-            | "__builtin_ia32_subps512_mask" | "__builtin_ia32_subpd512_mask"
-            | "__builtin_ia32_mulps512_mask" | "__builtin_ia32_mulpd512_mask"
-            | "__builtin_ia32_divps512_mask" | "__builtin_ia32_divpd512_mask"
-            | "__builtin_ia32_vfmaddsubps512_mask" | "__builtin_ia32_vfmaddsubpd512_mask"
-            | "__builtin_ia32_cvtdq2ps512_mask" | "__builtin_ia32_cvtudq2ps512_mask" => {
-                if index == args_len - 1 {
-                    return true;
-                }
-            },
+        "__builtin_ia32_maxps512_mask"
+        | "__builtin_ia32_maxpd512_mask"
+        | "__builtin_ia32_minps512_mask"
+        | "__builtin_ia32_minpd512_mask"
+        | "__builtin_ia32_sqrtps512_mask"
+        | "__builtin_ia32_sqrtpd512_mask"
+        | "__builtin_ia32_addps512_mask"
+        | "__builtin_ia32_addpd512_mask"
+        | "__builtin_ia32_subps512_mask"
+        | "__builtin_ia32_subpd512_mask"
+        | "__builtin_ia32_mulps512_mask"
+        | "__builtin_ia32_mulpd512_mask"
+        | "__builtin_ia32_divps512_mask"
+        | "__builtin_ia32_divpd512_mask"
+        | "__builtin_ia32_vfmaddsubps512_mask"
+        | "__builtin_ia32_vfmaddsubpd512_mask"
+        | "__builtin_ia32_cvtdq2ps512_mask"
+        | "__builtin_ia32_cvtudq2ps512_mask" => {
+            if index == args_len - 1 {
+                return true;
+            }
+        }
         "__builtin_ia32_rndscaless_mask_round" | "__builtin_ia32_rndscalesd_mask_round" => {
             if index == 2 || index == 3 {
                 return true;
             }
-        },
+        }
         "__builtin_ia32_vfmaddps512_mask" | "__builtin_ia32_vfmaddpd512_mask" => {
             // Since there are two LLVM intrinsics that map to each of these GCC builtins and only
             // one of them has a missing parameter before the last one, we check the number of
@@ -415,49 +592,50 @@ pub fn ignore_arg_cast(func_name: &str, index: usize, args_len: usize) -> bool {
             if args_len == 4 && index == args_len - 1 {
                 return true;
             }
-        },
+        }
         // NOTE: the LLVM intrinsic receives 3 floats, but the GCC builtin requires 3 vectors.
         "__builtin_ia32_vfmaddss3_round" | "__builtin_ia32_vfmaddsd3_round" => return true,
-        "__builtin_ia32_vplzcntd_512_mask" | "__builtin_ia32_vplzcntd_256_mask" | "__builtin_ia32_vplzcntd_128_mask"
-            | "__builtin_ia32_vplzcntq_512_mask" | "__builtin_ia32_vplzcntq_256_mask" | "__builtin_ia32_vplzcntq_128_mask" => {
+        "__builtin_ia32_vplzcntd_512_mask"
+        | "__builtin_ia32_vplzcntd_256_mask"
+        | "__builtin_ia32_vplzcntd_128_mask"
+        | "__builtin_ia32_vplzcntq_512_mask"
+        | "__builtin_ia32_vplzcntq_256_mask"
+        | "__builtin_ia32_vplzcntq_128_mask" => {
             if index == args_len - 1 {
                 return true;
             }
-        },
+        }
         _ => (),
     }
 
     false
 }
 
-#[cfg(not(feature="master"))]
+#[cfg(not(feature = "master"))]
 pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function<'gcc> {
-    let gcc_name =
-        match name {
-            "llvm.x86.sse2.pause" => {
-                // NOTE: pause is only a hint, so we use a dummy built-in because target built-ins
-                // are not supported in libgccjit 12.
-                "__builtin_inff"
-            },
-            "llvm.x86.xgetbv" => {
-                "__builtin_trap"
-            },
-            _ => unimplemented!("unsupported LLVM intrinsic {}", name),
-        };
+    let gcc_name = match name {
+        "llvm.x86.sse2.pause" => {
+            // NOTE: pause is only a hint, so we use a dummy built-in because target built-ins
+            // are not supported in libgccjit 12.
+            "__builtin_inff"
+        }
+        "llvm.x86.xgetbv" => "__builtin_trap",
+        _ => unimplemented!("unsupported LLVM intrinsic {}", name),
+    };
     let func = cx.context.get_builtin_function(gcc_name);
     cx.functions.borrow_mut().insert(gcc_name.to_string(), func);
     return func;
 }
 
-#[cfg(feature="master")]
+#[cfg(feature = "master")]
 pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function<'gcc> {
     match name {
         "llvm.prefetch" => {
             let gcc_name = "__builtin_prefetch";
             let func = cx.context.get_builtin_function(gcc_name);
             cx.functions.borrow_mut().insert(gcc_name.to_string(), func);
-            return func
-        },
+            return func;
+        }
         _ => (),
     }
 
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index d43f5d74757..a6c8b72e851 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -1,43 +1,48 @@
 pub mod llvm;
 mod simd;
 
-#[cfg(feature="master")]
+#[cfg(feature = "master")]
 use std::iter;
 
-#[cfg(feature="master")]
+#[cfg(feature = "master")]
 use gccjit::FunctionType;
 use gccjit::{ComparisonOp, Function, RValue, ToRValue, Type, UnaryOp};
-use rustc_codegen_ssa::MemFlags;
 use rustc_codegen_ssa::base::wants_msvc_seh;
 use rustc_codegen_ssa::common::IntPredicate;
+use rustc_codegen_ssa::errors::InvalidMonomorphization;
 use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
 use rustc_codegen_ssa::mir::place::PlaceRef;
-use rustc_codegen_ssa::traits::{ArgAbiMethods, BuilderMethods, ConstMethods, IntrinsicCallMethods};
-#[cfg(feature="master")]
+use rustc_codegen_ssa::traits::{
+    ArgAbiMethods, BuilderMethods, ConstMethods, IntrinsicCallMethods,
+};
+#[cfg(feature = "master")]
 use rustc_codegen_ssa::traits::{BaseTypeMethods, MiscMethods};
-use rustc_codegen_ssa::errors::InvalidMonomorphization;
+use rustc_codegen_ssa::MemFlags;
 use rustc_middle::bug;
-use rustc_middle::ty::{self, Instance, Ty};
 use rustc_middle::ty::layout::LayoutOf;
-#[cfg(feature="master")]
+#[cfg(feature = "master")]
 use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt};
-use rustc_span::{Span, Symbol, sym};
-use rustc_target::abi::HasDataLayout;
+use rustc_middle::ty::{self, Instance, Ty};
+use rustc_span::{sym, Span, Symbol};
 use rustc_target::abi::call::{ArgAbi, FnAbi, PassMode};
-use rustc_target::spec::PanicStrategy;
-#[cfg(feature="master")]
+use rustc_target::abi::HasDataLayout;
+#[cfg(feature = "master")]
 use rustc_target::spec::abi::Abi;
+use rustc_target::spec::PanicStrategy;
 
-use crate::abi::GccType;
-#[cfg(feature="master")]
+#[cfg(feature = "master")]
 use crate::abi::FnAbiGccExt;
+use crate::abi::GccType;
 use crate::builder::Builder;
 use crate::common::{SignType, TypeReflection};
 use crate::context::CodegenCx;
-use crate::type_of::LayoutGccExt;
 use crate::intrinsic::simd::generic_simd_intrinsic;
+use crate::type_of::LayoutGccExt;
 
-fn get_simple_intrinsic<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, name: Symbol) -> Option<Function<'gcc>> {
+fn get_simple_intrinsic<'gcc, 'tcx>(
+    cx: &CodegenCx<'gcc, 'tcx>,
+    name: Symbol,
+) -> Option<Function<'gcc>> {
     let gcc_name = match name {
         sym::sqrtf32 => "sqrtf",
         sym::sqrtf64 => "sqrt",
@@ -90,7 +95,14 @@ fn get_simple_intrinsic<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, name: Symbol) ->
 }
 
 impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
-    fn codegen_intrinsic_call(&mut self, instance: Instance<'tcx>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, args: &[OperandRef<'tcx, RValue<'gcc>>], llresult: RValue<'gcc>, span: Span) -> Result<(), Instance<'tcx>> {
+    fn codegen_intrinsic_call(
+        &mut self,
+        instance: Instance<'tcx>,
+        fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
+        args: &[OperandRef<'tcx, RValue<'gcc>>],
+        llresult: RValue<'gcc>,
+        span: Span,
+    ) -> Result<(), Instance<'tcx>> {
         let tcx = self.tcx;
         let callee_ty = instance.ty(tcx, ty::ParamEnv::reveal_all());
 
@@ -110,268 +122,274 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
         let result = PlaceRef::new_sized(llresult, fn_abi.ret.layout);
 
         let simple = get_simple_intrinsic(self, name);
-        let llval =
-            match name {
-                _ if simple.is_some() => {
-                    // FIXME(antoyo): remove this cast when the API supports function.
-                    let func = unsafe { std::mem::transmute(simple.expect("simple")) };
-                    self.call(self.type_void(), None, None, func, &args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(), None)
-                },
-                sym::likely => {
-                    self.expect(args[0].immediate(), true)
-                }
-                sym::unlikely => {
-                    self.expect(args[0].immediate(), false)
-                }
-                sym::is_val_statically_known => {
-                    let a = args[0].immediate();
-                    let builtin = self.context.get_builtin_function("__builtin_constant_p");
-                    let res = self.context.new_call(None, builtin, &[a]);
-                    self.icmp(IntPredicate::IntEQ, res, self.const_i32(0))
-                }
-                sym::catch_unwind => {
-                    try_intrinsic(
-                        self,
-                        args[0].immediate(),
-                        args[1].immediate(),
-                        args[2].immediate(),
-                        llresult,
-                    );
-                    return Ok(());
-                }
-                sym::breakpoint => {
-                    unimplemented!();
-                }
-                sym::va_copy => {
-                    unimplemented!();
-                }
-                sym::va_arg => {
-                    unimplemented!();
-                }
+        let llval = match name {
+            _ if simple.is_some() => {
+                // FIXME(antoyo): remove this cast when the API supports function.
+                let func = unsafe { std::mem::transmute(simple.expect("simple")) };
+                self.call(
+                    self.type_void(),
+                    None,
+                    None,
+                    func,
+                    &args.iter().map(|arg| arg.immediate()).collect::<Vec<_>>(),
+                    None,
+                )
+            }
+            sym::likely => self.expect(args[0].immediate(), true),
+            sym::unlikely => self.expect(args[0].immediate(), false),
+            sym::is_val_statically_known => {
+                let a = args[0].immediate();
+                let builtin = self.context.get_builtin_function("__builtin_constant_p");
+                let res = self.context.new_call(None, builtin, &[a]);
+                self.icmp(IntPredicate::IntEQ, res, self.const_i32(0))
+            }
+            sym::catch_unwind => {
+                try_intrinsic(
+                    self,
+                    args[0].immediate(),
+                    args[1].immediate(),
+                    args[2].immediate(),
+                    llresult,
+                );
+                return Ok(());
+            }
+            sym::breakpoint => {
+                unimplemented!();
+            }
+            sym::va_copy => {
+                unimplemented!();
+            }
+            sym::va_arg => {
+                unimplemented!();
+            }
 
-                sym::volatile_load | sym::unaligned_volatile_load => {
-                    let tp_ty = fn_args.type_at(0);
-                    let ptr = args[0].immediate();
-                    let load =
-                        if let PassMode::Cast { cast: ty, pad_i32: _ } = &fn_abi.ret.mode {
-                            let gcc_ty = ty.gcc_type(self);
-                            self.volatile_load(gcc_ty, ptr)
+            sym::volatile_load | sym::unaligned_volatile_load => {
+                let tp_ty = fn_args.type_at(0);
+                let ptr = args[0].immediate();
+                let load = if let PassMode::Cast { cast: ty, pad_i32: _ } = &fn_abi.ret.mode {
+                    let gcc_ty = ty.gcc_type(self);
+                    self.volatile_load(gcc_ty, ptr)
+                } else {
+                    self.volatile_load(self.layout_of(tp_ty).gcc_type(self), ptr)
+                };
+                // TODO(antoyo): set alignment.
+                self.to_immediate(load, self.layout_of(tp_ty))
+            }
+            sym::volatile_store => {
+                let dst = args[0].deref(self.cx());
+                args[1].val.volatile_store(self, dst);
+                return Ok(());
+            }
+            sym::unaligned_volatile_store => {
+                let dst = args[0].deref(self.cx());
+                args[1].val.unaligned_volatile_store(self, dst);
+                return Ok(());
+            }
+            sym::prefetch_read_data
+            | sym::prefetch_write_data
+            | sym::prefetch_read_instruction
+            | sym::prefetch_write_instruction => {
+                unimplemented!();
+            }
+            sym::ctlz
+            | sym::ctlz_nonzero
+            | sym::cttz
+            | sym::cttz_nonzero
+            | sym::ctpop
+            | sym::bswap
+            | sym::bitreverse
+            | sym::rotate_left
+            | sym::rotate_right
+            | sym::saturating_add
+            | sym::saturating_sub => {
+                let ty = arg_tys[0];
+                match int_type_width_signed(ty, self) {
+                    Some((width, signed)) => match name {
+                        sym::ctlz | sym::cttz => {
+                            let func = self.current_func.borrow().expect("func");
+                            let then_block = func.new_block("then");
+                            let else_block = func.new_block("else");
+                            let after_block = func.new_block("after");
+
+                            let arg = args[0].immediate();
+                            let result = func.new_local(None, arg.get_type(), "zeros");
+                            let zero = self.cx.gcc_zero(arg.get_type());
+                            let cond = self.gcc_icmp(IntPredicate::IntEQ, arg, zero);
+                            self.llbb().end_with_conditional(None, cond, then_block, else_block);
+
+                            let zero_result = self.cx.gcc_uint(arg.get_type(), width);
+                            then_block.add_assignment(None, result, zero_result);
+                            then_block.end_with_jump(None, after_block);
+
+                            // NOTE: since jumps were added in a place
+                            // count_leading_zeroes() does not expect, the current block
+                            // in the state need to be updated.
+                            self.switch_to_block(else_block);
+
+                            let zeros = match name {
+                                sym::ctlz => self.count_leading_zeroes(width, arg),
+                                sym::cttz => self.count_trailing_zeroes(width, arg),
+                                _ => unreachable!(),
+                            };
+                            self.llbb().add_assignment(None, result, zeros);
+                            self.llbb().end_with_jump(None, after_block);
+
+                            // NOTE: since jumps were added in a place rustc does not
+                            // expect, the current block in the state need to be updated.
+                            self.switch_to_block(after_block);
+
+                            result.to_rvalue()
                         }
-                        else {
-                            self.volatile_load(self.layout_of(tp_ty).gcc_type(self), ptr)
-                        };
-                    // TODO(antoyo): set alignment.
-                    self.to_immediate(load, self.layout_of(tp_ty))
-                }
-                sym::volatile_store => {
-                    let dst = args[0].deref(self.cx());
-                    args[1].val.volatile_store(self, dst);
-                    return Ok(());
-                }
-                sym::unaligned_volatile_store => {
-                    let dst = args[0].deref(self.cx());
-                    args[1].val.unaligned_volatile_store(self, dst);
-                    return Ok(());
-                }
-                sym::prefetch_read_data
-                    | sym::prefetch_write_data
-                    | sym::prefetch_read_instruction
-                    | sym::prefetch_write_instruction => {
-                        unimplemented!();
-                    }
-                sym::ctlz
-                    | sym::ctlz_nonzero
-                    | sym::cttz
-                    | sym::cttz_nonzero
-                    | sym::ctpop
-                    | sym::bswap
-                    | sym::bitreverse
-                    | sym::rotate_left
-                    | sym::rotate_right
-                    | sym::saturating_add
-                    | sym::saturating_sub => {
-                        let ty = arg_tys[0];
-                        match int_type_width_signed(ty, self) {
-                            Some((width, signed)) => match name {
-                                sym::ctlz | sym::cttz => {
-                                    let func = self.current_func.borrow().expect("func");
-                                    let then_block = func.new_block("then");
-                                    let else_block = func.new_block("else");
-                                    let after_block = func.new_block("after");
-
-                                    let arg = args[0].immediate();
-                                    let result = func.new_local(None, arg.get_type(), "zeros");
-                                    let zero = self.cx.gcc_zero(arg.get_type());
-                                    let cond = self.gcc_icmp(IntPredicate::IntEQ, arg, zero);
-                                    self.llbb().end_with_conditional(None, cond, then_block, else_block);
-
-                                    let zero_result = self.cx.gcc_uint(arg.get_type(), width);
-                                    then_block.add_assignment(None, result, zero_result);
-                                    then_block.end_with_jump(None, after_block);
-
-                                    // NOTE: since jumps were added in a place
-                                    // count_leading_zeroes() does not expect, the current block
-                                    // in the state need to be updated.
-                                    self.switch_to_block(else_block);
-
-                                    let zeros =
-                                        match name {
-                                            sym::ctlz => self.count_leading_zeroes(width, arg),
-                                            sym::cttz => self.count_trailing_zeroes(width, arg),
-                                            _ => unreachable!(),
-                                        };
-                                    self.llbb().add_assignment(None, result, zeros);
-                                    self.llbb().end_with_jump(None, after_block);
-
-                                    // NOTE: since jumps were added in a place rustc does not
-                                    // expect, the current block in the state need to be updated.
-                                    self.switch_to_block(after_block);
-
-                                    result.to_rvalue()
-                                }
-                                sym::ctlz_nonzero => {
-                                    self.count_leading_zeroes(width, args[0].immediate())
-                                },
-                                sym::cttz_nonzero => {
-                                    self.count_trailing_zeroes(width, args[0].immediate())
-                                }
-                                sym::ctpop => self.pop_count(args[0].immediate()),
-                                sym::bswap => {
-                                    if width == 8 {
-                                        args[0].immediate() // byte swap a u8/i8 is just a no-op
-                                    }
-                                    else {
-                                        self.gcc_bswap(args[0].immediate(), width)
-                                    }
-                                },
-                                sym::bitreverse => self.bit_reverse(width, args[0].immediate()),
-                                sym::rotate_left | sym::rotate_right => {
-                                    // TODO(antoyo): implement using algorithm from:
-                                    // https://blog.regehr.org/archives/1063
-                                    // for other platforms.
-                                    let is_left = name == sym::rotate_left;
-                                    let val = args[0].immediate();
-                                    let raw_shift = args[1].immediate();
-                                    if is_left {
-                                        self.rotate_left(val, raw_shift, width)
-                                    }
-                                    else {
-                                        self.rotate_right(val, raw_shift, width)
-                                    }
-                                },
-                                sym::saturating_add => {
-                                    self.saturating_add(args[0].immediate(), args[1].immediate(), signed, width)
-                                },
-                                sym::saturating_sub => {
-                                    self.saturating_sub(args[0].immediate(), args[1].immediate(), signed, width)
-                                },
-                                _ => bug!(),
-                            },
-                            None => {
-                                tcx.dcx().emit_err(InvalidMonomorphization::BasicIntegerType { span, name, ty });
-                                return Ok(());
+                        sym::ctlz_nonzero => self.count_leading_zeroes(width, args[0].immediate()),
+                        sym::cttz_nonzero => self.count_trailing_zeroes(width, args[0].immediate()),
+                        sym::ctpop => self.pop_count(args[0].immediate()),
+                        sym::bswap => {
+                            if width == 8 {
+                                args[0].immediate() // byte swap a u8/i8 is just a no-op
+                            } else {
+                                self.gcc_bswap(args[0].immediate(), width)
                             }
                         }
-                    }
-
-                sym::raw_eq => {
-                    use rustc_target::abi::Abi::*;
-                    let tp_ty = fn_args.type_at(0);
-                    let layout = self.layout_of(tp_ty).layout;
-                    let _use_integer_compare = match layout.abi() {
-                        Scalar(_) | ScalarPair(_, _) => true,
-                        Uninhabited | Vector { .. } => false,
-                        Aggregate { .. } => {
-                            // For rusty ABIs, small aggregates are actually passed
-                            // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),
-                            // so we re-use that same threshold here.
-                            layout.size() <= self.data_layout().pointer_size * 2
+                        sym::bitreverse => self.bit_reverse(width, args[0].immediate()),
+                        sym::rotate_left | sym::rotate_right => {
+                            // TODO(antoyo): implement using algorithm from:
+                            // https://blog.regehr.org/archives/1063
+                            // for other platforms.
+                            let is_left = name == sym::rotate_left;
+                            let val = args[0].immediate();
+                            let raw_shift = args[1].immediate();
+                            if is_left {
+                                self.rotate_left(val, raw_shift, width)
+                            } else {
+                                self.rotate_right(val, raw_shift, width)
+                            }
                         }
-                    };
-
-                    let a = args[0].immediate();
-                    let b = args[1].immediate();
-                    if layout.size().bytes() == 0 {
-                        self.const_bool(true)
-                    }
-                    /*else if use_integer_compare {
-                        let integer_ty = self.type_ix(layout.size.bits()); // FIXME(antoyo): LLVM creates an integer of 96 bits for [i32; 3], but gcc doesn't support this, so it creates an integer of 128 bits.
-                        let ptr_ty = self.type_ptr_to(integer_ty);
-                        let a_ptr = self.bitcast(a, ptr_ty);
-                        let a_val = self.load(integer_ty, a_ptr, layout.align.abi);
-                        let b_ptr = self.bitcast(b, ptr_ty);
-                        let b_val = self.load(integer_ty, b_ptr, layout.align.abi);
-                        self.icmp(IntPredicate::IntEQ, a_val, b_val)
-                    }*/
-                    else {
-                        let void_ptr_type = self.context.new_type::<*const ()>();
-                        let a_ptr = self.bitcast(a, void_ptr_type);
-                        let b_ptr = self.bitcast(b, void_ptr_type);
-                        let n = self.context.new_cast(None, self.const_usize(layout.size().bytes()), self.sizet_type);
-                        let builtin = self.context.get_builtin_function("memcmp");
-                        let cmp = self.context.new_call(None, builtin, &[a_ptr, b_ptr, n]);
-                        self.icmp(IntPredicate::IntEQ, cmp, self.const_i32(0))
+                        sym::saturating_add => self.saturating_add(
+                            args[0].immediate(),
+                            args[1].immediate(),
+                            signed,
+                            width,
+                        ),
+                        sym::saturating_sub => self.saturating_sub(
+                            args[0].immediate(),
+                            args[1].immediate(),
+                            signed,
+                            width,
+                        ),
+                        _ => bug!(),
+                    },
+                    None => {
+                        tcx.dcx().emit_err(InvalidMonomorphization::BasicIntegerType {
+                            span,
+                            name,
+                            ty,
+                        });
+                        return Ok(());
                     }
                 }
+            }
 
-                sym::compare_bytes => {
-                    let a = args[0].immediate();
-                    let b = args[1].immediate();
-                    let n = args[2].immediate();
+            sym::raw_eq => {
+                use rustc_target::abi::Abi::*;
+                let tp_ty = fn_args.type_at(0);
+                let layout = self.layout_of(tp_ty).layout;
+                let _use_integer_compare = match layout.abi() {
+                    Scalar(_) | ScalarPair(_, _) => true,
+                    Uninhabited | Vector { .. } => false,
+                    Aggregate { .. } => {
+                        // For rusty ABIs, small aggregates are actually passed
+                        // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`),
+                        // so we re-use that same threshold here.
+                        layout.size() <= self.data_layout().pointer_size * 2
+                    }
+                };
 
+                let a = args[0].immediate();
+                let b = args[1].immediate();
+                if layout.size().bytes() == 0 {
+                    self.const_bool(true)
+                }
+                /*else if use_integer_compare {
+                    let integer_ty = self.type_ix(layout.size.bits()); // FIXME(antoyo): LLVM creates an integer of 96 bits for [i32; 3], but gcc doesn't support this, so it creates an integer of 128 bits.
+                    let ptr_ty = self.type_ptr_to(integer_ty);
+                    let a_ptr = self.bitcast(a, ptr_ty);
+                    let a_val = self.load(integer_ty, a_ptr, layout.align.abi);
+                    let b_ptr = self.bitcast(b, ptr_ty);
+                    let b_val = self.load(integer_ty, b_ptr, layout.align.abi);
+                    self.icmp(IntPredicate::IntEQ, a_val, b_val)
+                }*/
+                else {
                     let void_ptr_type = self.context.new_type::<*const ()>();
                     let a_ptr = self.bitcast(a, void_ptr_type);
                     let b_ptr = self.bitcast(b, void_ptr_type);
-
-                    // Here we assume that the `memcmp` provided by the target is a NOP for size 0.
+                    let n = self.context.new_cast(
+                        None,
+                        self.const_usize(layout.size().bytes()),
+                        self.sizet_type,
+                    );
                     let builtin = self.context.get_builtin_function("memcmp");
                     let cmp = self.context.new_call(None, builtin, &[a_ptr, b_ptr, n]);
-                    self.sext(cmp, self.type_ix(32))
+                    self.icmp(IntPredicate::IntEQ, cmp, self.const_i32(0))
                 }
+            }
 
-                sym::black_box => {
-                    args[0].val.store(self, result);
+            sym::compare_bytes => {
+                let a = args[0].immediate();
+                let b = args[1].immediate();
+                let n = args[2].immediate();
 
-                    let block = self.llbb();
-                    let extended_asm = block.add_extended_asm(None, "");
-                    extended_asm.add_input_operand(None, "r", result.llval);
-                    extended_asm.add_clobber("memory");
-                    extended_asm.set_volatile_flag(true);
+                let void_ptr_type = self.context.new_type::<*const ()>();
+                let a_ptr = self.bitcast(a, void_ptr_type);
+                let b_ptr = self.bitcast(b, void_ptr_type);
 
-                    // We have copied the value to `result` already.
-                    return Ok(());
-                }
+                // Here we assume that the `memcmp` provided by the target is a NOP for size 0.
+                let builtin = self.context.get_builtin_function("memcmp");
+                let cmp = self.context.new_call(None, builtin, &[a_ptr, b_ptr, n]);
+                self.sext(cmp, self.type_ix(32))
+            }
 
-                sym::ptr_mask => {
-                    let usize_type = self.context.new_type::<usize>();
-                    let void_ptr_type = self.context.new_type::<*const ()>();
+            sym::black_box => {
+                args[0].val.store(self, result);
 
-                    let ptr = args[0].immediate();
-                    let mask = args[1].immediate();
+                let block = self.llbb();
+                let extended_asm = block.add_extended_asm(None, "");
+                extended_asm.add_input_operand(None, "r", result.llval);
+                extended_asm.add_clobber("memory");
+                extended_asm.set_volatile_flag(true);
 
-                    let addr = self.bitcast(ptr, usize_type);
-                    let masked = self.and(addr, mask);
-                    self.bitcast(masked, void_ptr_type)
-                },
+                // We have copied the value to `result` already.
+                return Ok(());
+            }
 
-                _ if name_str.starts_with("simd_") => {
-                    match generic_simd_intrinsic(self, name, callee_ty, args, ret_ty, llret_ty, span) {
-                        Ok(llval) => llval,
-                        Err(()) => return Ok(()),
-                    }
+            sym::ptr_mask => {
+                let usize_type = self.context.new_type::<usize>();
+                let void_ptr_type = self.context.new_type::<*const ()>();
+
+                let ptr = args[0].immediate();
+                let mask = args[1].immediate();
+
+                let addr = self.bitcast(ptr, usize_type);
+                let masked = self.and(addr, mask);
+                self.bitcast(masked, void_ptr_type)
+            }
+
+            _ if name_str.starts_with("simd_") => {
+                match generic_simd_intrinsic(self, name, callee_ty, args, ret_ty, llret_ty, span) {
+                    Ok(llval) => llval,
+                    Err(()) => return Ok(()),
                 }
+            }
 
-                // Fall back to default body
-                _ => return Err(Instance::new(instance.def_id(), instance.args)),
-            };
+            // Fall back to default body
+            _ => return Err(Instance::new(instance.def_id(), instance.args)),
+        };
 
         if !fn_abi.ret.is_ignore() {
             if let PassMode::Cast { cast: ty, .. } = &fn_abi.ret.mode {
                 let ptr_llty = self.type_ptr_to(ty.gcc_type(self));
                 let ptr = self.pointercast(result.llval, ptr_llty);
                 self.store(llval, ptr, result.align);
-            }
-            else {
+            } else {
                 OperandRef::from_immediate_or_packed_pair(self, llval, result.layout)
                     .val
                     .store(self, result);
@@ -423,11 +441,21 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
 }
 
 impl<'a, 'gcc, 'tcx> ArgAbiMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
-    fn store_fn_arg(&mut self, arg_abi: &ArgAbi<'tcx, Ty<'tcx>>, idx: &mut usize, dst: PlaceRef<'tcx, Self::Value>) {
+    fn store_fn_arg(
+        &mut self,
+        arg_abi: &ArgAbi<'tcx, Ty<'tcx>>,
+        idx: &mut usize,
+        dst: PlaceRef<'tcx, Self::Value>,
+    ) {
         arg_abi.store_fn_arg(self, idx, dst)
     }
 
-    fn store_arg(&mut self, arg_abi: &ArgAbi<'tcx, Ty<'tcx>>, val: RValue<'gcc>, dst: PlaceRef<'tcx, RValue<'gcc>>) {
+    fn store_arg(
+        &mut self,
+        arg_abi: &ArgAbi<'tcx, Ty<'tcx>>,
+        val: RValue<'gcc>,
+        dst: PlaceRef<'tcx, RValue<'gcc>>,
+    ) {
         arg_abi.store(self, val, dst)
     }
 
@@ -438,8 +466,18 @@ impl<'a, 'gcc, 'tcx> ArgAbiMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
 
 pub trait ArgAbiExt<'gcc, 'tcx> {
     fn memory_ty(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>;
-    fn store(&self, bx: &mut Builder<'_, 'gcc, 'tcx>, val: RValue<'gcc>, dst: PlaceRef<'tcx, RValue<'gcc>>);
-    fn store_fn_arg(&self, bx: &mut Builder<'_, 'gcc, 'tcx>, idx: &mut usize, dst: PlaceRef<'tcx, RValue<'gcc>>);
+    fn store(
+        &self,
+        bx: &mut Builder<'_, 'gcc, 'tcx>,
+        val: RValue<'gcc>,
+        dst: PlaceRef<'tcx, RValue<'gcc>>,
+    );
+    fn store_fn_arg(
+        &self,
+        bx: &mut Builder<'_, 'gcc, 'tcx>,
+        idx: &mut usize,
+        dst: PlaceRef<'tcx, RValue<'gcc>>,
+    );
 }
 
 impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
@@ -453,17 +491,20 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
     /// place for the original Rust type of this argument/return.
     /// Can be used for both storing formal arguments into Rust variables
     /// or results of call/invoke instructions into their destinations.
-    fn store(&self, bx: &mut Builder<'_, 'gcc, 'tcx>, val: RValue<'gcc>, dst: PlaceRef<'tcx, RValue<'gcc>>) {
+    fn store(
+        &self,
+        bx: &mut Builder<'_, 'gcc, 'tcx>,
+        val: RValue<'gcc>,
+        dst: PlaceRef<'tcx, RValue<'gcc>>,
+    ) {
         if self.is_ignore() {
             return;
         }
         if self.is_sized_indirect() {
             OperandValue::Ref(val, None, self.layout.align.abi).store(bx, dst)
-        }
-        else if self.is_unsized_indirect() {
+        } else if self.is_unsized_indirect() {
             bug!("unsized `ArgAbi` must be handled through `store_fn_arg`");
-        }
-        else if let PassMode::Cast { ref cast, .. } = self.mode {
+        } else if let PassMode::Cast { ref cast, .. } = self.mode {
             // FIXME(eddyb): Figure out when the simpler Store is safe, clang
             // uses it for i16 -> {i8, i8}, but not for i24 -> {i8, i8, i8}.
             let can_store_through_cast_ptr = false;
@@ -471,8 +512,7 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
                 let cast_ptr_llty = bx.type_ptr_to(cast.gcc_type(bx));
                 let cast_dst = bx.pointercast(dst.llval, cast_ptr_llty);
                 bx.store(val, cast_dst, self.layout.align.abi);
-            }
-            else {
+            } else {
                 // The actual return type is a struct, but the ABI
                 // adaptation code has cast it into some scalar type.  The
                 // code that follows is the only reliable way I have
@@ -508,35 +548,44 @@ impl<'gcc, 'tcx> ArgAbiExt<'gcc, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
 
                 bx.lifetime_end(llscratch, scratch_size);
             }
-        }
-        else {
+        } else {
             OperandValue::Immediate(val).store(bx, dst);
         }
     }
 
-    fn store_fn_arg<'a>(&self, bx: &mut Builder<'a, 'gcc, 'tcx>, idx: &mut usize, dst: PlaceRef<'tcx, RValue<'gcc>>) {
+    fn store_fn_arg<'a>(
+        &self,
+        bx: &mut Builder<'a, 'gcc, 'tcx>,
+        idx: &mut usize,
+        dst: PlaceRef<'tcx, RValue<'gcc>>,
+    ) {
         let mut next = || {
             let val = bx.current_func().get_param(*idx as i32);
             *idx += 1;
             val.to_rvalue()
         };
         match self.mode {
-            PassMode::Ignore => {},
+            PassMode::Ignore => {}
             PassMode::Pair(..) => {
                 OperandValue::Pair(next(), next()).store(bx, dst);
-            },
+            }
             PassMode::Indirect { meta_attrs: Some(_), .. } => {
                 OperandValue::Ref(next(), Some(next()), self.layout.align.abi).store(bx, dst);
-            },
-            PassMode::Direct(_) | PassMode::Indirect { meta_attrs: None, .. } | PassMode::Cast { .. } => {
+            }
+            PassMode::Direct(_)
+            | PassMode::Indirect { meta_attrs: None, .. }
+            | PassMode::Cast { .. } => {
                 let next_arg = next();
                 self.store(bx, next_arg, dst);
-            },
+            }
         }
     }
 }
 
-fn int_type_width_signed<'gcc, 'tcx>(ty: Ty<'tcx>, cx: &CodegenCx<'gcc, 'tcx>) -> Option<(u64, bool)> {
+fn int_type_width_signed<'gcc, 'tcx>(
+    ty: Ty<'tcx>,
+    cx: &CodegenCx<'gcc, 'tcx>,
+) -> Option<(u64, bool)> {
     match ty.kind() {
         ty::Int(t) => Some((
             match t {
@@ -570,82 +619,76 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         let typ = result_type.to_unsigned(self.cx);
 
         let value =
-            if result_type.is_signed(self.cx) {
-                self.gcc_int_cast(value, typ)
-            }
-            else {
-                value
-            };
+            if result_type.is_signed(self.cx) { self.gcc_int_cast(value, typ) } else { value };
 
         let context = &self.cx.context;
-        let result =
-            match width {
-                8 | 16 | 32 | 64 => {
-                    let mask = ((1u128 << width) - 1) as u64;
-                    let (m0, m1, m2) = if width > 16 {
-                        (
-                            context.new_rvalue_from_long(typ, (0x5555555555555555u64 & mask) as i64),
-                            context.new_rvalue_from_long(typ, (0x3333333333333333u64 & mask) as i64),
-                            context.new_rvalue_from_long(typ, (0x0f0f0f0f0f0f0f0fu64 & mask) as i64),
-                        )
-                    } else {
-                        (
-                            context.new_rvalue_from_int(typ, (0x5555u64 & mask) as i32),
-                            context.new_rvalue_from_int(typ, (0x3333u64 & mask) as i32),
-                            context.new_rvalue_from_int(typ, (0x0f0fu64 & mask) as i32),
-                        )
-                    };
-                    let one = context.new_rvalue_from_int(typ, 1);
-                    let two = context.new_rvalue_from_int(typ, 2);
-                    let four = context.new_rvalue_from_int(typ, 4);
-
-                    // First step.
-                    let left = self.lshr(value, one);
-                    let left = self.and(left, m0);
-                    let right = self.and(value, m0);
-                    let right = self.shl(right, one);
-                    let step1 = self.or(left, right);
-
-                    // Second step.
-                    let left = self.lshr(step1, two);
-                    let left = self.and(left, m1);
-                    let right = self.and(step1, m1);
-                    let right = self.shl(right, two);
-                    let step2 = self.or(left, right);
-
-                    // Third step.
-                    let left = self.lshr(step2, four);
-                    let left = self.and(left, m2);
-                    let right = self.and(step2, m2);
-                    let right = self.shl(right, four);
-                    let step3 = self.or(left, right);
-
-                    // Fourth step.
-                    if width == 8 {
-                        step3
-                    } else {
-                        self.gcc_bswap(step3, width)
-                    }
-                },
-                128 => {
-                    // TODO(antoyo): find a more efficient implementation?
-                    let sixty_four = self.gcc_int(typ, 64);
-                    let right_shift = self.gcc_lshr(value, sixty_four);
-                    let high = self.gcc_int_cast(right_shift, self.u64_type);
-                    let low = self.gcc_int_cast(value, self.u64_type);
-
-                    let reversed_high = self.bit_reverse(64, high);
-                    let reversed_low = self.bit_reverse(64, low);
-
-                    let new_low = self.gcc_int_cast(reversed_high, typ);
-                    let new_high = self.shl(self.gcc_int_cast(reversed_low, typ), sixty_four);
-
-                    self.gcc_or(new_low, new_high)
-                },
-                _ => {
-                    panic!("cannot bit reverse with width = {}", width);
-                },
-            };
+        let result = match width {
+            8 | 16 | 32 | 64 => {
+                let mask = ((1u128 << width) - 1) as u64;
+                let (m0, m1, m2) = if width > 16 {
+                    (
+                        context.new_rvalue_from_long(typ, (0x5555555555555555u64 & mask) as i64),
+                        context.new_rvalue_from_long(typ, (0x3333333333333333u64 & mask) as i64),
+                        context.new_rvalue_from_long(typ, (0x0f0f0f0f0f0f0f0fu64 & mask) as i64),
+                    )
+                } else {
+                    (
+                        context.new_rvalue_from_int(typ, (0x5555u64 & mask) as i32),
+                        context.new_rvalue_from_int(typ, (0x3333u64 & mask) as i32),
+                        context.new_rvalue_from_int(typ, (0x0f0fu64 & mask) as i32),
+                    )
+                };
+                let one = context.new_rvalue_from_int(typ, 1);
+                let two = context.new_rvalue_from_int(typ, 2);
+                let four = context.new_rvalue_from_int(typ, 4);
+
+                // First step.
+                let left = self.lshr(value, one);
+                let left = self.and(left, m0);
+                let right = self.and(value, m0);
+                let right = self.shl(right, one);
+                let step1 = self.or(left, right);
+
+                // Second step.
+                let left = self.lshr(step1, two);
+                let left = self.and(left, m1);
+                let right = self.and(step1, m1);
+                let right = self.shl(right, two);
+                let step2 = self.or(left, right);
+
+                // Third step.
+                let left = self.lshr(step2, four);
+                let left = self.and(left, m2);
+                let right = self.and(step2, m2);
+                let right = self.shl(right, four);
+                let step3 = self.or(left, right);
+
+                // Fourth step.
+                if width == 8 {
+                    step3
+                } else {
+                    self.gcc_bswap(step3, width)
+                }
+            }
+            128 => {
+                // TODO(antoyo): find a more efficient implementation?
+                let sixty_four = self.gcc_int(typ, 64);
+                let right_shift = self.gcc_lshr(value, sixty_four);
+                let high = self.gcc_int_cast(right_shift, self.u64_type);
+                let low = self.gcc_int_cast(value, self.u64_type);
+
+                let reversed_high = self.bit_reverse(64, high);
+                let reversed_low = self.bit_reverse(64, low);
+
+                let new_low = self.gcc_int_cast(reversed_high, typ);
+                let new_high = self.shl(self.gcc_int_cast(reversed_low, typ), sixty_four);
+
+                self.gcc_or(new_low, new_high, self.location)
+            }
+            _ => {
+                panic!("cannot bit reverse with width = {}", width);
+            }
+        };
 
         self.gcc_int_cast(result, result_type)
     }
@@ -685,56 +728,54 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
                 let first_elem = self.context.new_array_access(None, result, zero);
                 let first_value = self.gcc_int_cast(self.context.new_call(None, clzll, &[high]), arg_type);
                 self.llbb()
-                    .add_assignment(None, first_elem, first_value);
+                    .add_assignment(self.location, first_elem, first_value);
 
-                let second_elem = self.context.new_array_access(None, result, one);
-                let cast = self.gcc_int_cast(self.context.new_call(None, clzll, &[low]), arg_type);
+                let second_elem = self.context.new_array_access(self.location, result, one);
+                let cast = self.gcc_int_cast(self.context.new_call(self.location, clzll, &[low]), arg_type);
                 let second_value = self.add(cast, sixty_four);
                 self.llbb()
-                    .add_assignment(None, second_elem, second_value);
+                    .add_assignment(self.location, second_elem, second_value);
 
-                let third_elem = self.context.new_array_access(None, result, two);
+                let third_elem = self.context.new_array_access(self.location, result, two);
                 let third_value = self.const_uint(arg_type, 128);
                 self.llbb()
-                    .add_assignment(None, third_elem, third_value);
+                    .add_assignment(self.location, third_elem, third_value);
 
-                let not_high = self.context.new_unary_op(None, UnaryOp::LogicalNegate, self.u64_type, high);
-                let not_low = self.context.new_unary_op(None, UnaryOp::LogicalNegate, self.u64_type, low);
+                let not_high = self.context.new_unary_op(self.location, UnaryOp::LogicalNegate, self.u64_type, high);
+                let not_low = self.context.new_unary_op(self.location, UnaryOp::LogicalNegate, self.u64_type, low);
                 let not_low_and_not_high = not_low & not_high;
                 let index = not_high + not_low_and_not_high;
                 // NOTE: the following cast is necessary to avoid a GIMPLE verification failure in
                 // gcc.
                 // TODO(antoyo): do the correct verification in libgccjit to avoid an error at the
                 // compilation stage.
-                let index = self.context.new_cast(None, index, self.i32_type);
+                let index = self.context.new_cast(self.location, index, self.i32_type);
 
-                let res = self.context.new_array_access(None, result, index);
+                let res = self.context.new_array_access(self.location, result, index);
 
                 return self.gcc_int_cast(res.to_rvalue(), arg_type);
             }
             else {
                 let count_leading_zeroes = self.context.get_builtin_function("__builtin_clzll");
-                let arg = self.context.new_cast(None, arg, self.ulonglong_type);
+                let arg = self.context.new_cast(self.location, arg, self.ulonglong_type);
                 let diff = self.ulonglong_type.get_size() as i64 - arg_type.get_size() as i64;
                 let diff = self.context.new_rvalue_from_long(self.int_type, diff * 8);
-                let res = self.context.new_call(None, count_leading_zeroes, &[arg]) - diff;
-                return self.context.new_cast(None, res, arg_type);
+                let res = self.context.new_call(self.location, count_leading_zeroes, &[arg]) - diff;
+                return self.context.new_cast(self.location, res, arg_type);
             };
         let count_leading_zeroes = self.context.get_builtin_function(count_leading_zeroes);
-        let res = self.context.new_call(None, count_leading_zeroes, &[arg]);
-        self.context.new_cast(None, res, arg_type)
+        let res = self.context.new_call(self.location, count_leading_zeroes, &[arg]);
+        self.context.new_cast(self.location, res, arg_type)
     }
 
     fn count_trailing_zeroes(&mut self, _width: u64, arg: RValue<'gcc>) -> RValue<'gcc> {
         let result_type = arg.get_type();
-        let arg =
-            if result_type.is_signed(self.cx) {
-                let new_type = result_type.to_unsigned(self.cx);
-                self.gcc_int_cast(arg, new_type)
-            }
-            else {
-                arg
-            };
+        let arg = if result_type.is_signed(self.cx) {
+            let new_type = result_type.to_unsigned(self.cx);
+            self.gcc_int_cast(arg, new_type)
+        } else {
+            arg
+        };
         let arg_type = arg.get_type();
         let (count_trailing_zeroes, expected_type) =
             // TODO(antoyo): write a new function Type::is_compatible_with(&Type) and use it here
@@ -766,58 +807,56 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
 
                 let ctzll = self.context.get_builtin_function("__builtin_ctzll");
 
-                let first_elem = self.context.new_array_access(None, result, zero);
-                let first_value = self.gcc_int_cast(self.context.new_call(None, ctzll, &[low]), arg_type);
+                let first_elem = self.context.new_array_access(self.location, result, zero);
+                let first_value = self.gcc_int_cast(self.context.new_call(self.location, ctzll, &[low]), arg_type);
                 self.llbb()
-                    .add_assignment(None, first_elem, first_value);
+                    .add_assignment(self.location, first_elem, first_value);
 
-                let second_elem = self.context.new_array_access(None, result, one);
-                let second_value = self.gcc_add(self.gcc_int_cast(self.context.new_call(None, ctzll, &[high]), arg_type), sixty_four);
+                let second_elem = self.context.new_array_access(self.location, result, one);
+                let second_value = self.gcc_add(self.gcc_int_cast(self.context.new_call(self.location, ctzll, &[high]), arg_type), sixty_four);
                 self.llbb()
-                    .add_assignment(None, second_elem, second_value);
+                    .add_assignment(self.location, second_elem, second_value);
 
-                let third_elem = self.context.new_array_access(None, result, two);
+                let third_elem = self.context.new_array_access(self.location, result, two);
                 let third_value = self.gcc_int(arg_type, 128);
                 self.llbb()
-                    .add_assignment(None, third_elem, third_value);
+                    .add_assignment(self.location, third_elem, third_value);
 
-                let not_low = self.context.new_unary_op(None, UnaryOp::LogicalNegate, self.u64_type, low);
-                let not_high = self.context.new_unary_op(None, UnaryOp::LogicalNegate, self.u64_type, high);
+                let not_low = self.context.new_unary_op(self.location, UnaryOp::LogicalNegate, self.u64_type, low);
+                let not_high = self.context.new_unary_op(self.location, UnaryOp::LogicalNegate, self.u64_type, high);
                 let not_low_and_not_high = not_low & not_high;
                 let index = not_low + not_low_and_not_high;
                 // NOTE: the following cast is necessary to avoid a GIMPLE verification failure in
                 // gcc.
                 // TODO(antoyo): do the correct verification in libgccjit to avoid an error at the
                 // compilation stage.
-                let index = self.context.new_cast(None, index, self.i32_type);
+                let index = self.context.new_cast(self.location, index, self.i32_type);
 
-                let res = self.context.new_array_access(None, result, index);
+                let res = self.context.new_array_access(self.location, result, index);
 
                 return self.gcc_int_cast(res.to_rvalue(), result_type);
             }
             else {
                 let count_trailing_zeroes = self.context.get_builtin_function("__builtin_ctzll");
                 let arg_size = arg_type.get_size();
-                let casted_arg = self.context.new_cast(None, arg, self.ulonglong_type);
+                let casted_arg = self.context.new_cast(self.location, arg, self.ulonglong_type);
                 let byte_diff = self.ulonglong_type.get_size() as i64 - arg_size as i64;
                 let diff = self.context.new_rvalue_from_long(self.int_type, byte_diff * 8);
                 let mask = self.context.new_rvalue_from_long(arg_type, -1); // To get the value with all bits set.
-                let masked = mask & self.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, arg);
-                let cond = self.context.new_comparison(None, ComparisonOp::Equals, masked, mask);
-                let diff = diff * self.context.new_cast(None, cond, self.int_type);
-                let res = self.context.new_call(None, count_trailing_zeroes, &[casted_arg]) - diff;
-                return self.context.new_cast(None, res, result_type);
+                let masked = mask & self.context.new_unary_op(self.location, UnaryOp::BitwiseNegate, arg_type, arg);
+                let cond = self.context.new_comparison(self.location, ComparisonOp::Equals, masked, mask);
+                let diff = diff * self.context.new_cast(self.location, cond, self.int_type);
+                let res = self.context.new_call(self.location, count_trailing_zeroes, &[casted_arg]) - diff;
+                return self.context.new_cast(self.location, res, result_type);
             };
         let count_trailing_zeroes = self.context.get_builtin_function(count_trailing_zeroes);
-        let arg =
-            if arg_type != expected_type {
-                self.context.new_cast(None, arg, expected_type)
-            }
-            else {
-                arg
-            };
-        let res = self.context.new_call(None, count_trailing_zeroes, &[arg]);
-        self.context.new_cast(None, res, result_type)
+        let arg = if arg_type != expected_type {
+            self.context.new_cast(self.location, arg, expected_type)
+        } else {
+            arg
+        };
+        let res = self.context.new_call(self.location, count_trailing_zeroes, &[arg]);
+        self.context.new_cast(self.location, res, result_type)
     }
 
     fn pop_count(&mut self, value: RValue<'gcc>) -> RValue<'gcc> {
@@ -825,13 +864,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         let result_type = value.get_type();
         let value_type = result_type.to_unsigned(self.cx);
 
-        let value =
-            if result_type.is_signed(self.cx) {
-                self.gcc_int_cast(value, value_type)
-            }
-            else {
-                value
-            };
+        let value = if result_type.is_signed(self.cx) {
+            self.gcc_int_cast(value, value_type)
+        } else {
+            value
+        };
 
         // only break apart 128-bit ints if they're not natively supported
         // TODO(antoyo): remove this if/when native 128-bit integers land in libgccjit
@@ -859,8 +896,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         let counter = self.current_func().new_local(None, counter_type, "popcount_counter");
         let val = self.current_func().new_local(None, value_type, "popcount_value");
         let zero = self.gcc_zero(counter_type);
-        self.llbb().add_assignment(None, counter, zero);
-        self.llbb().add_assignment(None, val, value);
+        self.llbb().add_assignment(self.location, counter, zero);
+        self.llbb().add_assignment(self.location, val, value);
         self.br(loop_head);
 
         // check if value isn't zero
@@ -874,12 +911,12 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
         let one = self.gcc_int(value_type, 1);
         let sub = self.gcc_sub(val.to_rvalue(), one);
         let op = self.gcc_and(val.to_rvalue(), sub);
-        loop_body.add_assignment(None, val, op);
+        loop_body.add_assignment(self.location, val, op);
 
         // counter += 1
         let one = self.gcc_int(counter_type, 1);
         let op = self.gcc_add(counter.to_rvalue(), one);
-        loop_body.add_assignment(None, counter, op);
+        loop_body.add_assignment(self.location, counter, op);
         self.br(loop_head);
 
         // end of loop
@@ -888,66 +925,70 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
     }
 
     // Algorithm from: https://blog.regehr.org/archives/1063
-    fn rotate_left(&mut self, value: RValue<'gcc>, shift: RValue<'gcc>, width: u64) -> RValue<'gcc> {
+    fn rotate_left(
+        &mut self,
+        value: RValue<'gcc>,
+        shift: RValue<'gcc>,
+        width: u64,
+    ) -> RValue<'gcc> {
         let max = self.const_uint(shift.get_type(), width);
         let shift = self.urem(shift, max);
         let lhs = self.shl(value, shift);
         let result_neg = self.neg(shift);
-        let result_and =
-            self.and(
-                result_neg,
-                self.const_uint(shift.get_type(), width - 1),
-            );
+        let result_and = self.and(result_neg, self.const_uint(shift.get_type(), width - 1));
         let rhs = self.lshr(value, result_and);
         self.or(lhs, rhs)
     }
 
     // Algorithm from: https://blog.regehr.org/archives/1063
-    fn rotate_right(&mut self, value: RValue<'gcc>, shift: RValue<'gcc>, width: u64) -> RValue<'gcc> {
+    fn rotate_right(
+        &mut self,
+        value: RValue<'gcc>,
+        shift: RValue<'gcc>,
+        width: u64,
+    ) -> RValue<'gcc> {
         let max = self.const_uint(shift.get_type(), width);
         let shift = self.urem(shift, max);
         let lhs = self.lshr(value, shift);
         let result_neg = self.neg(shift);
-        let result_and =
-            self.and(
-                result_neg,
-                self.const_uint(shift.get_type(), width - 1),
-            );
+        let result_and = self.and(result_neg, self.const_uint(shift.get_type(), width - 1));
         let rhs = self.shl(value, result_and);
         self.or(lhs, rhs)
     }
 
-    fn saturating_add(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>, signed: bool, width: u64) -> RValue<'gcc> {
+    fn saturating_add(
+        &mut self,
+        lhs: RValue<'gcc>,
+        rhs: RValue<'gcc>,
+        signed: bool,
+        width: u64,
+    ) -> RValue<'gcc> {
         let result_type = lhs.get_type();
         if signed {
             // Based on algorithm from: https://stackoverflow.com/a/56531252/389119
             let func = self.current_func.borrow().expect("func");
-            let res = func.new_local(None, result_type, "saturating_sum");
+            let res = func.new_local(self.location, result_type, "saturating_sum");
             let supports_native_type = self.is_native_int_type(result_type);
-            let overflow =
-                if supports_native_type {
-                    let func_name =
-                        match width {
-                            8 => "__builtin_add_overflow",
-                            16 => "__builtin_add_overflow",
-                            32 => "__builtin_sadd_overflow",
-                            64 => "__builtin_saddll_overflow",
-                            128 => "__builtin_add_overflow",
-                            _ => unreachable!(),
-                        };
-                    let overflow_func = self.context.get_builtin_function(func_name);
-                    self.overflow_call(overflow_func, &[lhs, rhs, res.get_address(None)], None)
-                }
-                else {
-                    let func_name =
-                        match width {
-                            128 => "__rust_i128_addo",
-                            _ => unreachable!(),
-                        };
-                    let (int_result, overflow) = self.operation_with_overflow(func_name, lhs, rhs);
-                    self.llbb().add_assignment(None, res, int_result);
-                    overflow
+            let overflow = if supports_native_type {
+                let func_name = match width {
+                    8 => "__builtin_add_overflow",
+                    16 => "__builtin_add_overflow",
+                    32 => "__builtin_sadd_overflow",
+                    64 => "__builtin_saddll_overflow",
+                    128 => "__builtin_add_overflow",
+                    _ => unreachable!(),
+                };
+                let overflow_func = self.context.get_builtin_function(func_name);
+                self.overflow_call(overflow_func, &[lhs, rhs, res.get_address(self.location)], None)
+            } else {
+                let func_name = match width {
+                    128 => "__rust_i128_addo",
+                    _ => unreachable!(),
                 };
+                let (int_result, overflow) = self.operation_with_overflow(func_name, lhs, rhs);
+                self.llbb().add_assignment(self.location, res, int_result);
+                overflow
+            };
 
             let then_block = func.new_block("then");
             let after_block = func.new_block("after");
@@ -955,83 +996,97 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
             // Return `result_type`'s maximum or minimum value on overflow
             // NOTE: convert the type to unsigned to have an unsigned shift.
             let unsigned_type = result_type.to_unsigned(&self.cx);
-            let shifted = self.gcc_lshr(self.gcc_int_cast(lhs, unsigned_type), self.gcc_int(unsigned_type, width as i64 - 1));
+            let shifted = self.gcc_lshr(
+                self.gcc_int_cast(lhs, unsigned_type),
+                self.gcc_int(unsigned_type, width as i64 - 1),
+            );
             let uint_max = self.gcc_not(self.gcc_int(unsigned_type, 0));
             let int_max = self.gcc_lshr(uint_max, self.gcc_int(unsigned_type, 1));
-            then_block.add_assignment(None, res, self.gcc_int_cast(self.gcc_add(shifted, int_max), result_type));
-            then_block.end_with_jump(None, after_block);
+            then_block.add_assignment(
+                self.location,
+                res,
+                self.gcc_int_cast(self.gcc_add(shifted, int_max), result_type),
+            );
+            then_block.end_with_jump(self.location, after_block);
 
-            self.llbb().end_with_conditional(None, overflow, then_block, after_block);
+            self.llbb().end_with_conditional(self.location, overflow, then_block, after_block);
 
             // NOTE: since jumps were added in a place rustc does not
             // expect, the current block in the state need to be updated.
             self.switch_to_block(after_block);
 
             res.to_rvalue()
-        }
-        else {
+        } else {
             // Algorithm from: http://locklessinc.com/articles/sat_arithmetic/
             let res = self.gcc_add(lhs, rhs);
             let cond = self.gcc_icmp(IntPredicate::IntULT, res, lhs);
             let value = self.gcc_neg(self.gcc_int_cast(cond, result_type));
-            self.gcc_or(res, value)
+            self.gcc_or(res, value, self.location)
         }
     }
 
     // Algorithm from: https://locklessinc.com/articles/sat_arithmetic/
-    fn saturating_sub(&mut self, lhs: RValue<'gcc>, rhs: RValue<'gcc>, signed: bool, width: u64) -> RValue<'gcc> {
+    fn saturating_sub(
+        &mut self,
+        lhs: RValue<'gcc>,
+        rhs: RValue<'gcc>,
+        signed: bool,
+        width: u64,
+    ) -> RValue<'gcc> {
         let result_type = lhs.get_type();
         if signed {
             // Based on algorithm from: https://stackoverflow.com/a/56531252/389119
             let func = self.current_func.borrow().expect("func");
-            let res = func.new_local(None, result_type, "saturating_diff");
+            let res = func.new_local(self.location, result_type, "saturating_diff");
             let supports_native_type = self.is_native_int_type(result_type);
-            let overflow =
-                if supports_native_type {
-                    let func_name =
-                        match width {
-                            8 => "__builtin_sub_overflow",
-                            16 => "__builtin_sub_overflow",
-                            32 => "__builtin_ssub_overflow",
-                            64 => "__builtin_ssubll_overflow",
-                            128 => "__builtin_sub_overflow",
-                            _ => unreachable!(),
-                        };
-                    let overflow_func = self.context.get_builtin_function(func_name);
-                    self.overflow_call(overflow_func, &[lhs, rhs, res.get_address(None)], None)
-                }
-                else {
-                    let func_name =
-                        match width {
-                            128 => "__rust_i128_subo",
-                            _ => unreachable!(),
-                        };
-                    let (int_result, overflow) = self.operation_with_overflow(func_name, lhs, rhs);
-                    self.llbb().add_assignment(None, res, int_result);
-                    overflow
+            let overflow = if supports_native_type {
+                let func_name = match width {
+                    8 => "__builtin_sub_overflow",
+                    16 => "__builtin_sub_overflow",
+                    32 => "__builtin_ssub_overflow",
+                    64 => "__builtin_ssubll_overflow",
+                    128 => "__builtin_sub_overflow",
+                    _ => unreachable!(),
                 };
+                let overflow_func = self.context.get_builtin_function(func_name);
+                self.overflow_call(overflow_func, &[lhs, rhs, res.get_address(self.location)], None)
+            } else {
+                let func_name = match width {
+                    128 => "__rust_i128_subo",
+                    _ => unreachable!(),
+                };
+                let (int_result, overflow) = self.operation_with_overflow(func_name, lhs, rhs);
+                self.llbb().add_assignment(self.location, res, int_result);
+                overflow
+            };
 
             let then_block = func.new_block("then");
             let after_block = func.new_block("after");
 
             // Return `result_type`'s maximum or minimum value on overflow
             // NOTE: convert the type to unsigned to have an unsigned shift.
-            let unsigned_type = result_type.to_unsigned(&self.cx);
-            let shifted = self.gcc_lshr(self.gcc_int_cast(lhs, unsigned_type), self.gcc_int(unsigned_type, width as i64 - 1));
+            let unsigned_type = result_type.to_unsigned(self.cx);
+            let shifted = self.gcc_lshr(
+                self.gcc_int_cast(lhs, unsigned_type),
+                self.gcc_int(unsigned_type, width as i64 - 1),
+            );
             let uint_max = self.gcc_not(self.gcc_int(unsigned_type, 0));
             let int_max = self.gcc_lshr(uint_max, self.gcc_int(unsigned_type, 1));
-            then_block.add_assignment(None, res, self.gcc_int_cast(self.gcc_add(shifted, int_max), result_type));
-            then_block.end_with_jump(None, after_block);
+            then_block.add_assignment(
+                self.location,
+                res,
+                self.gcc_int_cast(self.gcc_add(shifted, int_max), result_type),
+            );
+            then_block.end_with_jump(self.location, after_block);
 
-            self.llbb().end_with_conditional(None, overflow, then_block, after_block);
+            self.llbb().end_with_conditional(self.location, overflow, then_block, after_block);
 
             // NOTE: since jumps were added in a place rustc does not
             // expect, the current block in the state need to be updated.
             self.switch_to_block(after_block);
 
             res.to_rvalue()
-        }
-        else {
+        } else {
             let res = self.gcc_sub(lhs, rhs);
             let comparison = self.gcc_icmp(IntPredicate::IntULE, res, lhs);
             let value = self.gcc_neg(self.gcc_int_cast(comparison, result_type));
@@ -1040,21 +1095,26 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
     }
 }
 
-fn try_intrinsic<'a, 'b, 'gcc, 'tcx>(bx: &'b mut Builder<'a, 'gcc, 'tcx>, try_func: RValue<'gcc>, data: RValue<'gcc>, _catch_func: RValue<'gcc>, dest: RValue<'gcc>) {
+fn try_intrinsic<'a, 'b, 'gcc, 'tcx>(
+    bx: &'b mut Builder<'a, 'gcc, 'tcx>,
+    try_func: RValue<'gcc>,
+    data: RValue<'gcc>,
+    _catch_func: RValue<'gcc>,
+    dest: RValue<'gcc>,
+) {
     if bx.sess().panic_strategy() == PanicStrategy::Abort {
         bx.call(bx.type_void(), None, None, try_func, &[data], None);
         // Return 0 unconditionally from the intrinsic call;
         // we can never unwind.
         let ret_align = bx.tcx.data_layout.i32_align.abi;
         bx.store(bx.const_i32(0), dest, ret_align);
-    }
-    else if wants_msvc_seh(bx.sess()) {
-        unimplemented!();
-    }
-    else {
-        #[cfg(feature="master")]
+    } else {
+        if wants_msvc_seh(bx.sess()) {
+            unimplemented!();
+        }
+        #[cfg(feature = "master")]
         codegen_gnu_try(bx, try_func, data, _catch_func, dest);
-        #[cfg(not(feature="master"))]
+        #[cfg(not(feature = "master"))]
         unimplemented!();
     }
 }
@@ -1070,8 +1130,14 @@ fn try_intrinsic<'a, 'b, 'gcc, 'tcx>(bx: &'b mut Builder<'a, 'gcc, 'tcx>, try_fu
 // function calling it, and that function may already have other personality
 // functions in play. By calling a shim we're guaranteed that our shim will have
 // the right personality function.
-#[cfg(feature="master")]
-fn codegen_gnu_try<'gcc>(bx: &mut Builder<'_, 'gcc, '_>, try_func: RValue<'gcc>, data: RValue<'gcc>, catch_func: RValue<'gcc>, dest: RValue<'gcc>) {
+#[cfg(feature = "master")]
+fn codegen_gnu_try<'gcc>(
+    bx: &mut Builder<'_, 'gcc, '_>,
+    try_func: RValue<'gcc>,
+    data: RValue<'gcc>,
+    catch_func: RValue<'gcc>,
+    dest: RValue<'gcc>,
+) {
     let cx: &CodegenCx<'gcc, '_> = bx.cx;
     let (llty, func) = get_rust_try_fn(cx, &mut |mut bx| {
         // Codegens the shims described above:
@@ -1095,7 +1161,7 @@ fn codegen_gnu_try<'gcc>(bx: &mut Builder<'_, 'gcc, '_>, try_func: RValue<'gcc>,
         let catch_func = func.get_param(2).to_rvalue();
         let try_func_ty = bx.type_func(&[bx.type_i8p()], bx.type_void());
 
-        let current_block = bx.block.clone();
+        let current_block = bx.block;
 
         bx.switch_to_block(then);
         bx.ret(bx.const_i32(0));
@@ -1130,36 +1196,44 @@ fn codegen_gnu_try<'gcc>(bx: &mut Builder<'_, 'gcc, '_>, try_func: RValue<'gcc>,
     bx.store(ret, dest, i32_align);
 }
 
-
 // Helper function used to get a handle to the `__rust_try` function used to
 // catch exceptions.
 //
 // This function is only generated once and is then cached.
-#[cfg(feature="master")]
-fn get_rust_try_fn<'a, 'gcc, 'tcx>(cx: &'a CodegenCx<'gcc, 'tcx>, codegen: &mut dyn FnMut(Builder<'a, 'gcc, 'tcx>)) -> (Type<'gcc>, Function<'gcc>) {
+#[cfg(feature = "master")]
+fn get_rust_try_fn<'a, 'gcc, 'tcx>(
+    cx: &'a CodegenCx<'gcc, 'tcx>,
+    codegen: &mut dyn FnMut(Builder<'a, 'gcc, 'tcx>),
+) -> (Type<'gcc>, Function<'gcc>) {
     if let Some(llfn) = cx.rust_try_fn.get() {
         return llfn;
     }
 
     // Define the type up front for the signature of the rust_try function.
     let tcx = cx.tcx;
-    let i8p = Ty::new_mut_ptr(tcx,tcx.types.i8);
+    let i8p = Ty::new_mut_ptr(tcx, tcx.types.i8);
     // `unsafe fn(*mut i8) -> ()`
-    let try_fn_ty = Ty::new_fn_ptr(tcx,ty::Binder::dummy(tcx.mk_fn_sig(
-        iter::once(i8p),
-        Ty::new_unit(tcx,),
-        false,
-        rustc_hir::Unsafety::Unsafe,
-        Abi::Rust,
-    )));
+    let try_fn_ty = Ty::new_fn_ptr(
+        tcx,
+        ty::Binder::dummy(tcx.mk_fn_sig(
+            iter::once(i8p),
+            Ty::new_unit(tcx),
+            false,
+            rustc_hir::Unsafety::Unsafe,
+            Abi::Rust,
+        )),
+    );
     // `unsafe fn(*mut i8, *mut i8) -> ()`
-    let catch_fn_ty = Ty::new_fn_ptr(tcx,ty::Binder::dummy(tcx.mk_fn_sig(
-        [i8p, i8p].iter().cloned(),
-        Ty::new_unit(tcx,),
-        false,
-        rustc_hir::Unsafety::Unsafe,
-        Abi::Rust,
-    )));
+    let catch_fn_ty = Ty::new_fn_ptr(
+        tcx,
+        ty::Binder::dummy(tcx.mk_fn_sig(
+            [i8p, i8p].iter().cloned(),
+            Ty::new_unit(tcx),
+            false,
+            rustc_hir::Unsafety::Unsafe,
+            Abi::Rust,
+        )),
+    );
     // `unsafe fn(unsafe fn(*mut i8) -> (), *mut i8, unsafe fn(*mut i8, *mut i8) -> ()) -> i32`
     let rust_fn_sig = ty::Binder::dummy(cx.tcx.mk_fn_sig(
         [try_fn_ty, i8p, catch_fn_ty],
@@ -1175,8 +1249,13 @@ fn get_rust_try_fn<'a, 'gcc, 'tcx>(cx: &'a CodegenCx<'gcc, 'tcx>, codegen: &mut
 
 // Helper function to give a Block to a closure to codegen a shim function.
 // This is currently primarily used for the `try` intrinsic functions above.
-#[cfg(feature="master")]
-fn gen_fn<'a, 'gcc, 'tcx>(cx: &'a CodegenCx<'gcc, 'tcx>, name: &str, rust_fn_sig: ty::PolyFnSig<'tcx>, codegen: &mut dyn FnMut(Builder<'a, 'gcc, 'tcx>)) -> (Type<'gcc>, Function<'gcc>) {
+#[cfg(feature = "master")]
+fn gen_fn<'a, 'gcc, 'tcx>(
+    cx: &'a CodegenCx<'gcc, 'tcx>,
+    name: &str,
+    rust_fn_sig: ty::PolyFnSig<'tcx>,
+    codegen: &mut dyn FnMut(Builder<'a, 'gcc, 'tcx>),
+) -> (Type<'gcc>, Function<'gcc>) {
     let fn_abi = cx.fn_abi_of_fn_ptr(rust_fn_sig, ty::List::empty());
     let return_type = fn_abi.gcc_type(cx).return_type;
     // FIXME(eddyb) find a nicer way to do this.
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
index d8091724d86..e9af34059a0 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
@@ -1,3 +1,5 @@
+use std::iter::FromIterator;
+
 use gccjit::ToRValue;
 use gccjit::{BinaryOp, RValue, Type};
 #[cfg(feature = "master")]
@@ -19,6 +21,8 @@ use rustc_span::{sym, Span, Symbol};
 use rustc_target::abi::Align;
 
 use crate::builder::Builder;
+#[cfg(not(feature = "master"))]
+use crate::common::SignType;
 #[cfg(feature = "master")]
 use crate::context::CodegenCx;
 
@@ -156,6 +160,197 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
         return Ok(compare_simd_types(bx, arg1, arg2, in_elem, llret_ty, cmp_op));
     }
 
+    let simd_bswap = |bx: &mut Builder<'a, 'gcc, 'tcx>, vector: RValue<'gcc>| -> RValue<'gcc> {
+        let v_type = vector.get_type();
+        let vector_type = v_type.unqualified().dyncast_vector().expect("vector type");
+        let elem_type = vector_type.get_element_type();
+        let elem_size_bytes = elem_type.get_size();
+        if elem_size_bytes == 1 {
+            return vector;
+        }
+
+        let type_size_bytes = elem_size_bytes as u64 * in_len;
+        let shuffle_indices = Vec::from_iter(0..type_size_bytes);
+        let byte_vector_type = bx.context.new_vector_type(bx.type_u8(), type_size_bytes);
+        let byte_vector = bx.context.new_bitcast(None, args[0].immediate(), byte_vector_type);
+
+        #[cfg(not(feature = "master"))]
+        let shuffled = {
+            let new_elements: Vec<_> = shuffle_indices
+                .chunks_exact(elem_size_bytes as _)
+                .flat_map(|x| x.iter().rev())
+                .map(|&i| {
+                    let index = bx.context.new_rvalue_from_long(bx.u64_type, i as _);
+                    bx.extract_element(byte_vector, index)
+                })
+                .collect();
+
+            bx.context.new_rvalue_from_vector(None, byte_vector_type, &new_elements)
+        };
+        #[cfg(feature = "master")]
+        let shuffled = {
+            let indices: Vec<_> = shuffle_indices
+                .chunks_exact(elem_size_bytes as _)
+                .flat_map(|x| x.iter().rev())
+                .map(|&i| bx.context.new_rvalue_from_int(bx.u8_type, i as _))
+                .collect();
+
+            let mask = bx.context.new_rvalue_from_vector(None, byte_vector_type, &indices);
+            bx.context.new_rvalue_vector_perm(None, byte_vector, byte_vector, mask)
+        };
+        bx.context.new_bitcast(None, shuffled, v_type)
+    };
+
+    if name == sym::simd_bswap || name == sym::simd_bitreverse {
+        require!(
+            bx.type_kind(bx.element_type(llret_ty)) == TypeKind::Integer,
+            InvalidMonomorphization::UnsupportedOperation { span, name, in_ty, in_elem }
+        );
+    }
+
+    if name == sym::simd_bswap {
+        return Ok(simd_bswap(bx, args[0].immediate()));
+    }
+
+    // We use a different algorithm from non-vector bitreverse to take advantage of most
+    // processors' vector shuffle units.  It works like this:
+    // 1. Generate pre-reversed low and high nibbles as a vector.
+    // 2. Byte-swap the input.
+    // 3. Mask off the low and high nibbles of each byte in the byte-swapped input.
+    // 4. Shuffle the pre-reversed low and high-nibbles using the masked nibbles as a shuffle mask.
+    // 5. Combine the results of the shuffle back together and cast back to the original type.
+    #[cfg(feature = "master")]
+    if name == sym::simd_bitreverse {
+        let vector = args[0].immediate();
+        let v_type = vector.get_type();
+        let vector_type = v_type.unqualified().dyncast_vector().expect("vector type");
+        let elem_type = vector_type.get_element_type();
+        let elem_size_bytes = elem_type.get_size();
+
+        let type_size_bytes = elem_size_bytes as u64 * in_len;
+        // We need to ensure at least 16 entries in our vector type, since the pre-reversed vectors
+        // we generate below have 16 entries in them.  `new_rvalue_vector_perm` requires the mask
+        // vector to be of the same length as the source vectors.
+        let byte_vector_type_size = type_size_bytes.max(16);
+
+        let byte_vector_type = bx.context.new_vector_type(bx.u8_type, type_size_bytes);
+        let long_byte_vector_type = bx.context.new_vector_type(bx.u8_type, byte_vector_type_size);
+
+        // Step 1: Generate pre-reversed low and high nibbles as a vector.
+        let zero_byte = bx.context.new_rvalue_zero(bx.u8_type);
+        let hi_nibble_elements: Vec<_> = (0u8..16)
+            .map(|x| bx.context.new_rvalue_from_int(bx.u8_type, x.reverse_bits() as _))
+            .chain((16..byte_vector_type_size).map(|_| zero_byte))
+            .collect();
+        let hi_nibble =
+            bx.context.new_rvalue_from_vector(None, long_byte_vector_type, &hi_nibble_elements);
+
+        let lo_nibble_elements: Vec<_> = (0u8..16)
+            .map(|x| bx.context.new_rvalue_from_int(bx.u8_type, (x.reverse_bits() >> 4) as _))
+            .chain((16..byte_vector_type_size).map(|_| zero_byte))
+            .collect();
+        let lo_nibble =
+            bx.context.new_rvalue_from_vector(None, long_byte_vector_type, &lo_nibble_elements);
+
+        let mask = bx.context.new_rvalue_from_vector(
+            None,
+            long_byte_vector_type,
+            &vec![bx.context.new_rvalue_from_int(bx.u8_type, 0x0f); byte_vector_type_size as _],
+        );
+
+        let four_vec = bx.context.new_rvalue_from_vector(
+            None,
+            long_byte_vector_type,
+            &vec![bx.context.new_rvalue_from_int(bx.u8_type, 4); byte_vector_type_size as _],
+        );
+
+        // Step 2: Byte-swap the input.
+        let swapped = simd_bswap(bx, args[0].immediate());
+        let byte_vector = bx.context.new_bitcast(None, swapped, byte_vector_type);
+
+        // We're going to need to extend the vector with zeros to make sure that the types are the
+        // same, since that's what new_rvalue_vector_perm expects.
+        let byte_vector = if byte_vector_type_size > type_size_bytes {
+            let mut byte_vector_elements = Vec::with_capacity(byte_vector_type_size as _);
+            for i in 0..type_size_bytes {
+                let idx = bx.context.new_rvalue_from_int(bx.u32_type, i as _);
+                let val = bx.extract_element(byte_vector, idx);
+                byte_vector_elements.push(val);
+            }
+            for _ in type_size_bytes..byte_vector_type_size {
+                byte_vector_elements.push(zero_byte);
+            }
+            bx.context.new_rvalue_from_vector(None, long_byte_vector_type, &byte_vector_elements)
+        } else {
+            bx.context.new_bitcast(None, byte_vector, long_byte_vector_type)
+        };
+
+        // Step 3: Mask off the low and high nibbles of each byte in the byte-swapped input.
+        let masked_hi = (byte_vector >> four_vec) & mask;
+        let masked_lo = byte_vector & mask;
+
+        // Step 4: Shuffle the pre-reversed low and high-nibbles using the masked nibbles as a shuffle mask.
+        let hi = bx.context.new_rvalue_vector_perm(None, hi_nibble, hi_nibble, masked_lo);
+        let lo = bx.context.new_rvalue_vector_perm(None, lo_nibble, lo_nibble, masked_hi);
+
+        // Step 5: Combine the results of the shuffle back together and cast back to the original type.
+        let result = hi | lo;
+        let cast_ty =
+            bx.context.new_vector_type(elem_type, byte_vector_type_size / (elem_size_bytes as u64));
+
+        // we might need to truncate if sizeof(v_type) < sizeof(cast_type)
+        if type_size_bytes < byte_vector_type_size {
+            let cast_result = bx.context.new_bitcast(None, result, cast_ty);
+            let elems: Vec<_> = (0..in_len)
+                .map(|i| {
+                    let idx = bx.context.new_rvalue_from_int(bx.u32_type, i as _);
+                    bx.extract_element(cast_result, idx)
+                })
+                .collect();
+            return Ok(bx.context.new_rvalue_from_vector(None, v_type, &elems));
+        } else {
+            // avoid the unnecessary truncation as an optimization.
+            return Ok(bx.context.new_bitcast(None, result, v_type));
+        }
+    }
+    // since gcc doesn't have vector shuffle methods available in non-patched builds, fallback to
+    // component-wise bitreverses if they're not available.
+    #[cfg(not(feature = "master"))]
+    if name == sym::simd_bitreverse {
+        let vector = args[0].immediate();
+        let vector_ty = vector.get_type();
+        let vector_type = vector_ty.unqualified().dyncast_vector().expect("vector type");
+        let num_elements = vector_type.get_num_units();
+
+        let elem_type = vector_type.get_element_type();
+        let elem_size_bytes = elem_type.get_size();
+        let num_type = elem_type.to_unsigned(bx.cx);
+        let new_elements: Vec<_> = (0..num_elements)
+            .map(|idx| {
+                let index = bx.context.new_rvalue_from_long(num_type, idx as _);
+                let extracted_value = bx.extract_element(vector, index).to_rvalue();
+                bx.bit_reverse(elem_size_bytes as u64 * 8, extracted_value)
+            })
+            .collect();
+        return Ok(bx.context.new_rvalue_from_vector(None, vector_ty, &new_elements));
+    }
+
+    if name == sym::simd_ctlz || name == sym::simd_cttz {
+        let vector = args[0].immediate();
+        let elements: Vec<_> = (0..in_len)
+            .map(|i| {
+                let index = bx.context.new_rvalue_from_long(bx.i32_type, i as i64);
+                let value = bx.extract_element(vector, index).to_rvalue();
+                if name == sym::simd_ctlz {
+                    bx.count_leading_zeroes(value.get_type().get_size() as u64 * 8, value)
+                } else {
+                    bx.count_trailing_zeroes(value.get_type().get_size() as u64 * 8, value)
+                }
+            })
+            .collect();
+        return Ok(bx.context.new_rvalue_from_vector(None, vector.get_type(), &elements));
+    }
+
     if name == sym::simd_shuffle {
         // Make sure this is actually an array, since typeck only checks the length-suffixed
         // version of this intrinsic.
@@ -504,20 +699,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
         default: RValue<'gcc>,
         pointers: RValue<'gcc>,
         mask: RValue<'gcc>,
-        pointer_count: usize,
         bx: &mut Builder<'a, 'gcc, 'tcx>,
         in_len: u64,
-        underlying_ty: Ty<'tcx>,
         invert: bool,
     ) -> RValue<'gcc> {
-        let vector_type = if pointer_count > 1 {
-            bx.context.new_vector_type(bx.usize_type, in_len)
-        } else {
-            vector_ty(bx, underlying_ty, in_len)
-        };
-        let elem_type = vector_type.dyncast_vector().expect("vector type").get_element_type();
+        let vector_type = default.get_type();
+        let elem_type =
+            vector_type.unqualified().dyncast_vector().expect("vector type").get_element_type();
 
-        let mut values = vec![];
+        let mut values = Vec::with_capacity(in_len as usize);
         for i in 0..in_len {
             let index = bx.context.new_rvalue_from_long(bx.i32_type, i as i64);
             let int = bx.context.new_vector_access(None, pointers, index).to_rvalue();
@@ -530,13 +720,15 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
 
         let vector = bx.context.new_rvalue_from_vector(None, vector_type, &values);
 
-        let mut mask_types = vec![];
-        let mut mask_values = vec![];
+        let mut mask_types = Vec::with_capacity(in_len as usize);
+        let mut mask_values = Vec::with_capacity(in_len as usize);
         for i in 0..in_len {
             let index = bx.context.new_rvalue_from_long(bx.i32_type, i as i64);
             mask_types.push(bx.context.new_field(None, bx.i32_type, "m"));
             let mask_value = bx.context.new_vector_access(None, mask, index).to_rvalue();
-            let masked = bx.context.new_rvalue_from_int(bx.i32_type, in_len as i32) & mask_value;
+            let mask_value_cast = bx.context.new_cast(None, mask_value, bx.i32_type);
+            let masked =
+                bx.context.new_rvalue_from_int(bx.i32_type, in_len as i32) & mask_value_cast;
             let value = index + masked;
             mask_values.push(value);
         }
@@ -665,10 +857,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
             args[0].immediate(),
             args[1].immediate(),
             args[2].immediate(),
-            pointer_count,
             bx,
             in_len,
-            underlying_ty,
             false,
         ));
     }
@@ -779,16 +969,8 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>(
             }
         }
 
-        let result = gather(
-            args[0].immediate(),
-            args[1].immediate(),
-            args[2].immediate(),
-            pointer_count,
-            bx,
-            in_len,
-            underlying_ty,
-            true,
-        );
+        let result =
+            gather(args[0].immediate(), args[1].immediate(), args[2].immediate(), bx, in_len, true);
 
         let pointers = args[1].immediate();
 
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index 09ce059476e..a4ee3015b8d 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -4,6 +4,7 @@
  * TODO(antoyo): support LTO (gcc's equivalent to Full LTO is -flto -flto-partition=one — https://documentation.suse.com/sbp/all/html/SBP-GCC-10/index.html).
  * For Thin LTO, this might be helpful:
  * In gcc 4.6 -fwhopr was removed and became default with -flto. The non-whopr path can still be executed via -flto-partition=none.
+ * Or the new incremental LTO?
  *
  * Maybe some missing optizations enabled by rustc's LTO is in there: https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
  * Like -fipa-icf (should be already enabled) and maybe -fdevirtualize-at-ltrans.
@@ -24,9 +25,10 @@
     hash_raw_entry
 )]
 #![allow(broken_intra_doc_links)]
-#![recursion_limit="256"]
+#![recursion_limit = "256"]
 #![warn(rust_2018_idioms)]
 #![warn(unused_lifetimes)]
+#![deny(clippy::pattern_type_mismatch)]
 
 extern crate rustc_apfloat;
 extern crate rustc_ast;
@@ -37,7 +39,8 @@ extern crate rustc_errors;
 extern crate rustc_fluent_macro;
 extern crate rustc_fs_util;
 extern crate rustc_hir;
-#[cfg(feature="master")]
+extern crate rustc_index;
+#[cfg(feature = "master")]
 extern crate rustc_interface;
 extern crate rustc_macros;
 extern crate rustc_metadata;
@@ -77,36 +80,40 @@ mod type_of;
 
 use std::any::Any;
 use std::fmt::Debug;
-use std::sync::Arc;
-use std::sync::Mutex;
-#[cfg(not(feature="master"))]
+#[cfg(not(feature = "master"))]
 use std::sync::atomic::AtomicBool;
-#[cfg(not(feature="master"))]
+#[cfg(not(feature = "master"))]
 use std::sync::atomic::Ordering;
+use std::sync::Arc;
+use std::sync::Mutex;
 
+use errors::LTONotSupported;
+#[cfg(not(feature = "master"))]
+use gccjit::CType;
 use gccjit::{Context, OptimizationLevel};
-#[cfg(feature="master")]
+#[cfg(feature = "master")]
 use gccjit::{TargetInfo, Version};
-#[cfg(not(feature="master"))]
-use gccjit::CType;
-use errors::LTONotSupported;
 use rustc_ast::expand::allocator::AllocatorKind;
-use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen};
-use rustc_codegen_ssa::base::codegen_crate;
-use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryFn};
 use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
+use rustc_codegen_ssa::back::write::{
+    CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryFn,
+};
+use rustc_codegen_ssa::base::codegen_crate;
+use rustc_codegen_ssa::traits::{
+    CodegenBackend, ExtraBackendMethods, ThinBufferMethods, WriteBackendMethods,
+};
+use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen};
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::sync::IntoDynSyncSend;
-use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, ThinBufferMethods, WriteBackendMethods};
-use rustc_errors::{ErrorGuaranteed, DiagCtxt};
+use rustc_errors::{DiagCtxt, ErrorGuaranteed};
 use rustc_metadata::EncodedMetadata;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
-use rustc_middle::util::Providers;
 use rustc_middle::ty::TyCtxt;
+use rustc_middle::util::Providers;
 use rustc_session::config::{Lto, OptLevel, OutputFilenames};
 use rustc_session::Session;
-use rustc_span::Symbol;
 use rustc_span::fatal_error::FatalError;
+use rustc_span::Symbol;
 use tempfile::TempDir;
 
 use crate::back::lto::ModuleBuffer;
@@ -124,13 +131,13 @@ impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
     }
 }
 
-#[cfg(not(feature="master"))]
+#[cfg(not(feature = "master"))]
 #[derive(Debug)]
 pub struct TargetInfo {
     supports_128bit_integers: AtomicBool,
 }
 
-#[cfg(not(feature="master"))]
+#[cfg(not(feature = "master"))]
 impl TargetInfo {
     fn cpu_supports(&self, _feature: &str) -> bool {
         false
@@ -173,26 +180,26 @@ impl CodegenBackend for GccCodegenBackend {
     }
 
     fn init(&self, sess: &Session) {
-        #[cfg(feature="master")]
+        #[cfg(feature = "master")]
         {
             let target_cpu = target_cpu(sess);
 
             // Get the second TargetInfo with the correct CPU features by setting the arch.
             let context = Context::default();
             if target_cpu != "generic" {
-                context.add_command_line_option(&format!("-march={}", target_cpu));
+                context.add_command_line_option(format!("-march={}", target_cpu));
             }
 
             **self.target_info.info.lock().expect("lock") = context.get_target_info();
         }
 
-        #[cfg(feature="master")]
+        #[cfg(feature = "master")]
         gccjit::set_global_personality_function_name(b"rust_eh_personality\0");
         if sess.lto() == Lto::Thin {
             sess.dcx().emit_warn(LTONotSupported {});
         }
 
-        #[cfg(not(feature="master"))]
+        #[cfg(not(feature = "master"))]
         {
             let temp_dir = TempDir::new().expect("cannot create temporary directory");
             let temp_file = temp_dir.into_path().join("result.asm");
@@ -200,39 +207,62 @@ impl CodegenBackend for GccCodegenBackend {
             check_context.set_print_errors_to_stderr(false);
             let _int128_ty = check_context.new_c_type(CType::UInt128t);
             // NOTE: we cannot just call compile() as this would require other files than libgccjit.so.
-            check_context.compile_to_file(gccjit::OutputKind::Assembler, temp_file.to_str().expect("path to str"));
-            self.target_info.info.lock().expect("lock").supports_128bit_integers.store(check_context.get_last_error() == Ok(None), Ordering::SeqCst);
+            check_context.compile_to_file(
+                gccjit::OutputKind::Assembler,
+                temp_file.to_str().expect("path to str"),
+            );
+            self.target_info
+                .info
+                .lock()
+                .expect("lock")
+                .supports_128bit_integers
+                .store(check_context.get_last_error() == Ok(None), Ordering::SeqCst);
         }
     }
 
     fn provide(&self, providers: &mut Providers) {
-        providers.global_backend_features =
-            |tcx, ()| gcc_util::global_gcc_features(tcx.sess, true)
+        providers.global_backend_features = |tcx, ()| gcc_util::global_gcc_features(tcx.sess, true)
     }
 
-    fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>, metadata: EncodedMetadata, need_metadata_module: bool) -> Box<dyn Any> {
+    fn codegen_crate(
+        &self,
+        tcx: TyCtxt<'_>,
+        metadata: EncodedMetadata,
+        need_metadata_module: bool,
+    ) -> Box<dyn Any> {
         let target_cpu = target_cpu(tcx.sess);
-        let res = codegen_crate(self.clone(), tcx, target_cpu.to_string(), metadata, need_metadata_module);
+        let res = codegen_crate(
+            self.clone(),
+            tcx,
+            target_cpu.to_string(),
+            metadata,
+            need_metadata_module,
+        );
 
         Box::new(res)
     }
 
-    fn join_codegen(&self, ongoing_codegen: Box<dyn Any>, sess: &Session, _outputs: &OutputFilenames) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) {
+    fn join_codegen(
+        &self,
+        ongoing_codegen: Box<dyn Any>,
+        sess: &Session,
+        _outputs: &OutputFilenames,
+    ) -> (CodegenResults, FxIndexMap<WorkProductId, WorkProduct>) {
         ongoing_codegen
             .downcast::<rustc_codegen_ssa::back::write::OngoingCodegen<GccCodegenBackend>>()
             .expect("Expected GccCodegenBackend's OngoingCodegen, found Box<Any>")
             .join(sess)
     }
 
-    fn link(&self, sess: &Session, codegen_results: CodegenResults, outputs: &OutputFilenames) -> Result<(), ErrorGuaranteed> {
+    fn link(
+        &self,
+        sess: &Session,
+        codegen_results: CodegenResults,
+        outputs: &OutputFilenames,
+    ) -> Result<(), ErrorGuaranteed> {
         use rustc_codegen_ssa::back::link::link_binary;
 
-        link_binary(
-            sess,
-            &crate::archive::ArArchiveBuilderBuilder,
-            &codegen_results,
-            outputs,
-        )
+        link_binary(sess, &crate::archive::ArArchiveBuilderBuilder, &codegen_results, outputs)
     }
 
     fn target_features(&self, sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
@@ -245,13 +275,15 @@ fn new_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> {
     if tcx.sess.target.arch == "x86" || tcx.sess.target.arch == "x86_64" {
         context.add_command_line_option("-masm=intel");
     }
-    #[cfg(feature="master")]
+    #[cfg(feature = "master")]
     {
+        context.set_special_chars_allowed_in_func_names("$.*");
         let version = Version::get();
         let version = format!("{}.{}.{}", version.major, version.minor, version.patch);
-        context.set_output_ident(&format!("rustc version {} with libgccjit {}",
-                rustc_interface::util::rustc_version_str().unwrap_or("unknown version"),
-                version,
+        context.set_output_ident(&format!(
+            "rustc version {} with libgccjit {}",
+            rustc_interface::util::rustc_version_str().unwrap_or("unknown version"),
+            version,
         ));
     }
     // TODO(antoyo): check if this should only be added when using -Cforce-unwind-tables=n.
@@ -260,26 +292,41 @@ fn new_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> {
 }
 
 impl ExtraBackendMethods for GccCodegenBackend {
-    fn codegen_allocator<'tcx>(&self, tcx: TyCtxt<'tcx>, module_name: &str, kind: AllocatorKind, alloc_error_handler_kind: AllocatorKind) -> Self::Module {
+    fn codegen_allocator(
+        &self,
+        tcx: TyCtxt<'_>,
+        module_name: &str,
+        kind: AllocatorKind,
+        alloc_error_handler_kind: AllocatorKind,
+    ) -> Self::Module {
         let mut mods = GccContext {
             context: new_context(tcx),
             should_combine_object_files: false,
             temp_dir: None,
         };
 
-        unsafe { allocator::codegen(tcx, &mut mods, module_name, kind, alloc_error_handler_kind); }
+        unsafe {
+            allocator::codegen(tcx, &mut mods, module_name, kind, alloc_error_handler_kind);
+        }
         mods
     }
 
-    fn compile_codegen_unit(&self, tcx: TyCtxt<'_>, cgu_name: Symbol) -> (ModuleCodegen<Self::Module>, u64) {
+    fn compile_codegen_unit(
+        &self,
+        tcx: TyCtxt<'_>,
+        cgu_name: Symbol,
+    ) -> (ModuleCodegen<Self::Module>, u64) {
         base::compile_codegen_unit(tcx, cgu_name, self.target_info.clone())
     }
 
-    fn target_machine_factory(&self, _sess: &Session, _opt_level: OptLevel, _features: &[String]) -> TargetMachineFactoryFn<Self> {
+    fn target_machine_factory(
+        &self,
+        _sess: &Session,
+        _opt_level: OptLevel,
+        _features: &[String],
+    ) -> TargetMachineFactoryFn<Self> {
         // TODO(antoyo): set opt level.
-        Arc::new(|_| {
-            Ok(())
-        })
+        Arc::new(|_| Ok(()))
     }
 }
 
@@ -310,11 +357,19 @@ impl WriteBackendMethods for GccCodegenBackend {
     type ThinData = ();
     type ThinBuffer = ThinBuffer;
 
-    fn run_fat_lto(cgcx: &CodegenContext<Self>, modules: Vec<FatLtoInput<Self>>, cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>) -> Result<LtoModuleCodegen<Self>, FatalError> {
+    fn run_fat_lto(
+        cgcx: &CodegenContext<Self>,
+        modules: Vec<FatLtoInput<Self>>,
+        cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
+    ) -> Result<LtoModuleCodegen<Self>, FatalError> {
         back::lto::run_fat(cgcx, modules, cached_modules)
     }
 
-    fn run_thin_lto(_cgcx: &CodegenContext<Self>, _modules: Vec<(String, Self::ThinBuffer)>, _cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>) -> Result<(Vec<LtoModuleCodegen<Self>>, Vec<WorkProduct>), FatalError> {
+    fn run_thin_lto(
+        _cgcx: &CodegenContext<Self>,
+        _modules: Vec<(String, Self::ThinBuffer)>,
+        _cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
+    ) -> Result<(Vec<LtoModuleCodegen<Self>>, Vec<WorkProduct>), FatalError> {
         unimplemented!();
     }
 
@@ -326,21 +381,37 @@ impl WriteBackendMethods for GccCodegenBackend {
         unimplemented!()
     }
 
-    unsafe fn optimize(_cgcx: &CodegenContext<Self>, _dcx: &DiagCtxt, module: &ModuleCodegen<Self::Module>, config: &ModuleConfig) -> Result<(), FatalError> {
+    unsafe fn optimize(
+        _cgcx: &CodegenContext<Self>,
+        _dcx: &DiagCtxt,
+        module: &ModuleCodegen<Self::Module>,
+        config: &ModuleConfig,
+    ) -> Result<(), FatalError> {
         module.module_llvm.context.set_optimization_level(to_gcc_opt_level(config.opt_level));
         Ok(())
     }
 
-    fn optimize_fat(_cgcx: &CodegenContext<Self>, _module: &mut ModuleCodegen<Self::Module>) -> Result<(), FatalError> {
+    fn optimize_fat(
+        _cgcx: &CodegenContext<Self>,
+        _module: &mut ModuleCodegen<Self::Module>,
+    ) -> Result<(), FatalError> {
         // TODO(antoyo)
         Ok(())
     }
 
-    unsafe fn optimize_thin(_cgcx: &CodegenContext<Self>, _thin: ThinModule<Self>) -> Result<ModuleCodegen<Self::Module>, FatalError> {
+    unsafe fn optimize_thin(
+        _cgcx: &CodegenContext<Self>,
+        _thin: ThinModule<Self>,
+    ) -> Result<ModuleCodegen<Self::Module>, FatalError> {
         unimplemented!();
     }
 
-    unsafe fn codegen(cgcx: &CodegenContext<Self>, dcx: &DiagCtxt, module: ModuleCodegen<Self::Module>, config: &ModuleConfig) -> Result<CompiledModule, FatalError> {
+    unsafe fn codegen(
+        cgcx: &CodegenContext<Self>,
+        dcx: &DiagCtxt,
+        module: ModuleCodegen<Self::Module>,
+        config: &ModuleConfig,
+    ) -> Result<CompiledModule, FatalError> {
         back::write::codegen(cgcx, dcx, module, config)
     }
 
@@ -352,7 +423,11 @@ impl WriteBackendMethods for GccCodegenBackend {
         unimplemented!();
     }
 
-    fn run_link(cgcx: &CodegenContext<Self>, dcx: &DiagCtxt, modules: Vec<ModuleCodegen<Self::Module>>) -> Result<ModuleCodegen<Self::Module>, FatalError> {
+    fn run_link(
+        cgcx: &CodegenContext<Self>,
+        dcx: &DiagCtxt,
+        modules: Vec<ModuleCodegen<Self::Module>>,
+    ) -> Result<ModuleCodegen<Self::Module>, FatalError> {
         back::write::link(cgcx, dcx, modules)
     }
 }
@@ -360,56 +435,57 @@ impl WriteBackendMethods for GccCodegenBackend {
 /// This is the entrypoint for a hot plugged rustc_codegen_gccjit
 #[no_mangle]
 pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
-    #[cfg(feature="master")]
+    #[cfg(feature = "master")]
     let info = {
         // Check whether the target supports 128-bit integers.
         let context = Context::default();
         Arc::new(Mutex::new(IntoDynSyncSend(context.get_target_info())))
     };
-    #[cfg(not(feature="master"))]
+    #[cfg(not(feature = "master"))]
     let info = Arc::new(Mutex::new(IntoDynSyncSend(TargetInfo {
         supports_128bit_integers: AtomicBool::new(false),
     })));
 
-    Box::new(GccCodegenBackend {
-        target_info: LockedTargetInfo { info },
-    })
+    Box::new(GccCodegenBackend { target_info: LockedTargetInfo { info } })
 }
 
 fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
     match optlevel {
         None => OptimizationLevel::None,
-        Some(level) => {
-            match level {
-                OptLevel::No => OptimizationLevel::None,
-                OptLevel::Less => OptimizationLevel::Limited,
-                OptLevel::Default => OptimizationLevel::Standard,
-                OptLevel::Aggressive => OptimizationLevel::Aggressive,
-                OptLevel::Size | OptLevel::SizeMin => OptimizationLevel::Limited,
-            }
+        Some(level) => match level {
+            OptLevel::No => OptimizationLevel::None,
+            OptLevel::Less => OptimizationLevel::Limited,
+            OptLevel::Default => OptimizationLevel::Standard,
+            OptLevel::Aggressive => OptimizationLevel::Aggressive,
+            OptLevel::Size | OptLevel::SizeMin => OptimizationLevel::Limited,
         },
     }
 }
 
-pub fn target_features(sess: &Session, allow_unstable: bool, target_info: &LockedTargetInfo) -> Vec<Symbol> {
-    sess
-        .target
+pub fn target_features(
+    sess: &Session,
+    allow_unstable: bool,
+    target_info: &LockedTargetInfo,
+) -> Vec<Symbol> {
+    sess.target
         .supported_target_features()
         .iter()
-        .filter_map(
-            |&(feature, gate)| {
-                if sess.is_nightly_build() || allow_unstable || gate.is_stable() { Some(feature) } else { None }
-            },
-        )
+        .filter_map(|&(feature, gate)| {
+            if sess.is_nightly_build() || allow_unstable || gate.is_stable() {
+                Some(feature)
+            } else {
+                None
+            }
+        })
         .filter(|_feature| {
             target_info.cpu_supports(_feature)
             /*
-               adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma,
-               avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq,
-               bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm,
-               sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves
-             */
+              adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma,
+              avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq,
+              bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm,
+              sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves
+            */
         })
-        .map(|feature| Symbol::intern(feature))
+        .map(Symbol::intern)
         .collect()
 }
diff --git a/compiler/rustc_codegen_gcc/src/mono_item.rs b/compiler/rustc_codegen_gcc/src/mono_item.rs
index 3322d56513b..e56c49686c0 100644
--- a/compiler/rustc_codegen_gcc/src/mono_item.rs
+++ b/compiler/rustc_codegen_gcc/src/mono_item.rs
@@ -1,11 +1,11 @@
-#[cfg(feature="master")]
-use gccjit::{VarAttribute, FnAttribute};
+#[cfg(feature = "master")]
+use gccjit::{FnAttribute, VarAttribute};
 use rustc_codegen_ssa::traits::PreDefineMethods;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::mono::{Linkage, Visibility};
-use rustc_middle::ty::{self, Instance, TypeVisitableExt};
 use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
+use rustc_middle::ty::{self, Instance, TypeVisitableExt};
 
 use crate::attributes;
 use crate::base;
@@ -13,8 +13,14 @@ use crate::context::CodegenCx;
 use crate::type_of::LayoutGccExt;
 
 impl<'gcc, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
-    #[cfg_attr(not(feature="master"), allow(unused_variables))]
-    fn predefine_static(&self, def_id: DefId, _linkage: Linkage, visibility: Visibility, symbol_name: &str) {
+    #[cfg_attr(not(feature = "master"), allow(unused_variables))]
+    fn predefine_static(
+        &self,
+        def_id: DefId,
+        _linkage: Linkage,
+        visibility: Visibility,
+        symbol_name: &str,
+    ) {
         let attrs = self.tcx.codegen_fn_attrs(def_id);
         let instance = Instance::mono(self.tcx, def_id);
         let ty = instance.ty(self.tcx, ty::ParamEnv::reveal_all());
@@ -22,20 +28,26 @@ impl<'gcc, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
 
         let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL);
         let global = self.define_global(symbol_name, gcc_type, is_tls, attrs.link_section);
-        #[cfg(feature="master")]
-        global.add_attribute(VarAttribute::Visibility(base::visibility_to_gcc(visibility)));
+        #[cfg(feature = "master")]
+        global.add_string_attribute(VarAttribute::Visibility(base::visibility_to_gcc(visibility)));
 
         // TODO(antoyo): set linkage.
         self.instances.borrow_mut().insert(instance, global);
     }
 
-    #[cfg_attr(not(feature="master"), allow(unused_variables))]
-    fn predefine_fn(&self, instance: Instance<'tcx>, linkage: Linkage, visibility: Visibility, symbol_name: &str) {
+    #[cfg_attr(not(feature = "master"), allow(unused_variables))]
+    fn predefine_fn(
+        &self,
+        instance: Instance<'tcx>,
+        linkage: Linkage,
+        visibility: Visibility,
+        symbol_name: &str,
+    ) {
         assert!(!instance.args.has_infer());
 
         let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty());
         self.linkage.set(base::linkage_to_gcc(linkage));
-        let decl = self.declare_fn(symbol_name, &fn_abi);
+        let decl = self.declare_fn(symbol_name, fn_abi);
         //let attrs = self.tcx.codegen_fn_attrs(instance.def_id());
 
         attributes::from_fn_attrs(self, decl, instance);
@@ -48,11 +60,10 @@ impl<'gcc, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
             && linkage != Linkage::Private
             && self.tcx.is_compiler_builtins(LOCAL_CRATE)
         {
-            #[cfg(feature="master")]
+            #[cfg(feature = "master")]
             decl.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden));
-        }
-        else {
-            #[cfg(feature="master")]
+        } else {
+            #[cfg(feature = "master")]
             decl.add_attribute(FnAttribute::Visibility(base::visibility_to_gcc(visibility)));
         }
 
diff --git a/compiler/rustc_codegen_gcc/src/type_.rs b/compiler/rustc_codegen_gcc/src/type_.rs
index 7e5aa1c1766..68471b028be 100644
--- a/compiler/rustc_codegen_gcc/src/type_.rs
+++ b/compiler/rustc_codegen_gcc/src/type_.rs
@@ -1,8 +1,8 @@
 use gccjit::{RValue, Struct, Type};
-use rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, TypeMembershipMethods};
 use rustc_codegen_ssa::common::TypeKind;
-use rustc_middle::{bug, ty};
+use rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, TypeMembershipMethods};
 use rustc_middle::ty::layout::TyAndLayout;
+use rustc_middle::{bug, ty};
 use rustc_target::abi::{AddressSpace, Align, Integer, Size};
 
 use crate::common::TypeReflection;
@@ -123,7 +123,7 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     fn type_f16(&self) -> Type<'gcc> {
         unimplemented!("f16_f128")
     }
-    
+
     fn type_f32(&self) -> Type<'gcc> {
         self.float_type
     }
@@ -143,14 +143,18 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     fn type_struct(&self, fields: &[Type<'gcc>], packed: bool) -> Type<'gcc> {
         let types = fields.to_vec();
         if let Some(typ) = self.struct_types.borrow().get(fields) {
-            return typ.clone();
+            return *typ;
         }
-        let fields: Vec<_> = fields.iter().enumerate()
-            .map(|(index, field)| self.context.new_field(None, *field, &format!("field{}_TODO", index)))
+        let fields: Vec<_> = fields
+            .iter()
+            .enumerate()
+            .map(|(index, field)| {
+                self.context.new_field(None, *field, format!("field{}_TODO", index))
+            })
             .collect();
         let typ = self.context.new_struct_type(None, "struct", &fields).as_type();
         if packed {
-            #[cfg(feature="master")]
+            #[cfg(feature = "master")]
             typ.set_packed();
         }
         self.struct_types.borrow_mut().insert(types, typ);
@@ -160,17 +164,13 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     fn type_kind(&self, typ: Type<'gcc>) -> TypeKind {
         if self.is_int_type_or_bool(typ) {
             TypeKind::Integer
-        }
-        else if typ.is_compatible_with(self.float_type) {
+        } else if typ.is_compatible_with(self.float_type) {
             TypeKind::Float
-        }
-        else if typ.is_compatible_with(self.double_type) {
+        } else if typ.is_compatible_with(self.double_type) {
             TypeKind::Double
-        }
-        else if typ.is_vector() {
+        } else if typ.is_vector() {
             TypeKind::Vector
-        }
-        else {
+        } else {
             // TODO(antoyo): support other types.
             TypeKind::Void
         }
@@ -187,14 +187,11 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     fn element_type(&self, ty: Type<'gcc>) -> Type<'gcc> {
         if let Some(typ) = ty.dyncast_array() {
             typ
-        }
-        else if let Some(vector_type) = ty.dyncast_vector() {
+        } else if let Some(vector_type) = ty.dyncast_vector() {
             vector_type.get_element_type()
-        }
-        else if let Some(typ) = ty.get_pointee() {
+        } else if let Some(typ) = ty.get_pointee() {
             typ
-        }
-        else {
+        } else {
             unreachable!()
         }
     }
@@ -208,11 +205,9 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         let f64 = self.context.new_type::<f64>();
         if typ.is_compatible_with(f32) {
             32
-        }
-        else if typ.is_compatible_with(f64) {
+        } else if typ.is_compatible_with(f64) {
             64
-        }
-        else {
+        } else {
             panic!("Cannot get width of float type {:?}", typ);
         }
         // TODO(antoyo): support other sizes.
@@ -226,9 +221,9 @@ impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         value.get_type()
     }
 
-    #[cfg_attr(feature="master", allow(unused_mut))]
+    #[cfg_attr(feature = "master", allow(unused_mut))]
     fn type_array(&self, ty: Type<'gcc>, mut len: u64) -> Type<'gcc> {
-        #[cfg(not(feature="master"))]
+        #[cfg(not(feature = "master"))]
         if let Some(struct_type) = ty.is_struct() {
             if struct_type.get_field_count() == 0 {
                 // NOTE: since gccjit only supports i32 for the array size and libcore's tests uses a
@@ -252,12 +247,14 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
     }
 
     pub fn set_struct_body(&self, typ: Struct<'gcc>, fields: &[Type<'gcc>], packed: bool) {
-        let fields: Vec<_> = fields.iter().enumerate()
-            .map(|(index, field)| self.context.new_field(None, *field, &format!("field_{}", index)))
+        let fields: Vec<_> = fields
+            .iter()
+            .enumerate()
+            .map(|(index, field)| self.context.new_field(None, *field, format!("field_{}", index)))
             .collect();
         typ.set_fields(None, &fields);
         if packed {
-            #[cfg(feature="master")]
+            #[cfg(feature = "master")]
             typ.as_type().set_packed();
         }
     }
@@ -267,7 +264,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
     }
 }
 
-pub fn struct_fields<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout<'tcx>) -> (Vec<Type<'gcc>>, bool) {
+pub fn struct_fields<'gcc, 'tcx>(
+    cx: &CodegenCx<'gcc, 'tcx>,
+    layout: TyAndLayout<'tcx>,
+) -> (Vec<Type<'gcc>>, bool) {
     let field_count = layout.fields.count();
 
     let mut packed = false;
@@ -275,7 +275,7 @@ pub fn struct_fields<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout
     let mut prev_effective_align = layout.align.abi;
     let mut result: Vec<_> = Vec::with_capacity(1 + field_count * 2);
     for i in layout.fields.index_by_increasing_offset() {
-        let target_offset = layout.fields.offset(i as usize);
+        let target_offset = layout.fields.offset(i);
         let field = layout.field(cx, i);
         let effective_field_align =
             layout.align.abi.min(field.align.abi).restrict_for_offset(target_offset);
@@ -305,5 +305,4 @@ pub fn struct_fields<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout
     (result, packed)
 }
 
-impl<'gcc, 'tcx> TypeMembershipMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
-}
+impl<'gcc, 'tcx> TypeMembershipMethods<'tcx> for CodegenCx<'gcc, 'tcx> {}
diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs
index 5a9212762b7..8f9bfbbd18f 100644
--- a/compiler/rustc_codegen_gcc/src/type_of.rs
+++ b/compiler/rustc_codegen_gcc/src/type_of.rs
@@ -1,13 +1,16 @@
 use std::fmt::Write;
 
-use gccjit::{Struct, Type};
 use crate::rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods};
+use gccjit::{Struct, Type};
 use rustc_middle::bug;
-use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_target::abi::{self, Abi, Align, F16, F128, F32, F64, FieldsShape, Int, Integer, Pointer, PointeeInfo, Size, TyAbiInterface, Variants};
+use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 use rustc_target::abi::call::{CastTarget, FnAbi, Reg};
+use rustc_target::abi::{
+    self, Abi, Align, FieldsShape, Int, Integer, PointeeInfo, Pointer, Size, TyAbiInterface,
+    Variants, F128, F16, F32, F64,
+};
 
 use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType};
 use crate::context::CodegenCx;
@@ -25,7 +28,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         }
     }
 
-    #[cfg(feature="master")]
+    #[cfg(feature = "master")]
     pub fn type_int_from_ty(&self, t: ty::IntTy) -> Type<'gcc> {
         match t {
             ty::IntTy::Isize => self.type_isize(),
@@ -37,7 +40,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
         }
     }
 
-    #[cfg(feature="master")]
+    #[cfg(feature = "master")]
     pub fn type_uint_from_ty(&self, t: ty::UintTy) -> Type<'gcc> {
         match t {
             ty::UintTy::Usize => self.type_isize(),
@@ -56,7 +59,11 @@ impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
     }
 }
 
-fn uncached_gcc_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout<'tcx>, defer: &mut Option<(Struct<'gcc>, TyAndLayout<'tcx>)>) -> Type<'gcc> {
+fn uncached_gcc_type<'gcc, 'tcx>(
+    cx: &CodegenCx<'gcc, 'tcx>,
+    layout: TyAndLayout<'tcx>,
+    defer: &mut Option<(Struct<'gcc>, TyAndLayout<'tcx>)>,
+) -> Type<'gcc> {
     match layout.abi {
         Abi::Scalar(_) => bug!("handled elsewhere"),
         Abi::Vector { ref element, count } => {
@@ -70,7 +77,7 @@ fn uncached_gcc_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout
                     element
                 };
             return cx.context.new_vector_type(element, count);
-        },
+        }
         Abi::ScalarPair(..) => {
             return cx.type_struct(
                 &[
@@ -87,7 +94,12 @@ fn uncached_gcc_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout
         // FIXME(eddyb) producing readable type names for trait objects can result
         // in problematically distinct types due to HRTB and subtyping (see #47638).
         // ty::Dynamic(..) |
-        ty::Adt(..) | ty::Closure(..) | ty::CoroutineClosure(..) | ty::Foreign(..) | ty::Coroutine(..) | ty::Str
+        ty::Adt(..)
+        | ty::Closure(..)
+        | ty::CoroutineClosure(..)
+        | ty::Foreign(..)
+        | ty::Coroutine(..)
+        | ty::Str
             if !cx.sess().fewer_names() =>
         {
             let mut name = with_no_trimmed_paths!(layout.ty.to_string());
@@ -125,22 +137,21 @@ fn uncached_gcc_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, layout: TyAndLayout
                     let gcc_type = cx.type_named_struct(name);
                     cx.set_struct_body(gcc_type, &[fill], packed);
                     gcc_type.as_type()
-                },
+                }
             }
         }
         FieldsShape::Array { count, .. } => cx.type_array(layout.field(cx, 0).gcc_type(cx), count),
-        FieldsShape::Arbitrary { .. } =>
-            match name {
-                None => {
-                    let (gcc_fields, packed) = struct_fields(cx, layout);
-                    cx.type_struct(&gcc_fields, packed)
-                },
-                Some(ref name) => {
-                    let gcc_type = cx.type_named_struct(name);
-                    *defer = Some((gcc_type, layout));
-                    gcc_type.as_type()
-                },
-            },
+        FieldsShape::Arbitrary { .. } => match name {
+            None => {
+                let (gcc_fields, packed) = struct_fields(cx, layout);
+                cx.type_struct(&gcc_fields, packed)
+            }
+            Some(ref name) => {
+                let gcc_type = cx.type_named_struct(name);
+                *defer = Some((gcc_type, layout));
+                gcc_type.as_type()
+            }
+        },
     }
 }
 
@@ -149,9 +160,22 @@ pub trait LayoutGccExt<'tcx> {
     fn is_gcc_scalar_pair(&self) -> bool;
     fn gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>;
     fn immediate_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>) -> Type<'gcc>;
-    fn scalar_gcc_type_at<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, scalar: &abi::Scalar, offset: Size) -> Type<'gcc>;
-    fn scalar_pair_element_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, index: usize) -> Type<'gcc>;
-    fn pointee_info_at<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, offset: Size) -> Option<PointeeInfo>;
+    fn scalar_gcc_type_at<'gcc>(
+        &self,
+        cx: &CodegenCx<'gcc, 'tcx>,
+        scalar: &abi::Scalar,
+        offset: Size,
+    ) -> Type<'gcc>;
+    fn scalar_pair_element_gcc_type<'gcc>(
+        &self,
+        cx: &CodegenCx<'gcc, 'tcx>,
+        index: usize,
+    ) -> Type<'gcc>;
+    fn pointee_info_at<'gcc>(
+        &self,
+        cx: &CodegenCx<'gcc, 'tcx>,
+        offset: Size,
+    ) -> Option<PointeeInfo>;
 }
 
 impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
@@ -191,24 +215,24 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
             if let Some(&ty) = cx.scalar_types.borrow().get(&self.ty) {
                 return ty;
             }
-            let ty =
-                match *self.ty.kind() {
-                    // NOTE: we cannot remove this match like in the LLVM codegen because the call
-                    // to fn_ptr_backend_type handle the on-stack attribute.
-                    // TODO(antoyo): find a less hackish way to hande the on-stack attribute.
-                    ty::FnPtr(sig) => cx.fn_ptr_backend_type(&cx.fn_abi_of_fn_ptr(sig, ty::List::empty())),
-                    _ => self.scalar_gcc_type_at(cx, scalar, Size::ZERO),
-                };
+            let ty = match *self.ty.kind() {
+                // NOTE: we cannot remove this match like in the LLVM codegen because the call
+                // to fn_ptr_backend_type handle the on-stack attribute.
+                // TODO(antoyo): find a less hackish way to hande the on-stack attribute.
+                ty::FnPtr(sig) => {
+                    cx.fn_ptr_backend_type(&cx.fn_abi_of_fn_ptr(sig, ty::List::empty()))
+                }
+                _ => self.scalar_gcc_type_at(cx, scalar, Size::ZERO),
+            };
             cx.scalar_types.borrow_mut().insert(self.ty, ty);
             return ty;
         }
 
         // Check the cache.
-        let variant_index =
-            match self.variants {
-                Variants::Single { index } => Some(index),
-                _ => None,
-            };
+        let variant_index = match self.variants {
+            Variants::Single { index } => Some(index),
+            _ => None,
+        };
         let cached_type = cx.types.borrow().get(&(self.ty, variant_index)).cloned();
         if let Some(ty) = cached_type {
             return ty;
@@ -221,17 +245,15 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
         let normal_ty = cx.tcx.erase_regions(self.ty);
 
         let mut defer = None;
-        let ty =
-            if self.ty != normal_ty {
-                let mut layout = cx.layout_of(normal_ty);
-                if let Some(v) = variant_index {
-                    layout = layout.for_variant(cx, v);
-                }
-                layout.gcc_type(cx)
+        let ty = if self.ty != normal_ty {
+            let mut layout = cx.layout_of(normal_ty);
+            if let Some(v) = variant_index {
+                layout = layout.for_variant(cx, v);
             }
-            else {
-                uncached_gcc_type(cx, *self, &mut defer)
-            };
+            layout.gcc_type(cx)
+        } else {
+            uncached_gcc_type(cx, *self, &mut defer)
+        };
 
         cx.types.borrow_mut().insert((self.ty, variant_index), ty);
 
@@ -252,7 +274,12 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
         self.gcc_type(cx)
     }
 
-    fn scalar_gcc_type_at<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, scalar: &abi::Scalar, offset: Size) -> Type<'gcc> {
+    fn scalar_gcc_type_at<'gcc>(
+        &self,
+        cx: &CodegenCx<'gcc, 'tcx>,
+        scalar: &abi::Scalar,
+        offset: Size,
+    ) -> Type<'gcc> {
         match scalar.primitive() {
             Int(i, true) => cx.type_from_integer(i),
             Int(i, false) => cx.type_from_unsigned_integer(i),
@@ -262,19 +289,21 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
             F128 => cx.type_f128(),
             Pointer(address_space) => {
                 // If we know the alignment, pick something better than i8.
-                let pointee =
-                    if let Some(pointee) = self.pointee_info_at(cx, offset) {
-                        cx.type_pointee_for_align(pointee.align)
-                    }
-                    else {
-                        cx.type_i8()
-                    };
+                let pointee = if let Some(pointee) = self.pointee_info_at(cx, offset) {
+                    cx.type_pointee_for_align(pointee.align)
+                } else {
+                    cx.type_i8()
+                };
                 cx.type_ptr_to_ext(pointee, address_space)
             }
         }
     }
 
-    fn scalar_pair_element_gcc_type<'gcc>(&self, cx: &CodegenCx<'gcc, 'tcx>, index: usize) -> Type<'gcc> {
+    fn scalar_pair_element_gcc_type<'gcc>(
+        &self,
+        cx: &CodegenCx<'gcc, 'tcx>,
+        index: usize,
+    ) -> Type<'gcc> {
         // This must produce the same result for `repr(transparent)` wrappers as for the inner type!
         // In other words, this should generally not look at the type at all, but only at the
         // layout.
@@ -295,13 +324,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
             return cx.type_i1();
         }
 
-        let offset =
-            if index == 0 {
-                Size::ZERO
-            }
-            else {
-                a.size(cx).align_to(b.align(cx).abi)
-            };
+        let offset = if index == 0 { Size::ZERO } else { a.size(cx).align_to(b.align(cx).abi) };
         self.scalar_gcc_type_at(cx, scalar, offset)
     }
 
@@ -334,7 +357,12 @@ impl<'gcc, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         layout.is_gcc_scalar_pair()
     }
 
-    fn scalar_pair_element_backend_type(&self, layout: TyAndLayout<'tcx>, index: usize, _immediate: bool) -> Type<'gcc> {
+    fn scalar_pair_element_backend_type(
+        &self,
+        layout: TyAndLayout<'tcx>,
+        index: usize,
+        _immediate: bool,
+    ) -> Type<'gcc> {
         layout.scalar_pair_element_gcc_type(self, index)
     }
 
@@ -352,12 +380,7 @@ impl<'gcc, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
 
     fn fn_decl_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Type<'gcc> {
         // FIXME(antoyo): Should we do something with `FnAbiGcc::fn_attributes`?
-        let FnAbiGcc {
-            return_type,
-            arguments_type,
-            is_c_variadic,
-            ..
-        } = fn_abi.gcc_type(self);
+        let FnAbiGcc { return_type, arguments_type, is_c_variadic, .. } = fn_abi.gcc_type(self);
         self.context.new_function_pointer_type(None, return_type, &arguments_type, is_c_variadic)
     }
 }
diff --git a/compiler/rustc_codegen_gcc/test.sh b/compiler/rustc_codegen_gcc/test.sh
deleted file mode 100755
index e896237a1ea..00000000000
--- a/compiler/rustc_codegen_gcc/test.sh
+++ /dev/null
@@ -1,479 +0,0 @@
-#!/usr/bin/env bash
-
-# TODO(antoyo): rewrite to cargo-make (or just) or something like that to only rebuild the sysroot when needed?
-
-set -e
-#set -x
-
-flags=
-gcc_master_branch=1
-channel="debug"
-funcs=()
-build_only=0
-nb_parts=0
-current_part=0
-use_system_gcc=0
-use_backend=0
-cargo_target_dir=""
-
-export CHANNEL='debug'
-
-while [[ $# -gt 0 ]]; do
-    case $1 in
-        --release)
-            codegen_channel=release
-            channel="release"
-            export CHANNEL='release'
-            shift
-            ;;
-        --release-sysroot)
-            sysroot_channel="--release"
-            shift
-            ;;
-        --no-default-features)
-            gcc_master_branch=0
-            flags="$flags --no-default-features"
-            shift
-            ;;
-        --features)
-            shift
-            flags="$flags --features $1"
-            shift
-            ;;
-        "--test-rustc")
-            funcs+=(test_rustc)
-            shift
-            ;;
-        "--test-successful-rustc")
-            funcs+=(test_successful_rustc)
-            shift
-            ;;
-        "--test-failing-rustc")
-            funcs+=(test_failing_rustc)
-            shift
-            ;;
-
-        "--test-libcore")
-            funcs+=(test_libcore)
-            shift
-            ;;
-
-        "--clean-ui-tests")
-            funcs+=(clean_ui_tests)
-            shift
-            ;;
-        "--clean")
-            funcs+=(clean)
-            shift
-            ;;
-
-        "--std-tests")
-            funcs+=(std_tests)
-            shift
-            ;;
-
-        "--asm-tests")
-            funcs+=(asm_tests)
-            shift
-            ;;
-
-        "--extended-tests")
-            funcs+=(extended_sysroot_tests)
-            shift
-            ;;
-        "--extended-rand-tests")
-            funcs+=(extended_rand_tests)
-            shift
-            ;;
-        "--extended-regex-example-tests")
-            funcs+=(extended_regex_example_tests)
-            shift
-            ;;
-        "--extended-regex-tests")
-            funcs+=(extended_regex_tests)
-            shift
-            ;;
-
-        "--mini-tests")
-            funcs+=(mini_tests)
-            shift
-            ;;
-
-        "--build-sysroot")
-            funcs+=(build_sysroot)
-            shift
-            ;;
-        "--build")
-            build_only=1
-            shift
-            ;;
-        "--use-system-gcc")
-            use_system_gcc=1
-            shift
-            ;;
-        "--use-backend")
-            use_backend=1
-            shift
-            export BUILTIN_BACKEND=$1
-            shift
-            ;;
-        "--out-dir")
-            shift
-            export CARGO_TARGET_DIR=$1
-            cargo_target_dir=$1
-            shift
-            ;;
-        "--nb-parts")
-            shift
-            nb_parts=$1
-            shift
-            ;;
-        "--current-part")
-            shift
-            current_part=$1
-            shift
-            ;;
-        *)
-            echo "Unknown option $1"
-            exit 1
-            ;;
-    esac
-done
-
-if [ -f ./gcc_path ]; then
-    export GCC_PATH=$(cat gcc_path)
-elif (( $use_system_gcc == 1 )); then
-    echo 'Using system GCC'
-else
-    echo 'Please put the path to your custom build of libgccjit in the file `gcc_path`, see Readme.md for details'
-    exit 1
-fi
-
-export LD_LIBRARY_PATH="$GCC_PATH"
-export LIBRARY_PATH="$GCC_PATH"
-
-if [[ $use_backend == 0 ]]; then
-    if [[ $channel == "release" ]]; then
-        CARGO_INCREMENTAL=1 cargo rustc --release $flags
-    else
-        echo $LD_LIBRARY_PATH
-        cargo rustc $flags
-    fi
-fi
-
-if (( $build_only == 1 )); then
-    echo "Since it's 'build-only', exiting..."
-    exit
-fi
-
-source config.sh
-
-function clean() {
-    rm -r $cargo_target_dir || true
-    mkdir -p $cargo_target_dir/gccjit
-}
-
-function mini_tests() {
-    echo "[BUILD] mini_core"
-    crate_types="lib,dylib"
-
-    if [[ "$HOST_TRIPLE" != "$TARGET_TRIPLE" ]]; then
-        crate_types="lib"
-    fi
-
-    $RUST_CMD example/mini_core.rs --crate-name mini_core --crate-type $crate_types --target $TARGET_TRIPLE
-
-    echo "[BUILD] example"
-    $RUST_CMD example/example.rs --crate-type lib --target $TARGET_TRIPLE
-
-    echo "[AOT] mini_core_hello_world"
-    $RUST_CMD example/mini_core_hello_world.rs --crate-name mini_core_hello_world --crate-type bin -g --target $TARGET_TRIPLE
-    $RUN_WRAPPER $cargo_target_dir/mini_core_hello_world abc bcd
-}
-
-function build_sysroot() {
-    echo "[BUILD] sysroot"
-    time ./build_sysroot/build_sysroot.sh $sysroot_channel
-}
-
-# TODO(GuillaumeGomez): when rewriting in Rust, refactor with the code in tests/lang_tests_common.rs if possible.
-function run_in_vm() {
-    vm_parent_dir=${CG_GCC_VM_DIR:-$(pwd)}
-    vm_dir=vm
-    exe=$1
-    exe_filename=$(basename $exe)
-    vm_home_dir=$vm_parent_dir/$vm_dir/home
-    vm_exe_path=$vm_home_dir/$exe_filename
-    inside_vm_exe_path=/home/$exe_filename
-    sudo cp $exe $vm_exe_path
-
-    shift
-    pushd $vm_parent_dir
-    sudo chroot $vm_dir qemu-m68k-static $inside_vm_exe_path $@
-    popd
-}
-
-function std_tests() {
-    echo "[AOT] arbitrary_self_types_pointers_and_wrappers"
-    $RUST_CMD example/arbitrary_self_types_pointers_and_wrappers.rs --crate-name arbitrary_self_types_pointers_and_wrappers --crate-type bin --target $TARGET_TRIPLE
-    $RUN_WRAPPER $cargo_target_dir/arbitrary_self_types_pointers_and_wrappers
-
-    echo "[AOT] alloc_system"
-    $RUST_CMD example/alloc_system.rs --crate-type lib --target "$TARGET_TRIPLE"
-
-    # FIXME: doesn't work on m68k.
-    if [[ "$HOST_TRIPLE" == "$TARGET_TRIPLE" ]]; then
-        echo "[AOT] alloc_example"
-        $RUST_CMD example/alloc_example.rs --crate-type bin --target $TARGET_TRIPLE
-        $RUN_WRAPPER $cargo_target_dir/alloc_example
-    fi
-
-    echo "[AOT] dst_field_align"
-    # FIXME(antoyo): Re-add -Zmir-opt-level=2 once rust-lang/rust#67529 is fixed.
-    $RUST_CMD example/dst-field-align.rs --crate-name dst_field_align --crate-type bin --target $TARGET_TRIPLE
-    $RUN_WRAPPER $cargo_target_dir/dst_field_align || (echo $?; false)
-
-    echo "[AOT] std_example"
-    std_flags="--cfg feature=\"master\""
-    if (( $gcc_master_branch == 0 )); then
-        std_flags=""
-    fi
-    $RUST_CMD example/std_example.rs --crate-type bin --target $TARGET_TRIPLE $std_flags
-    $RUN_WRAPPER $cargo_target_dir/std_example --target $TARGET_TRIPLE
-
-    echo "[AOT] subslice-patterns-const-eval"
-    $RUST_CMD example/subslice-patterns-const-eval.rs --crate-type bin $TEST_FLAGS --target $TARGET_TRIPLE
-    $RUN_WRAPPER $cargo_target_dir/subslice-patterns-const-eval
-
-    echo "[AOT] track-caller-attribute"
-    $RUST_CMD example/track-caller-attribute.rs --crate-type bin $TEST_FLAGS --target $TARGET_TRIPLE
-    $RUN_WRAPPER $cargo_target_dir/track-caller-attribute
-
-    echo "[BUILD] mod_bench"
-    $RUST_CMD example/mod_bench.rs --crate-type bin --target $TARGET_TRIPLE
-}
-
-function setup_rustc() {
-    rust_toolchain=$(cat rust-toolchain | grep channel | sed 's/channel = "\(.*\)"/\1/')
-
-    git clone https://github.com/rust-lang/rust.git || true
-    cd rust
-    git fetch
-    git checkout $($RUSTC -V | cut -d' ' -f3 | tr -d '(')
-    export RUSTFLAGS=
-
-    rm config.toml || true
-
-    cat > config.toml <<EOF
-change-id = 115898
-
-[rust]
-codegen-backends = []
-deny-warnings = false
-verbose-tests = true
-
-[build]
-cargo = "$(rustup which cargo)"
-local-rebuild = true
-rustc = "$HOME/.rustup/toolchains/$rust_toolchain-$HOST_TRIPLE/bin/rustc"
-
-[target.x86_64-unknown-linux-gnu]
-llvm-filecheck = "`which FileCheck-10 || which FileCheck-11 || which FileCheck-12 || which FileCheck-13 || which FileCheck-14`"
-
-[llvm]
-download-ci-llvm = false
-EOF
-
-    $RUSTC -V | cut -d' ' -f3 | tr -d '('
-    git checkout $($RUSTC -V | cut -d' ' -f3 | tr -d '(') tests
-}
-
-function asm_tests() {
-    setup_rustc
-
-    echo "[TEST] rustc asm test suite"
-    RUSTC_ARGS="-Zpanic-abort-tests -Csymbol-mangling-version=v0 -Zcodegen-backend="$(pwd)"/../target/"$CHANNEL"/librustc_codegen_gcc."$dylib_ext" --sysroot "$(pwd)"/../build_sysroot/sysroot -Cpanic=abort"
-    COMPILETEST_FORCE_STAGE0=1 ./x.py test --run always --stage 0 tests/assembly/asm --rustc-args "$RUSTC_ARGS"
-}
-
-# FIXME(antoyo): linker gives multiple definitions error on Linux
-#echo "[BUILD] sysroot in release mode"
-#./build_sysroot/build_sysroot.sh --release
-
-function test_libcore() {
-    pushd build_sysroot/sysroot_src/library/core/tests
-    echo "[TEST] libcore"
-    rm -r ./target || true
-    ../../../../../cargo.sh test
-    popd
-}
-
-#echo
-#echo "[BENCH COMPILE] mod_bench"
-
-#COMPILE_MOD_BENCH_INLINE="$RUSTC example/mod_bench.rs --crate-type bin -Zmir-opt-level=3 -O --crate-name mod_bench_inline"
-#COMPILE_MOD_BENCH_LLVM_0="rustc example/mod_bench.rs --crate-type bin -Copt-level=0 -o $cargo_target_dir/mod_bench_llvm_0 -Cpanic=abort"
-#COMPILE_MOD_BENCH_LLVM_1="rustc example/mod_bench.rs --crate-type bin -Copt-level=1 -o $cargo_target_dir/mod_bench_llvm_1 -Cpanic=abort"
-#COMPILE_MOD_BENCH_LLVM_2="rustc example/mod_bench.rs --crate-type bin -Copt-level=2 -o $cargo_target_dir/mod_bench_llvm_2 -Cpanic=abort"
-#COMPILE_MOD_BENCH_LLVM_3="rustc example/mod_bench.rs --crate-type bin -Copt-level=3 -o $cargo_target_dir/mod_bench_llvm_3 -Cpanic=abort"
-
-## Use 100 runs, because a single compilations doesn't take more than ~150ms, so it isn't very slow
-#hyperfine --runs ${COMPILE_RUNS:-100} "$COMPILE_MOD_BENCH_INLINE" "$COMPILE_MOD_BENCH_LLVM_0" "$COMPILE_MOD_BENCH_LLVM_1" "$COMPILE_MOD_BENCH_LLVM_2" "$COMPILE_MOD_BENCH_LLVM_3"
-
-#echo
-#echo "[BENCH RUN] mod_bench"
-#hyperfine --runs ${RUN_RUNS:-10} $cargo_target_dir/mod_bench{,_inline} $cargo_target_dir/mod_bench_llvm_*
-
-function extended_rand_tests() {
-    if (( $gcc_master_branch == 0 )); then
-        return
-    fi
-
-    pushd rand
-    cargo clean
-    echo "[TEST] rust-random/rand"
-    ../cargo.sh test --workspace
-    popd
-}
-
-function extended_regex_example_tests() {
-    if (( $gcc_master_branch == 0 )); then
-        return
-    fi
-
-    pushd regex
-    echo "[TEST] rust-lang/regex example shootout-regex-dna"
-    cargo clean
-    export CG_RUSTFLAGS="--cap-lints warn" # newer aho_corasick versions throw a deprecation warning
-    # Make sure `[codegen mono items] start` doesn't poison the diff
-    ../cargo.sh build --example shootout-regex-dna
-    cat examples/regexdna-input.txt \
-        | ../cargo.sh run --example shootout-regex-dna \
-        | grep -v "Spawned thread" > res.txt
-    diff -u res.txt examples/regexdna-output.txt
-    popd
-}
-
-function extended_regex_tests() {
-    if (( $gcc_master_branch == 0 )); then
-        return
-    fi
-
-    pushd regex
-    echo "[TEST] rust-lang/regex tests"
-    export CG_RUSTFLAGS="--cap-lints warn" # newer aho_corasick versions throw a deprecation warning
-    ../cargo.sh test --tests -- --exclude-should-panic --test-threads 1 -Zunstable-options -q
-    popd
-}
-
-function extended_sysroot_tests() {
-    #pushd simple-raytracer
-    #echo "[BENCH COMPILE] ebobby/simple-raytracer"
-    #hyperfine --runs "${RUN_RUNS:-10}" --warmup 1 --prepare "cargo clean" \
-    #"RUSTC=rustc RUSTFLAGS='' cargo build" \
-    #"../cargo.sh build"
-
-    #echo "[BENCH RUN] ebobby/simple-raytracer"
-    #cp ./target/debug/main ./raytracer_cg_gcc
-    #hyperfine --runs "${RUN_RUNS:-10}" ./raytracer_cg_llvm ./raytracer_cg_gcc
-    #popd
-
-    extended_rand_tests
-    extended_regex_example_tests
-    extended_regex_tests
-}
-
-function test_rustc() {
-    echo
-    echo "[TEST] rust-lang/rust"
-
-    setup_rustc
-
-    for test in $(rg -i --files-with-matches "//(\[\w+\])?~|// error-pattern:|// build-fail|// run-fail|-Cllvm-args" tests/ui); do
-      rm $test
-    done
-    rm tests/ui/consts/const_cmp_type_id.rs
-    rm tests/ui/consts/issue-73976-monomorphic.rs
-
-    git checkout -- tests/ui/issues/auxiliary/issue-3136-a.rs # contains //~ERROR, but shouldn't be removed
-
-    rm -r tests/ui/{abi*,extern/,unsized-locals/,proc-macro/,threads-sendsync/,borrowck/,test*,consts/issue-miri-1910.rs} || true
-    rm tests/ui/mir/mir_heavy_promoted.rs # this test is oom-killed in the CI.
-    # Tests generating errors.
-    rm tests/ui/consts/issue-94675.rs
-    for test in $(rg --files-with-matches "thread" tests/ui); do
-      rm $test
-    done
-    git checkout tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice.rs
-    git checkout tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice2.rs
-    git checkout tests/ui/macros/rfc-2011-nicer-assert-messages/auxiliary/common.rs
-    git checkout tests/ui/imports/ambiguous-1.rs
-    git checkout tests/ui/imports/ambiguous-4-extern.rs
-    git checkout tests/ui/entry-point/auxiliary/bad_main_functions.rs
-
-    RUSTC_ARGS="$TEST_FLAGS -Csymbol-mangling-version=v0 -Zcodegen-backend="$(pwd)"/../target/"$CHANNEL"/librustc_codegen_gcc."$dylib_ext" --sysroot "$(pwd)"/../build_sysroot/sysroot"
-
-    if [ $# -eq 0 ]; then
-        # No argument supplied to the function. Doing nothing.
-        echo "No argument provided. Keeping all UI tests"
-    elif [ $1 = "0" ]; then
-        # Removing the failing tests.
-        xargs -a ../failing-ui-tests.txt -d'\n' rm
-    else
-        # Removing all tests.
-        find tests/ui -type f -name '*.rs' -not -path '*/auxiliary/*' -delete
-        # Putting back only the failing ones.
-        xargs -a ../failing-ui-tests.txt -d'\n' git checkout --
-    fi
-
-    if [ $nb_parts -gt 0 ]; then
-        echo "Splitting ui_test into $nb_parts parts (and running part $current_part)"
-        find tests/ui -type f -name '*.rs' -not -path "*/auxiliary/*" > ui_tests
-        # To ensure it'll be always the same sub files, we sort the content.
-        sort ui_tests -o ui_tests
-        count=$((`wc -l < ui_tests` / $nb_parts))
-        # We increment the number of tests by one because if this is an odd number, we would skip
-        # one test.
-        count=$((count + 1))
-        split -d -l $count -a 1 ui_tests ui_tests.split
-        # Removing all tests.
-        find tests/ui -type f -name '*.rs' -not -path "*/auxiliary/*" -delete
-        # Putting back only the ones we want to test.
-        xargs -a "ui_tests.split$current_part" -d'\n' git checkout --
-    fi
-
-    echo "[TEST] rustc test suite"
-    COMPILETEST_FORCE_STAGE0=1 ./x.py test --run always --stage 0 tests/ui/ --rustc-args "$RUSTC_ARGS" # --target $TARGET_TRIPLE
-}
-
-function test_failing_rustc() {
-    test_rustc "1"
-}
-
-function test_successful_rustc() {
-    test_rustc "0"
-}
-
-function clean_ui_tests() {
-    find rust/build/x86_64-unknown-linux-gnu/test/ui/ -name stamp -delete
-}
-
-function all() {
-    clean
-    mini_tests
-    build_sysroot
-    std_tests
-    #asm_tests
-    test_libcore
-    extended_sysroot_tests
-    test_rustc
-}
-
-if [ ${#funcs[@]} -eq 0 ]; then
-    echo "No command passed, running '--all'..."
-    all
-else
-    for t in ${funcs[@]}; do
-        $t
-    done
-fi
diff --git a/compiler/rustc_codegen_gcc/failing-lto-tests.txt b/compiler/rustc_codegen_gcc/tests/failing-lto-tests.txt
index 2e0b6134070..6e1ed99c6f7 100644
--- a/compiler/rustc_codegen_gcc/failing-lto-tests.txt
+++ b/compiler/rustc_codegen_gcc/tests/failing-lto-tests.txt
@@ -1,6 +1,6 @@
 tests/ui/lint/unsafe_code/forge_unsafe_block.rs
 tests/ui/lint/unused-qualification-in-derive-expansion.rs
-tests/ui/macro-quote-test.rs
+tests/ui/macros/macro-quote-test.rs
 tests/ui/macros/proc_macro.rs
 tests/ui/panic-runtime/lto-unwind.rs
 tests/ui/resolve/derive-macro-1.rs
@@ -21,3 +21,12 @@ tests/ui/fmt/format-args-capture-issue-106408.rs
 tests/ui/fmt/indoc-issue-106408.rs
 tests/ui/hygiene/issue-77523-def-site-async-await.rs
 tests/ui/inherent-impls-overlap-check/no-overlap.rs
+tests/ui/enum-discriminant/issue-46519.rs
+tests/ui/issues/issue-45731.rs
+tests/ui/lint/test-allow-dead-extern-static-no-warning.rs
+tests/ui/macros/macro-comma-behavior-rpass.rs
+tests/ui/macros/rfc-2011-nicer-assert-messages/assert-with-custom-errors-does-not-create-unnecessary-code.rs
+tests/ui/macros/rfc-2011-nicer-assert-messages/feature-gate-generic_assert.rs
+tests/ui/macros/stringify.rs
+tests/ui/reexport-test-harness-main.rs
+tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-in-test.rs
diff --git a/compiler/rustc_codegen_gcc/failing-non-lto-tests.txt b/compiler/rustc_codegen_gcc/tests/failing-non-lto-tests.txt
index 4fd60f2b8e4..384dfdc26fb 100644
--- a/compiler/rustc_codegen_gcc/failing-non-lto-tests.txt
+++ b/compiler/rustc_codegen_gcc/tests/failing-non-lto-tests.txt
@@ -5,7 +5,7 @@ tests/ui/lto/lto-many-codegen-units.rs
 tests/ui/lto/issue-100772.rs
 tests/ui/lto/lto-rustc-loads-linker-plugin.rs
 tests/ui/panic-runtime/lto-unwind.rs
-tests/ui/sanitize/issue-111184-coroutine-witness.rs
+tests/ui/sanitizer/issue-111184-cfi-coroutine-witness.rs
 tests/ui/sepcomp/sepcomp-lib-lto.rs
 tests/ui/lto/lto-opt-level-s.rs
 tests/ui/lto/lto-opt-level-z.rs
diff --git a/compiler/rustc_codegen_gcc/failing-ui-tests.txt b/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt
index 22044eabe96..d13562f8bb0 100644
--- a/compiler/rustc_codegen_gcc/failing-ui-tests.txt
+++ b/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt
@@ -13,7 +13,6 @@ tests/ui/sepcomp/sepcomp-extern.rs
 tests/ui/sepcomp/sepcomp-fns-backwards.rs
 tests/ui/sepcomp/sepcomp-fns.rs
 tests/ui/sepcomp/sepcomp-statics.rs
-tests/ui/simd/intrinsic/generic-arithmetic-pass.rs
 tests/ui/asm/x86_64/may_unwind.rs
 tests/ui/backtrace.rs
 tests/ui/catch-unwind-bang.rs
@@ -49,7 +48,6 @@ tests/ui/rfcs/rfc-1857-stabilize-drop-order/drop-order.rs
 tests/ui/rfcs/rfc-2091-track-caller/std-panic-locations.rs
 tests/ui/simd/issue-17170.rs
 tests/ui/simd/issue-39720.rs
-tests/ui/simd/issue-89193.rs
 tests/ui/statics/issue-91050-1.rs
 tests/ui/statics/issue-91050-2.rs
 tests/ui/alloc-error/default-alloc-error-hook.rs
@@ -57,7 +55,6 @@ tests/ui/coroutine/panic-safe.rs
 tests/ui/issues/issue-14875.rs
 tests/ui/issues/issue-29948.rs
 tests/ui/panics/nested_panic_caught.rs
-tests/ui/simd/intrinsic/generic-bswap-byte.rs
 tests/ui/const_prop/ice-issue-111353.rs
 tests/ui/process/println-with-broken-pipe.rs
 tests/ui/panic-runtime/lto-abort.rs
@@ -72,3 +69,8 @@ tests/ui/async-await/deep-futures-are-freeze.rs
 tests/ui/closures/capture-unsized-by-ref.rs
 tests/ui/coroutine/resume-after-return.rs
 tests/ui/macros/rfc-2011-nicer-assert-messages/all-expr-kinds.rs
+tests/ui/simd/masked-load-store.rs
+tests/ui/simd/repr_packed.rs
+tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs
+tests/ui/consts/try-operator.rs
+tests/ui/coroutine/unwind-abort-mix.rs
diff --git a/compiler/rustc_codegen_gcc/failing-ui-tests12.txt b/compiler/rustc_codegen_gcc/tests/failing-ui-tests12.txt
index 4af93939b06..1d9bdaa552c 100644
--- a/compiler/rustc_codegen_gcc/failing-ui-tests12.txt
+++ b/compiler/rustc_codegen_gcc/tests/failing-ui-tests12.txt
@@ -9,6 +9,7 @@ tests/ui/packed/packed-struct-vec.rs
 tests/ui/packed/packed-tuple-struct-layout.rs
 tests/ui/simd/array-type.rs
 tests/ui/simd/intrinsic/float-minmax-pass.rs
+tests/ui/simd/intrinsic/generic-arithmetic-pass.rs
 tests/ui/simd/intrinsic/generic-arithmetic-saturating-pass.rs
 tests/ui/simd/intrinsic/generic-as.rs
 tests/ui/simd/intrinsic/generic-cast-pass.rs
@@ -32,11 +33,16 @@ tests/ui/coroutine/size-moved-locals.rs
 tests/ui/macros/rfc-2011-nicer-assert-messages/all-not-available-cases.rs
 tests/ui/simd/intrinsic/generic-gather-pass.rs
 tests/ui/simd/issue-85915-simd-ptrs.rs
+tests/ui/simd/issue-89193.rs
 tests/ui/issues/issue-68010-large-zst-consts.rs
 tests/ui/rust-2018/proc-macro-crate-in-paths.rs
 tests/ui/target-feature/missing-plusminus.rs
 tests/ui/sse2.rs
 tests/ui/codegen/issue-79865-llvm-miscompile.rs
-tests/ui/intrinsics/intrinsics-integer.rs
 tests/ui/std-backtrace.rs
 tests/ui/mir/alignment/packed.rs
+tests/ui/intrinsics/intrinsics-integer.rs
+tests/ui/asm/x86_64/evex512-implicit-feature.rs
+tests/ui/packed/dyn-trait.rs
+tests/ui/packed/issue-118537-field-offset-ice.rs
+tests/ui/stable-mir-print/basic_function.rs
diff --git a/compiler/rustc_codegen_gcc/tests/lang_tests_common.rs b/compiler/rustc_codegen_gcc/tests/lang_tests_common.rs
index af0133aad46..d321ffc8ff5 100644
--- a/compiler/rustc_codegen_gcc/tests/lang_tests_common.rs
+++ b/compiler/rustc_codegen_gcc/tests/lang_tests_common.rs
@@ -5,6 +5,7 @@ use std::{
     process::Command,
 };
 
+use boml::Toml;
 use lang_tester::LangTester;
 use tempfile::TempDir;
 
@@ -20,20 +21,32 @@ pub fn main_inner(profile: Profile) {
     let tempdir = TempDir::new().expect("temp dir");
     let current_dir = current_dir().expect("current dir");
     let current_dir = current_dir.to_str().expect("current dir").to_string();
-    let gcc_path = include_str!("../gcc_path");
-    let gcc_path = gcc_path.trim();
+    let toml = Toml::parse(include_str!("../config.toml")).expect("Failed to parse `config.toml`");
+    let gcc_path = if let Ok(gcc_path) = toml.get_string("gcc-path") {
+        PathBuf::from(gcc_path.to_string())
+    } else {
+        // then we try to retrieve it from the `target` folder.
+        let commit = include_str!("../libgccjit.version").trim();
+        Path::new("build/libgccjit").join(commit)
+    };
+
+    let gcc_path = Path::new(&gcc_path)
+        .canonicalize()
+        .expect("failed to get absolute path of `gcc-path`")
+        .display()
+        .to_string();
     env::set_var("LD_LIBRARY_PATH", gcc_path);
 
-    fn rust_filter(filename: &Path) -> bool {
-        filename.extension().expect("extension").to_str().expect("to_str") == "rs"
+    fn rust_filter(path: &Path) -> bool {
+        path.is_file() && path.extension().expect("extension").to_str().expect("to_str") == "rs"
     }
 
-    #[cfg(feature="master")]
+    #[cfg(feature = "master")]
     fn filter(filename: &Path) -> bool {
         rust_filter(filename)
     }
 
-    #[cfg(not(feature="master"))]
+    #[cfg(not(feature = "master"))]
     fn filter(filename: &Path) -> bool {
         if let Some(filename) = filename.to_str() {
             if filename.ends_with("gep.rs") {
@@ -45,16 +58,17 @@ pub fn main_inner(profile: Profile) {
 
     LangTester::new()
         .test_dir("tests/run")
-        .test_file_filter(filter)
-        .test_extract(|source| {
-            let lines =
-                source.lines()
-                    .skip_while(|l| !l.starts_with("//"))
-                    .take_while(|l| l.starts_with("//"))
-                    .map(|l| &l[2..])
-                    .collect::<Vec<_>>()
-                    .join("\n");
-            Some(lines)
+        .test_path_filter(filter)
+        .test_extract(|path| {
+            let lines = std::fs::read_to_string(path)
+                .expect("read file")
+                .lines()
+                .skip_while(|l| !l.starts_with("//"))
+                .take_while(|l| l.starts_with("//"))
+                .map(|l| &l[2..])
+                .collect::<Vec<_>>()
+                .join("\n");
+            lines
         })
         .test_cmds(move |path| {
             // Test command 1: Compile `x.rs` into `tempdir/x`.
@@ -62,19 +76,22 @@ pub fn main_inner(profile: Profile) {
             exe.push(&tempdir);
             exe.push(path.file_stem().expect("file_stem"));
             let mut compiler = Command::new("rustc");
-            compiler.args(&[
+            compiler.args([
                 &format!("-Zcodegen-backend={}/target/debug/librustc_codegen_gcc.so", current_dir),
-                "--sysroot", &format!("{}/build_sysroot/sysroot/", current_dir),
+                "--sysroot",
+                &format!("{}/build_sysroot/sysroot/", current_dir),
                 "-Zno-parallel-llvm",
-                "-C", "link-arg=-lc",
-                "-o", exe.to_str().expect("to_str"),
+                "-C",
+                "link-arg=-lc",
+                "-o",
+                exe.to_str().expect("to_str"),
                 path.to_str().expect("to_str"),
             ]);
 
             // TODO(antoyo): find a way to send this via a cli argument.
             let test_target = std::env::var("CG_GCC_TEST_TARGET");
             if let Ok(ref target) = test_target {
-                compiler.args(&["--target", &target]);
+                compiler.args(["--target", target]);
                 let linker = format!("{}-gcc", target);
                 compiler.args(&[format!("-Clinker={}", linker)]);
                 let mut env_path = std::env::var("PATH").unwrap_or_default();
@@ -85,49 +102,38 @@ pub fn main_inner(profile: Profile) {
 
             if let Some(flags) = option_env!("TEST_FLAGS") {
                 for flag in flags.split_whitespace() {
-                    compiler.arg(&flag);
+                    compiler.arg(flag);
                 }
             }
             match profile {
                 Profile::Debug => {}
                 Profile::Release => {
-                    compiler.args(&[
-                        "-C", "opt-level=3",
-                        "-C", "lto=no",
-                    ]);
+                    compiler.args(["-C", "opt-level=3", "-C", "lto=no"]);
                 }
             }
             // Test command 2: run `tempdir/x`.
             if test_target.is_ok() {
                 let vm_parent_dir = std::env::var("CG_GCC_VM_DIR")
-                    .map(|dir| PathBuf::from(dir))
+                    .map(PathBuf::from)
                     .unwrap_or_else(|_| std::env::current_dir().unwrap());
                 let vm_dir = "vm";
                 let exe_filename = exe.file_name().unwrap();
                 let vm_home_dir = vm_parent_dir.join(vm_dir).join("home");
                 let vm_exe_path = vm_home_dir.join(exe_filename);
                 // FIXME(antoyo): panicking here makes the test pass.
-                let inside_vm_exe_path = PathBuf::from("/home").join(&exe_filename);
+                let inside_vm_exe_path = PathBuf::from("/home").join(exe_filename);
                 let mut copy = Command::new("sudo");
                 copy.arg("cp");
-                copy.args(&[&exe, &vm_exe_path]);
+                copy.args([&exe, &vm_exe_path]);
 
                 let mut runtime = Command::new("sudo");
-                runtime.args(&["chroot", vm_dir, "qemu-m68k-static"]);
+                runtime.args(["chroot", vm_dir, "qemu-m68k-static"]);
                 runtime.arg(inside_vm_exe_path);
                 runtime.current_dir(vm_parent_dir);
-                vec![
-                    ("Compiler", compiler),
-                    ("Copy", copy),
-                    ("Run-time", runtime),
-                ]
-            }
-            else {
+                vec![("Compiler", compiler), ("Copy", copy), ("Run-time", runtime)]
+            } else {
                 let runtime = Command::new(exe);
-                vec![
-                    ("Compiler", compiler),
-                    ("Run-time", runtime),
-                ]
+                vec![("Compiler", compiler), ("Run-time", runtime)]
             }
         })
         .run();
diff --git a/compiler/rustc_codegen_gcc/y.sh b/compiler/rustc_codegen_gcc/y.sh
index 188109743e3..69d7917dd77 100755
--- a/compiler/rustc_codegen_gcc/y.sh
+++ b/compiler/rustc_codegen_gcc/y.sh
@@ -2,7 +2,7 @@
 
 set -e
 echo "[BUILD] build system" 1>&2
-cd build_system
+pushd $(dirname "$0")/build_system > /dev/null
 cargo build --release
-cd ..
-./build_system/target/release/y $@
+popd > /dev/null
+$(dirname "$0")/build_system/target/release/y $@
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index b5b4f894e4d..147939d3a52 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -424,7 +424,10 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
             PassMode::Indirect { attrs, meta_attrs: _, on_stack } => {
                 assert!(!on_stack);
                 let i = apply(attrs);
-                let sret = llvm::CreateStructRetAttr(cx.llcx, self.ret.layout.llvm_type(cx));
+                let sret = llvm::CreateStructRetAttr(
+                    cx.llcx,
+                    cx.type_array(cx.type_i8(), self.ret.layout.size.bytes()),
+                );
                 attributes::apply_to_llfn(llfn, llvm::AttributePlace::Argument(i), &[sret]);
             }
             PassMode::Cast { cast, pad_i32: _ } => {
@@ -437,7 +440,10 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
                 PassMode::Ignore => {}
                 PassMode::Indirect { attrs, meta_attrs: None, on_stack: true } => {
                     let i = apply(attrs);
-                    let byval = llvm::CreateByValAttr(cx.llcx, arg.layout.llvm_type(cx));
+                    let byval = llvm::CreateByValAttr(
+                        cx.llcx,
+                        cx.type_array(cx.type_i8(), arg.layout.size.bytes()),
+                    );
                     attributes::apply_to_llfn(llfn, llvm::AttributePlace::Argument(i), &[byval]);
                 }
                 PassMode::Direct(attrs)
@@ -486,7 +492,10 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
             PassMode::Indirect { attrs, meta_attrs: _, on_stack } => {
                 assert!(!on_stack);
                 let i = apply(bx.cx, attrs);
-                let sret = llvm::CreateStructRetAttr(bx.cx.llcx, self.ret.layout.llvm_type(bx));
+                let sret = llvm::CreateStructRetAttr(
+                    bx.cx.llcx,
+                    bx.cx.type_array(bx.cx.type_i8(), self.ret.layout.size.bytes()),
+                );
                 attributes::apply_to_callsite(callsite, llvm::AttributePlace::Argument(i), &[sret]);
             }
             PassMode::Cast { cast, pad_i32: _ } => {
@@ -513,7 +522,10 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
                 PassMode::Ignore => {}
                 PassMode::Indirect { attrs, meta_attrs: None, on_stack: true } => {
                     let i = apply(bx.cx, attrs);
-                    let byval = llvm::CreateByValAttr(bx.cx.llcx, arg.layout.llvm_type(bx));
+                    let byval = llvm::CreateByValAttr(
+                        bx.cx.llcx,
+                        bx.cx.type_array(bx.cx.type_i8(), arg.layout.size.bytes()),
+                    );
                     attributes::apply_to_callsite(
                         callsite,
                         llvm::AttributePlace::Argument(i),
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index d1f32087908..f89c8c9f836 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -77,8 +77,8 @@ pub struct CodegenCx<'ll, 'tcx> {
     /// See <https://llvm.org/docs/LangRef.html#the-llvm-compiler-used-global-variable> for details
     pub compiler_used_statics: RefCell<Vec<&'ll Value>>,
 
-    /// Mapping of non-scalar types to llvm types and field remapping if needed.
-    pub type_lowering: RefCell<FxHashMap<(Ty<'tcx>, Option<VariantIdx>), TypeLowering<'ll>>>,
+    /// Mapping of non-scalar types to llvm types.
+    pub type_lowering: RefCell<FxHashMap<(Ty<'tcx>, Option<VariantIdx>), &'ll Type>>,
 
     /// Mapping of scalar types to llvm types.
     pub scalar_lltypes: RefCell<FxHashMap<Ty<'tcx>, &'ll Type>>,
@@ -105,15 +105,6 @@ pub struct CodegenCx<'ll, 'tcx> {
     pub renamed_statics: RefCell<FxHashMap<DefId, &'ll Value>>,
 }
 
-pub struct TypeLowering<'ll> {
-    /// Associated LLVM type
-    pub lltype: &'ll Type,
-
-    /// If padding is used the slice maps fields from source order
-    /// to llvm order.
-    pub field_remapping: Option<SmallVec<[u32; 4]>>,
-}
-
 fn to_llvm_tls_model(tls_model: TlsModel) -> llvm::ThreadLocalMode {
     match tls_model {
         TlsModel::GeneralDynamic => llvm::ThreadLocalMode::GeneralDynamic,
@@ -558,11 +549,12 @@ impl<'ll, 'tcx> MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
 
         let tcx = self.tcx;
         let llfn = match tcx.lang_items().eh_personality() {
-            Some(def_id) if name.is_none() => self.get_fn_addr(
-                ty::Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, ty::List::empty())
-                    .unwrap()
-                    .unwrap(),
-            ),
+            Some(def_id) if name.is_none() => self.get_fn_addr(ty::Instance::expect_resolve(
+                tcx,
+                ty::ParamEnv::reveal_all(),
+                def_id,
+                ty::List::empty(),
+            )),
             _ => {
                 let name = name.unwrap_or("rust_eh_personality");
                 if let Some(llfn) = self.get_declared_value(name) {
diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs
index 5bef240340b..e15eda7c66c 100644
--- a/compiler/rustc_codegen_llvm/src/errors.rs
+++ b/compiler/rustc_codegen_llvm/src/errors.rs
@@ -4,7 +4,7 @@ use std::path::Path;
 
 use crate::fluent_generated as fluent;
 use rustc_data_structures::small_c_str::SmallCStr;
-use rustc_errors::{Diag, DiagCtxt, EmissionGuarantee, IntoDiagnostic, Level};
+use rustc_errors::{Diag, DiagCtxt, Diagnostic, EmissionGuarantee, Level};
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::Span;
 
@@ -99,9 +99,9 @@ pub(crate) struct DynamicLinkingWithLTO;
 
 pub(crate) struct ParseTargetMachineConfig<'a>(pub LlvmError<'a>);
 
-impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for ParseTargetMachineConfig<'_> {
-    fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> Diag<'_, G> {
-        let diag: Diag<'_, G> = self.0.into_diagnostic(dcx, level);
+impl<G: EmissionGuarantee> Diagnostic<'_, G> for ParseTargetMachineConfig<'_> {
+    fn into_diag(self, dcx: &'_ DiagCtxt, level: Level) -> Diag<'_, G> {
+        let diag: Diag<'_, G> = self.0.into_diag(dcx, level);
         let (message, _) = diag.messages.first().expect("`LlvmError` with no message");
         let message = dcx.eagerly_translate_to_string(message.clone(), diag.args.iter());
         Diag::new(dcx, level, fluent::codegen_llvm_parse_target_machine_config)
@@ -119,8 +119,8 @@ pub(crate) struct TargetFeatureDisableOrEnable<'a> {
 #[help(codegen_llvm_missing_features)]
 pub(crate) struct MissingFeatures;
 
-impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> {
-    fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> Diag<'_, G> {
+impl<G: EmissionGuarantee> Diagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> {
+    fn into_diag(self, dcx: &'_ DiagCtxt, level: Level) -> Diag<'_, G> {
         let mut diag = Diag::new(dcx, level, fluent::codegen_llvm_target_feature_disable_or_enable);
         if let Some(span) = self.span {
             diag.span(span);
@@ -179,8 +179,8 @@ pub enum LlvmError<'a> {
 
 pub(crate) struct WithLlvmError<'a>(pub LlvmError<'a>, pub String);
 
-impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for WithLlvmError<'_> {
-    fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> Diag<'_, G> {
+impl<G: EmissionGuarantee> Diagnostic<'_, G> for WithLlvmError<'_> {
+    fn into_diag(self, dcx: &'_ DiagCtxt, level: Level) -> Diag<'_, G> {
         use LlvmError::*;
         let msg_with_llvm_err = match &self.0 {
             WriteOutput { .. } => fluent::codegen_llvm_write_output_with_llvm_err,
@@ -198,7 +198,7 @@ impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for WithLlvmError<'_> {
             ParseBitcode => fluent::codegen_llvm_parse_bitcode_with_llvm_err,
         };
         self.0
-            .into_diagnostic(dcx, level)
+            .into_diag(dcx, level)
             .with_primary_message(msg_with_llvm_err)
             .with_arg("llvm_err", self.1)
     }
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 78d47f36f91..e32c38644aa 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -5,6 +5,7 @@ use crate::errors::{
 };
 use crate::llvm;
 use libc::c_int;
+use rustc_codegen_ssa::base::wants_wasm_eh;
 use rustc_codegen_ssa::traits::PrintBackendInfo;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::small_c_str::SmallCStr;
@@ -98,6 +99,10 @@ unsafe fn configure_llvm(sess: &Session) {
             }
         }
 
+        if wants_wasm_eh(sess) {
+            add("-wasm-enable-eh", false);
+        }
+
         if sess.target.os == "emscripten" && sess.panic_strategy() == PanicStrategy::Unwind {
             add("-enable-emscripten-cxx-exceptions", false);
         }
@@ -523,6 +528,10 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec<Str
             .map(String::from),
     );
 
+    if wants_wasm_eh(sess) && sess.panic_strategy() == PanicStrategy::Unwind {
+        features.push("+exception-handling".into());
+    }
+
     // -Ctarget-features
     let supported_features = sess.target.supported_target_features();
     let mut featsmap = FxHashMap::default();
diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs
index 587adefe1d2..d10a083765b 100644
--- a/compiler/rustc_codegen_llvm/src/type_of.rs
+++ b/compiler/rustc_codegen_llvm/src/type_of.rs
@@ -1,5 +1,4 @@
 use crate::common::*;
-use crate::context::TypeLowering;
 use crate::type_::Type;
 use rustc_codegen_ssa::traits::*;
 use rustc_middle::bug;
@@ -10,7 +9,6 @@ use rustc_target::abi::HasDataLayout;
 use rustc_target::abi::{Abi, Align, FieldsShape};
 use rustc_target::abi::{Int, Pointer, F128, F16, F32, F64};
 use rustc_target::abi::{Scalar, Size, Variants};
-use smallvec::{smallvec, SmallVec};
 
 use std::fmt::Write;
 
@@ -18,7 +16,6 @@ fn uncached_llvm_type<'a, 'tcx>(
     cx: &CodegenCx<'a, 'tcx>,
     layout: TyAndLayout<'tcx>,
     defer: &mut Option<(&'a Type, TyAndLayout<'tcx>)>,
-    field_remapping: &mut Option<SmallVec<[u32; 4]>>,
 ) -> &'a Type {
     match layout.abi {
         Abi::Scalar(_) => bug!("handled elsewhere"),
@@ -71,8 +68,7 @@ fn uncached_llvm_type<'a, 'tcx>(
         FieldsShape::Array { count, .. } => cx.type_array(layout.field(cx, 0).llvm_type(cx), count),
         FieldsShape::Arbitrary { .. } => match name {
             None => {
-                let (llfields, packed, new_field_remapping) = struct_llfields(cx, layout);
-                *field_remapping = new_field_remapping;
+                let (llfields, packed) = struct_llfields(cx, layout);
                 cx.type_struct(&llfields, packed)
             }
             Some(ref name) => {
@@ -87,7 +83,7 @@ fn uncached_llvm_type<'a, 'tcx>(
 fn struct_llfields<'a, 'tcx>(
     cx: &CodegenCx<'a, 'tcx>,
     layout: TyAndLayout<'tcx>,
-) -> (Vec<&'a Type>, bool, Option<SmallVec<[u32; 4]>>) {
+) -> (Vec<&'a Type>, bool) {
     debug!("struct_llfields: {:#?}", layout);
     let field_count = layout.fields.count();
 
@@ -95,7 +91,6 @@ fn struct_llfields<'a, 'tcx>(
     let mut offset = Size::ZERO;
     let mut prev_effective_align = layout.align.abi;
     let mut result: Vec<_> = Vec::with_capacity(1 + field_count * 2);
-    let mut field_remapping = smallvec![0; field_count];
     for i in layout.fields.index_by_increasing_offset() {
         let target_offset = layout.fields.offset(i as usize);
         let field = layout.field(cx, i);
@@ -120,12 +115,10 @@ fn struct_llfields<'a, 'tcx>(
             result.push(cx.type_padding_filler(padding, padding_align));
             debug!("    padding before: {:?}", padding);
         }
-        field_remapping[i] = result.len() as u32;
         result.push(field.llvm_type(cx));
         offset = target_offset + field.size;
         prev_effective_align = effective_field_align;
     }
-    let padding_used = result.len() > field_count;
     if layout.is_sized() && field_count > 0 {
         if offset > layout.size {
             bug!("layout: {:#?} stride: {:?} offset: {:?}", layout, layout.size, offset);
@@ -143,8 +136,7 @@ fn struct_llfields<'a, 'tcx>(
     } else {
         debug!("struct_llfields: offset: {:?} stride: {:?}", offset, layout.size);
     }
-    let field_remapping = padding_used.then_some(field_remapping);
-    (result, packed, field_remapping)
+    (result, packed)
 }
 
 impl<'a, 'tcx> CodegenCx<'a, 'tcx> {
@@ -224,7 +216,7 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
             _ => None,
         };
         if let Some(llty) = cx.type_lowering.borrow().get(&(self.ty, variant_index)) {
-            return llty.lltype;
+            return llty;
         }
 
         debug!("llvm_type({:#?})", self);
@@ -236,7 +228,6 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
         let normal_ty = cx.tcx.erase_regions(self.ty);
 
         let mut defer = None;
-        let mut field_remapping = None;
         let llty = if self.ty != normal_ty {
             let mut layout = cx.layout_of(normal_ty);
             if let Some(v) = variant_index {
@@ -244,22 +235,15 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> {
             }
             layout.llvm_type(cx)
         } else {
-            uncached_llvm_type(cx, *self, &mut defer, &mut field_remapping)
+            uncached_llvm_type(cx, *self, &mut defer)
         };
         debug!("--> mapped {:#?} to llty={:?}", self, llty);
 
-        cx.type_lowering
-            .borrow_mut()
-            .insert((self.ty, variant_index), TypeLowering { lltype: llty, field_remapping });
+        cx.type_lowering.borrow_mut().insert((self.ty, variant_index), llty);
 
         if let Some((llty, layout)) = defer {
-            let (llfields, packed, new_field_remapping) = struct_llfields(cx, layout);
+            let (llfields, packed) = struct_llfields(cx, layout);
             cx.set_struct_body(llty, &llfields, packed);
-            cx.type_lowering
-                .borrow_mut()
-                .get_mut(&(self.ty, variant_index))
-                .unwrap()
-                .field_remapping = new_field_remapping;
         }
         llty
     }
diff --git a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs
index 7ecc3864347..e441aea8400 100644
--- a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs
+++ b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs
@@ -27,7 +27,7 @@ use crate::errors;
 use rustc_ast as ast;
 use rustc_data_structures::unord::UnordMap;
 use rustc_data_structures::unord::UnordSet;
-use rustc_errors::{DiagArgValue, IntoDiagnosticArg};
+use rustc_errors::{DiagArgValue, IntoDiagArg};
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_middle::mir::mono::CodegenUnitNameBuilder;
 use rustc_middle::ty::TyCtxt;
@@ -205,8 +205,8 @@ impl fmt::Display for CguReuse {
     }
 }
 
-impl IntoDiagnosticArg for CguReuse {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for CguReuse {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(Cow::Owned(self.to_string()))
     }
 }
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index fcb3602b734..e70cc9b6216 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -24,6 +24,7 @@ use rustc_span::symbol::Symbol;
 use rustc_target::spec::crt_objects::CrtObjects;
 use rustc_target::spec::LinkSelfContainedComponents;
 use rustc_target::spec::LinkSelfContainedDefault;
+use rustc_target::spec::LinkerFlavorCli;
 use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, Lld, PanicStrategy};
 use rustc_target::spec::{RelocModel, RelroLevel, SanitizerSet, SplitDebuginfo};
 
@@ -1350,6 +1351,7 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
                         }
                     }
                     LinkerFlavor::Bpf => "bpf-linker",
+                    LinkerFlavor::Llbc => "llvm-bitcode-linker",
                     LinkerFlavor::Ptx => "rust-ptx-linker",
                 }),
                 flavor,
@@ -1367,8 +1369,17 @@ pub fn linker_and_flavor(sess: &Session) -> (PathBuf, LinkerFlavor) {
 
     // linker and linker flavor specified via command line have precedence over what the target
     // specification specifies
-    let linker_flavor =
-        sess.opts.cg.linker_flavor.map(|flavor| sess.target.linker_flavor.with_cli_hints(flavor));
+    let linker_flavor = match sess.opts.cg.linker_flavor {
+        // The linker flavors that are non-target specific can be directly translated to LinkerFlavor
+        Some(LinkerFlavorCli::Llbc) => Some(LinkerFlavor::Llbc),
+        Some(LinkerFlavorCli::Ptx) => Some(LinkerFlavor::Ptx),
+        // The linker flavors that corresponds to targets needs logic that keeps the base LinkerFlavor
+        _ => sess
+            .opts
+            .cg
+            .linker_flavor
+            .map(|flavor| sess.target.linker_flavor.with_cli_hints(flavor)),
+    };
     if let Some(ret) = infer_from(sess, sess.opts.cg.linker.clone(), linker_flavor) {
         return ret;
     }
@@ -2338,8 +2349,12 @@ fn add_order_independent_options(
         });
     }
 
-    if flavor == LinkerFlavor::Ptx {
-        // Provide the linker with fallback to internal `target-cpu`.
+    if flavor == LinkerFlavor::Llbc {
+        cmd.arg("--target");
+        cmd.arg(sess.target.llvm_target.as_ref());
+        cmd.arg("--target-cpu");
+        cmd.arg(&codegen_results.crate_info.target_cpu);
+    } else if flavor == LinkerFlavor::Ptx {
         cmd.arg("--fallback-arch");
         cmd.arg(&codegen_results.crate_info.target_cpu);
     } else if flavor == LinkerFlavor::Bpf {
diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs
index e52efd86955..b4e054417f3 100644
--- a/compiler/rustc_codegen_ssa/src/back/linker.rs
+++ b/compiler/rustc_codegen_ssa/src/back/linker.rs
@@ -153,6 +153,7 @@ pub fn get_linker<'a>(
         LinkerFlavor::Msvc(..) => Box::new(MsvcLinker { cmd, sess }) as Box<dyn Linker>,
         LinkerFlavor::EmCc => Box::new(EmLinker { cmd, sess }) as Box<dyn Linker>,
         LinkerFlavor::Bpf => Box::new(BpfLinker { cmd, sess }) as Box<dyn Linker>,
+        LinkerFlavor::Llbc => Box::new(LlbcLinker { cmd, sess }) as Box<dyn Linker>,
         LinkerFlavor::Ptx => Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>,
     }
 }
@@ -1824,7 +1825,7 @@ impl<'a> Linker for PtxLinker<'a> {
             }
 
             Lto::No => {}
-        };
+        }
     }
 
     fn output_filename(&mut self, path: &Path) {
@@ -1862,6 +1863,104 @@ impl<'a> Linker for PtxLinker<'a> {
     fn linker_plugin_lto(&mut self) {}
 }
 
+/// The `self-contained` LLVM bitcode linker
+pub struct LlbcLinker<'a> {
+    cmd: Command,
+    sess: &'a Session,
+}
+
+impl<'a> Linker for LlbcLinker<'a> {
+    fn cmd(&mut self) -> &mut Command {
+        &mut self.cmd
+    }
+
+    fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {}
+
+    fn link_dylib_by_name(&mut self, _name: &str, _verbatim: bool, _as_needed: bool) {
+        panic!("external dylibs not supported")
+    }
+
+    fn link_staticlib_by_name(
+        &mut self,
+        _name: &str,
+        _verbatim: bool,
+        _whole_archive: bool,
+        _search_paths: &SearchPaths,
+    ) {
+        panic!("staticlibs not supported")
+    }
+
+    fn link_staticlib_by_path(&mut self, path: &Path, _whole_archive: bool) {
+        self.cmd.arg(path);
+    }
+
+    fn include_path(&mut self, path: &Path) {
+        self.cmd.arg("-L").arg(path);
+    }
+
+    fn debuginfo(&mut self, _strip: Strip, _: &[PathBuf]) {
+        self.cmd.arg("--debug");
+    }
+
+    fn add_object(&mut self, path: &Path) {
+        self.cmd.arg(path);
+    }
+
+    fn optimize(&mut self) {
+        match self.sess.opts.optimize {
+            OptLevel::No => "-O0",
+            OptLevel::Less => "-O1",
+            OptLevel::Default => "-O2",
+            OptLevel::Aggressive => "-O3",
+            OptLevel::Size => "-Os",
+            OptLevel::SizeMin => "-Oz",
+        };
+    }
+
+    fn output_filename(&mut self, path: &Path) {
+        self.cmd.arg("-o").arg(path);
+    }
+
+    fn framework_path(&mut self, _path: &Path) {
+        panic!("frameworks not supported")
+    }
+
+    fn full_relro(&mut self) {}
+
+    fn partial_relro(&mut self) {}
+
+    fn no_relro(&mut self) {}
+
+    fn gc_sections(&mut self, _keep_metadata: bool) {}
+
+    fn no_gc_sections(&mut self) {}
+
+    fn pgo_gen(&mut self) {}
+
+    fn no_crt_objects(&mut self) {}
+
+    fn no_default_libraries(&mut self) {}
+
+    fn control_flow_guard(&mut self) {}
+
+    fn ehcont_guard(&mut self) {}
+
+    fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType, symbols: &[String]) {
+        match _crate_type {
+            CrateType::Cdylib => {
+                for sym in symbols {
+                    self.cmd.arg("--export-symbol").arg(sym);
+                }
+            }
+            _ => (),
+        }
+    }
+
+    fn subsystem(&mut self, _subsystem: &str) {}
+
+    fn linker_plugin_lto(&mut self) {}
+}
+
 pub struct BpfLinker<'a> {
     cmd: Command,
     sess: &'a Session,
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index bbb04652119..4eda4c2f08c 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -374,6 +374,10 @@ pub struct CodegenContext<B: WriteBackendMethods> {
     pub incr_comp_session_dir: Option<PathBuf>,
     /// Channel back to the main control thread to send messages to
     pub coordinator_send: Sender<Box<dyn Any + Send>>,
+    /// `true` if the codegen should be run in parallel.
+    ///
+    /// Depends on [`CodegenBackend::supports_parallel()`] and `-Zno_parallel_backend`.
+    pub parallel: bool,
 }
 
 impl<B: WriteBackendMethods> CodegenContext<B> {
@@ -1152,6 +1156,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
         target_arch: tcx.sess.target.arch.to_string(),
         split_debuginfo: tcx.sess.split_debuginfo(),
         split_dwarf_kind: tcx.sess.opts.unstable_opts.split_dwarf_kind,
+        parallel: backend.supports_parallel() && !sess.opts.unstable_opts.no_parallel_backend,
     };
 
     // This is the "main loop" of parallel work happening for parallel codegen.
@@ -1422,7 +1427,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
                             .binary_search_by_key(&cost, |&(_, cost)| cost)
                             .unwrap_or_else(|e| e);
                         work_items.insert(insertion_index, (work, cost));
-                        if !cgcx.opts.unstable_opts.no_parallel_llvm {
+                        if cgcx.parallel {
                             helper.request_token();
                         }
                     }
@@ -1545,7 +1550,7 @@ fn start_executing_work<B: ExtraBackendMethods>(
                     };
                     work_items.insert(insertion_index, (llvm_work_item, cost));
 
-                    if !cgcx.opts.unstable_opts.no_parallel_llvm {
+                    if cgcx.parallel {
                         helper.request_token();
                     }
                     assert_eq!(main_thread_state, MainThreadState::Codegenning);
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index 1a3c70cedd0..c316d19e041 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -165,14 +165,11 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
                 cx.tcx().vtable_trait_upcasting_coercion_new_vptr_slot((source, target));
 
             if let Some(entry_idx) = vptr_entry_idx {
-                let ptr_ty = cx.type_ptr();
-                let ptr_align = cx.tcx().data_layout.pointer_align.abi;
-                let gep = bx.inbounds_gep(
-                    ptr_ty,
-                    old_info,
-                    &[bx.const_usize(u64::try_from(entry_idx).unwrap())],
-                );
-                let new_vptr = bx.load(ptr_ty, gep, ptr_align);
+                let ptr_size = bx.data_layout().pointer_size;
+                let ptr_align = bx.data_layout().pointer_align.abi;
+                let vtable_byte_offset = u64::try_from(entry_idx).unwrap() * ptr_size.bytes();
+                let gep = bx.inbounds_ptradd(old_info, bx.const_usize(vtable_byte_offset));
+                let new_vptr = bx.load(bx.type_ptr(), gep, ptr_align);
                 bx.nonnull_metadata(new_vptr);
                 // VTable loads are invariant.
                 bx.set_invariant_load(new_vptr);
@@ -467,16 +464,12 @@ pub fn maybe_create_entry_wrapper<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
 
         let (start_fn, start_ty, args) = if let EntryFnType::Main { sigpipe } = entry_type {
             let start_def_id = cx.tcx().require_lang_item(LangItem::Start, None);
-            let start_fn = cx.get_fn_addr(
-                ty::Instance::resolve(
-                    cx.tcx(),
-                    ty::ParamEnv::reveal_all(),
-                    start_def_id,
-                    cx.tcx().mk_args(&[main_ret_ty.into()]),
-                )
-                .unwrap()
-                .unwrap(),
-            );
+            let start_fn = cx.get_fn_addr(ty::Instance::expect_resolve(
+                cx.tcx(),
+                ty::ParamEnv::reveal_all(),
+                start_def_id,
+                cx.tcx().mk_args(&[main_ret_ty.into()]),
+            ));
 
             let i8_ty = cx.type_i8();
             let arg_sigpipe = bx.const_u8(sigpipe);
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index 8fae80de064..3572ee301c8 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -4,8 +4,7 @@ use crate::assert_module_sources::CguReuse;
 use crate::back::command::Command;
 use crate::fluent_generated as fluent;
 use rustc_errors::{
-    codes::*, Diag, DiagArgValue, DiagCtxt, EmissionGuarantee, IntoDiagnostic, IntoDiagnosticArg,
-    Level,
+    codes::*, Diag, DiagArgValue, DiagCtxt, Diagnostic, EmissionGuarantee, IntoDiagArg, Level,
 };
 use rustc_macros::Diagnostic;
 use rustc_middle::ty::layout::LayoutError;
@@ -152,8 +151,8 @@ impl<'a> CopyPath<'a> {
 
 struct DebugArgPath<'a>(pub &'a Path);
 
-impl IntoDiagnosticArg for DebugArgPath<'_> {
-    fn into_diagnostic_arg(self) -> rustc_errors::DiagArgValue {
+impl IntoDiagArg for DebugArgPath<'_> {
+    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
         DiagArgValue::Str(Cow::Owned(format!("{:?}", self.0)))
     }
 }
@@ -215,8 +214,8 @@ pub enum LinkRlibError {
 
 pub struct ThorinErrorWrapper(pub thorin::Error);
 
-impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for ThorinErrorWrapper {
-    fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> Diag<'_, G> {
+impl<G: EmissionGuarantee> Diagnostic<'_, G> for ThorinErrorWrapper {
+    fn into_diag(self, dcx: &DiagCtxt, level: Level) -> Diag<'_, G> {
         let build = |msg| Diag::new(dcx, level, msg);
         match self.0 {
             thorin::Error::ReadInput(_) => build(fluent::codegen_ssa_thorin_read_input_failure),
@@ -348,8 +347,8 @@ pub struct LinkingFailed<'a> {
     pub escaped_output: String,
 }
 
-impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for LinkingFailed<'_> {
-    fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> Diag<'_, G> {
+impl<G: EmissionGuarantee> Diagnostic<'_, G> for LinkingFailed<'_> {
+    fn into_diag(self, dcx: &DiagCtxt, level: Level) -> Diag<'_, G> {
         let mut diag = Diag::new(dcx, level, fluent::codegen_ssa_linking_failed);
         diag.arg("linker_path", format!("{}", self.linker_path.display()));
         diag.arg("exit_status", format!("{}", self.exit_status));
@@ -974,8 +973,8 @@ pub enum ExpectedPointerMutability {
     Not,
 }
 
-impl IntoDiagnosticArg for ExpectedPointerMutability {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for ExpectedPointerMutability {
+    fn into_diag_arg(self) -> DiagArgValue {
         match self {
             ExpectedPointerMutability::Mut => DiagArgValue::Str(Cow::Borrowed("*mut")),
             ExpectedPointerMutability::Not => DiagArgValue::Str(Cow::Borrowed("*_")),
diff --git a/compiler/rustc_codegen_ssa/src/meth.rs b/compiler/rustc_codegen_ssa/src/meth.rs
index 12146a54d3b..4f7dc9968a1 100644
--- a/compiler/rustc_codegen_ssa/src/meth.rs
+++ b/compiler/rustc_codegen_ssa/src/meth.rs
@@ -20,9 +20,13 @@ impl<'a, 'tcx> VirtualIndex {
         ty: Ty<'tcx>,
         fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
     ) -> Bx::Value {
-        // Load the data pointer from the object.
+        // Load the function pointer from the object.
         debug!("get_fn({llvtable:?}, {ty:?}, {self:?})");
+
         let llty = bx.fn_ptr_backend_type(fn_abi);
+        let ptr_size = bx.data_layout().pointer_size;
+        let ptr_align = bx.data_layout().pointer_align.abi;
+        let vtable_byte_offset = self.0 * ptr_size.bytes();
 
         if bx.cx().sess().opts.unstable_opts.virtual_function_elimination
             && bx.cx().sess().lto() == Lto::Fat
@@ -30,12 +34,10 @@ impl<'a, 'tcx> VirtualIndex {
             let typeid = bx
                 .typeid_metadata(typeid_for_trait_ref(bx.tcx(), expect_dyn_trait_in_self(ty)))
                 .unwrap();
-            let vtable_byte_offset = self.0 * bx.data_layout().pointer_size.bytes();
             let func = bx.type_checked_load(llvtable, vtable_byte_offset, typeid);
             func
         } else {
-            let ptr_align = bx.tcx().data_layout.pointer_align.abi;
-            let gep = bx.inbounds_gep(llty, llvtable, &[bx.const_usize(self.0)]);
+            let gep = bx.inbounds_ptradd(llvtable, bx.const_usize(vtable_byte_offset));
             let ptr = bx.load(llty, gep, ptr_align);
             bx.nonnull_metadata(ptr);
             // VTable loads are invariant.
@@ -53,9 +55,12 @@ impl<'a, 'tcx> VirtualIndex {
         debug!("get_int({:?}, {:?})", llvtable, self);
 
         let llty = bx.type_isize();
-        let usize_align = bx.tcx().data_layout.pointer_align.abi;
-        let gep = bx.inbounds_gep(llty, llvtable, &[bx.const_usize(self.0)]);
-        let ptr = bx.load(llty, gep, usize_align);
+        let ptr_size = bx.data_layout().pointer_size;
+        let ptr_align = bx.data_layout().pointer_align.abi;
+        let vtable_byte_offset = self.0 * ptr_size.bytes();
+
+        let gep = bx.inbounds_ptradd(llvtable, bx.const_usize(vtable_byte_offset));
+        let ptr = bx.load(llty, gep, ptr_align);
         // VTable loads are invariant.
         bx.set_invariant_load(ptr);
         ptr
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 89a44d2897a..d3f5de25d9a 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -1597,7 +1597,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         let funclet;
         let llbb;
         let mut bx;
-        if base::wants_msvc_seh(self.cx.sess()) {
+        if base::wants_new_eh_instructions(self.cx.sess()) {
             // This is a basic block that we're aborting the program for,
             // notably in an `extern` function. These basic blocks are inserted
             // so that we assert that `extern` functions do indeed not panic,
diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs
index cb1feff1336..e6d42c596d2 100644
--- a/compiler/rustc_codegen_ssa/src/traits/backend.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs
@@ -111,6 +111,13 @@ pub trait CodegenBackend {
         codegen_results: CodegenResults,
         outputs: &OutputFilenames,
     ) -> Result<(), ErrorGuaranteed>;
+
+    /// Returns `true` if this backend can be safely called from multiple threads.
+    ///
+    /// Defaults to `true`.
+    fn supports_parallel(&self) -> bool {
+        true
+    }
 }
 
 pub trait ExtraBackendMethods:
diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl
index 81c9e02e2ee..f3af633b4e5 100644
--- a/compiler/rustc_const_eval/messages.ftl
+++ b/compiler/rustc_const_eval/messages.ftl
@@ -146,9 +146,6 @@ const_eval_intern_kind = {$kind ->
     *[other] {""}
 }
 
-const_eval_invalid_align =
-    align has to be a power of 2
-
 const_eval_invalid_align_details =
     invalid align passed to `{$name}`: {$align} is {$err_kind ->
         [not_power_of_two] not a power of 2
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index e5b4fc3a574..b6adee435ba 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -1,6 +1,6 @@
 use std::mem;
 
-use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, IntoDiagnostic, IntoDiagnosticArg};
+use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, Diagnostic, IntoDiagArg};
 use rustc_hir::CRATE_HIR_ID;
 use rustc_middle::mir::AssertKind;
 use rustc_middle::query::TyCtxtAt;
@@ -40,10 +40,10 @@ impl MachineStopType for ConstEvalErrKind {
             RecursiveStatic | ConstAccessesMutGlobal | ModifiedGlobal => {}
             AssertFailure(kind) => kind.add_args(adder),
             Panic { msg, line, col, file } => {
-                adder("msg".into(), msg.into_diagnostic_arg());
-                adder("file".into(), file.into_diagnostic_arg());
-                adder("line".into(), line.into_diagnostic_arg());
-                adder("col".into(), col.into_diagnostic_arg());
+                adder("msg".into(), msg.into_diag_arg());
+                adder("file".into(), file.into_diag_arg());
+                adder("line".into(), line.into_diag_arg());
+                adder("col".into(), col.into_diag_arg());
             }
         }
     }
@@ -130,7 +130,7 @@ pub(super) fn report<'tcx, C, F, E>(
 where
     C: FnOnce() -> (Span, Vec<FrameNote>),
     F: FnOnce(Span, Vec<FrameNote>) -> E,
-    E: IntoDiagnostic<'tcx>,
+    E: Diagnostic<'tcx>,
 {
     // Special handling for certain errors
     match error {
@@ -168,7 +168,7 @@ pub(super) fn lint<'tcx, 'mir, L>(
     lint: &'static rustc_session::lint::Lint,
     decorator: impl FnOnce(Vec<errors::FrameNote>) -> L,
 ) where
-    L: for<'a> rustc_errors::DecorateLint<'a, ()>,
+    L: for<'a> rustc_errors::LintDiagnostic<'a, ()>,
 {
     let (span, frames) = get_span_and_frames(tcx, machine);
 
diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
index 9e4e7911c3a..90884adb28c 100644
--- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs
@@ -67,7 +67,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
     trace!(
         "eval_body_using_ecx: pushing stack frame for global: {}{}",
         with_no_trimmed_paths!(ecx.tcx.def_path_str(cid.instance.def_id())),
-        cid.promoted.map_or_else(String::new, |p| format!("::promoted[{p:?}]"))
+        cid.promoted.map_or_else(String::new, |p| format!("::{p:?}"))
     );
 
     ecx.push_stack_frame(
@@ -380,16 +380,12 @@ pub fn eval_in_interpreter<'mir, 'tcx>(
         }
         Ok(mplace) => {
             // Since evaluation had no errors, validate the resulting constant.
-
-            // Temporarily allow access to the static_root_alloc_id for the purpose of validation.
-            let static_root_alloc_id = ecx.machine.static_root_alloc_id.take();
-            let validation = const_validate_mplace(&ecx, &mplace, cid);
-            ecx.machine.static_root_alloc_id = static_root_alloc_id;
+            let res = const_validate_mplace(&ecx, &mplace, cid);
 
             let alloc_id = mplace.ptr().provenance.unwrap().alloc_id();
 
             // Validation failed, report an error.
-            if let Err(error) = validation {
+            if let Err(error) = res {
                 Err(const_report_error(&ecx, error, alloc_id))
             } else {
                 // Convert to raw constant
@@ -412,10 +408,10 @@ pub fn const_validate_mplace<'mir, 'tcx>(
             _ if cid.promoted.is_some() => CtfeValidationMode::Promoted,
             Some(mutbl) => CtfeValidationMode::Static { mutbl }, // a `static`
             None => {
-                // In normal `const` (not promoted), the outermost allocation is always only copied,
-                // so having `UnsafeCell` in there is okay despite them being in immutable memory.
-                let allow_immutable_unsafe_cell = cid.promoted.is_none() && !inner;
-                CtfeValidationMode::Const { allow_immutable_unsafe_cell }
+                // This is a normal `const` (not promoted).
+                // The outermost allocation is always only copied, so having `UnsafeCell` in there
+                // is okay despite them being in immutable memory.
+                CtfeValidationMode::Const { allow_immutable_unsafe_cell: !inner }
             }
         };
         ecx.const_validate_operand(&mplace.into(), path, &mut ref_tracking, mode)?;
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 6736fc749c0..f104b836716 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -243,14 +243,12 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
         } else if Some(def_id) == self.tcx.lang_items().panic_fmt() {
             // For panic_fmt, call const_panic_fmt instead.
             let const_def_id = self.tcx.require_lang_item(LangItem::ConstPanicFmt, None);
-            let new_instance = ty::Instance::resolve(
+            let new_instance = ty::Instance::expect_resolve(
                 *self.tcx,
                 ty::ParamEnv::reveal_all(),
                 const_def_id,
                 instance.args,
-            )
-            .unwrap()
-            .unwrap();
+            );
 
             return Ok(Some(new_instance));
         } else if Some(def_id) == self.tcx.lang_items().align_offset_fn() {
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index afabd9689c6..249c02b75f7 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -1,7 +1,7 @@
 use std::borrow::Cow;
 
 use rustc_errors::{
-    codes::*, Diag, DiagArgValue, DiagCtxt, DiagMessage, EmissionGuarantee, IntoDiagnostic, Level,
+    codes::*, Diag, DiagArgValue, DiagCtxt, DiagMessage, Diagnostic, EmissionGuarantee, Level,
 };
 use rustc_hir::ConstContext;
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
@@ -239,7 +239,7 @@ pub(crate) struct NonConstImplNote {
     pub span: Span,
 }
 
-#[derive(Subdiagnostic, PartialEq, Eq, Clone)]
+#[derive(Subdiagnostic, Clone)]
 #[note(const_eval_frame_note)]
 pub struct FrameNote {
     #[primary_span]
@@ -858,8 +858,7 @@ impl<'tcx> ReportErrorExt for InvalidProgramInfo<'tcx> {
             InvalidProgramInfo::Layout(e) => {
                 // The level doesn't matter, `dummy_diag` is consumed without it being used.
                 let dummy_level = Level::Bug;
-                let dummy_diag: Diag<'_, ()> =
-                    e.into_diagnostic().into_diagnostic(diag.dcx, dummy_level);
+                let dummy_diag: Diag<'_, ()> = e.into_diagnostic().into_diag(diag.dcx, dummy_level);
                 for (name, val) in dummy_diag.args.iter() {
                     diag.arg(name.clone(), val.clone());
                 }
@@ -887,8 +886,8 @@ impl ReportErrorExt for ResourceExhaustionInfo {
     fn add_args<G: EmissionGuarantee>(self, _: &mut Diag<'_, G>) {}
 }
 
-impl rustc_errors::IntoDiagnosticArg for InternKind {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl rustc_errors::IntoDiagArg for InternKind {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(Cow::Borrowed(match self {
             InternKind::Static(Mutability::Not) => "static",
             InternKind::Static(Mutability::Mut) => "static_mut",
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index 90a654a1229..305f7ade101 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -391,6 +391,8 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
 
     /// Hook for performing extra checks on a memory read access.
     ///
+    /// This will *not* be called during validation!
+    ///
     /// Takes read-only access to the allocation so we can keep all the memory read
     /// operations take `&self`. Use a `RefCell` in `AllocExtra` if you
     /// need to mutate.
@@ -410,6 +412,8 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
     /// Hook for performing extra checks on any memory read access,
     /// that involves an allocation, even ZST reads.
     ///
+    /// This will *not* be called during validation!
+    ///
     /// Used to prevent statics from self-initializing by reading from their own memory
     /// as it is being initialized.
     fn before_alloc_read(
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 3b2208b8caa..cf7f165b87c 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -8,6 +8,7 @@
 
 use std::assert_matches::assert_matches;
 use std::borrow::Cow;
+use std::cell::Cell;
 use std::collections::VecDeque;
 use std::fmt;
 use std::ptr;
@@ -111,6 +112,11 @@ pub struct Memory<'mir, 'tcx, M: Machine<'mir, 'tcx>> {
     /// that do not exist any more.
     // FIXME: this should not be public, but interning currently needs access to it
     pub(super) dead_alloc_map: FxIndexMap<AllocId, (Size, Align)>,
+
+    /// This stores whether we are currently doing reads purely for the purpose of validation.
+    /// Those reads do not trigger the machine's hooks for memory reads.
+    /// Needless to say, this must only be set with great care!
+    validation_in_progress: Cell<bool>,
 }
 
 /// A reference to some allocation that was already bounds-checked for the given region
@@ -137,6 +143,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
             alloc_map: M::MemoryMap::default(),
             extra_fn_ptr_map: FxIndexMap::default(),
             dead_alloc_map: FxIndexMap::default(),
+            validation_in_progress: Cell::new(false),
         }
     }
 
@@ -624,10 +631,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             size,
             CheckInAllocMsg::MemoryAccessTest,
             |alloc_id, offset, prov| {
-                // We want to call the hook on *all* accesses that involve an AllocId,
-                // including zero-sized accesses. That means we have to do it here
-                // rather than below in the `Some` branch.
-                M::before_alloc_read(self, alloc_id)?;
+                if !self.memory.validation_in_progress.get() {
+                    // We want to call the hook on *all* accesses that involve an AllocId,
+                    // including zero-sized accesses. That means we have to do it here
+                    // rather than below in the `Some` branch.
+                    M::before_alloc_read(self, alloc_id)?;
+                }
                 let alloc = self.get_alloc_raw(alloc_id)?;
                 Ok((alloc.size(), alloc.align, (alloc_id, offset, prov, alloc)))
             },
@@ -635,7 +644,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
 
         if let Some((alloc_id, offset, prov, alloc)) = ptr_and_alloc {
             let range = alloc_range(offset, size);
-            M::before_memory_read(self.tcx, &self.machine, &alloc.extra, (alloc_id, prov), range)?;
+            if !self.memory.validation_in_progress.get() {
+                M::before_memory_read(
+                    self.tcx,
+                    &self.machine,
+                    &alloc.extra,
+                    (alloc_id, prov),
+                    range,
+                )?;
+            }
             Ok(Some(AllocRef { alloc, range, tcx: *self.tcx, alloc_id }))
         } else {
             Ok(None)
@@ -909,6 +926,21 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
         })
     }
+
+    /// Runs the close in "validation" mode, which means the machine's memory read hooks will be
+    /// suppressed. Needless to say, this must only be set with great care! Cannot be nested.
+    pub(super) fn run_for_validation<R>(&self, f: impl FnOnce() -> R) -> R {
+        assert!(
+            self.memory.validation_in_progress.replace(true) == false,
+            "`validation_in_progress` was already set"
+        );
+        let res = f();
+        assert!(
+            self.memory.validation_in_progress.replace(false) == true,
+            "`validation_in_progress` was unset by someone else"
+        );
+        res
+    }
 }
 
 #[doc(hidden)]
@@ -1154,6 +1186,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         };
         let src_alloc = self.get_alloc_raw(src_alloc_id)?;
         let src_range = alloc_range(src_offset, size);
+        assert!(!self.memory.validation_in_progress.get(), "we can't be copying during validation");
         M::before_memory_read(
             tcx,
             &self.machine,
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index c568f9acfd3..972424bccfa 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -971,7 +971,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         let mut visitor = ValidityVisitor { path, ref_tracking, ctfe_mode, ecx: self };
 
         // Run it.
-        match visitor.visit_value(op) {
+        match self.run_for_validation(|| visitor.visit_value(op)) {
             Ok(()) => Ok(()),
             // Pass through validation failures and "invalid program" issues.
             Err(err)
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 53308cd7f90..a93e8138aa4 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -30,7 +30,7 @@ type QualifResults<'mir, 'tcx, Q> =
     rustc_mir_dataflow::ResultsCursor<'mir, 'tcx, FlowSensitiveAnalysis<'mir, 'mir, 'tcx, Q>>;
 
 #[derive(Default)]
-pub struct Qualifs<'mir, 'tcx> {
+pub(crate) struct Qualifs<'mir, 'tcx> {
     has_mut_interior: Option<QualifResults<'mir, 'tcx, HasMutInterior>>,
     needs_drop: Option<QualifResults<'mir, 'tcx, NeedsDrop>>,
     needs_non_const_drop: Option<QualifResults<'mir, 'tcx, NeedsNonConstDrop>>,
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index 7eb3c181d69..1847847d9d2 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -284,6 +284,7 @@ where
                 if Q::in_adt_inherently(cx, def, args) {
                     return true;
                 }
+                // Don't do any value-based reasoning for unions.
                 if def.is_union() && Q::in_any_value_of_ty(cx, rvalue.ty(cx.body, cx.tcx)) {
                     return true;
                 }
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 2802f44cda7..7b1070f309b 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -37,7 +37,7 @@ use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS};
 use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType};
 use rustc_session::getopts::{self, Matches};
 use rustc_session::lint::{Lint, LintId};
-use rustc_session::{config, EarlyDiagCtxt, Session};
+use rustc_session::{config, filesearch, EarlyDiagCtxt, Session};
 use rustc_span::def_id::LOCAL_CRATE;
 use rustc_span::source_map::FileLoader;
 use rustc_span::symbol::sym;
@@ -887,7 +887,11 @@ pub fn version_at_macro_invocation(
 
         let debug_flags = matches.opt_strs("Z");
         let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
-        get_codegen_backend(early_dcx, &None, backend_name).print_version();
+        let opts = config::Options::default();
+        let sysroot = filesearch::materialize_sysroot(opts.maybe_sysroot.clone());
+        let target = config::build_target_config(early_dcx, &opts, None, &sysroot);
+
+        get_codegen_backend(early_dcx, &sysroot, backend_name, &target).print_version();
     }
 }
 
@@ -1092,7 +1096,12 @@ pub fn describe_flag_categories(early_dcx: &EarlyDiagCtxt, matches: &Matches) ->
 
     if cg_flags.iter().any(|x| *x == "passes=list") {
         let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend="));
-        get_codegen_backend(early_dcx, &None, backend_name).print_passes();
+
+        let opts = config::Options::default();
+        let sysroot = filesearch::materialize_sysroot(opts.maybe_sysroot.clone());
+        let target = config::build_target_config(early_dcx, &opts, None, &sysroot);
+
+        get_codegen_backend(early_dcx, &sysroot, backend_name, &target).print_passes();
         return true;
     }
 
diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs
index c9bbe45b212..c0c6201f73d 100644
--- a/compiler/rustc_driver_impl/src/pretty.rs
+++ b/compiler/rustc_driver_impl/src/pretty.rs
@@ -336,7 +336,8 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
         ThirTree => {
             let tcx = ex.tcx();
             let mut out = String::new();
-            if rustc_hir_analysis::check_crate(tcx).is_err() {
+            rustc_hir_analysis::check_crate(tcx);
+            if tcx.dcx().has_errors().is_some() {
                 FatalError.raise();
             }
             debug!("pretty printing THIR tree");
@@ -348,7 +349,8 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) {
         ThirFlat => {
             let tcx = ex.tcx();
             let mut out = String::new();
-            if rustc_hir_analysis::check_crate(tcx).is_err() {
+            rustc_hir_analysis::check_crate(tcx);
+            if tcx.dcx().has_errors().is_some() {
                 FatalError.raise();
             }
             debug!("pretty printing THIR flat");
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index c186d5b284f..0c3e7fb75b0 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -38,7 +38,7 @@ pub enum DiagArgValue {
     Str(Cow<'static, str>),
     // This gets converted to a `FluentNumber`, which is an `f64`. An `i32`
     // safely fits in an `f64`. Any integers bigger than that will be converted
-    // to strings in `into_diagnostic_arg` and stored using the `Str` variant.
+    // to strings in `into_diag_arg` and stored using the `Str` variant.
     Number(i32),
     StrListSepByAnd(Vec<Cow<'static, str>>),
 }
@@ -112,48 +112,48 @@ impl EmissionGuarantee for rustc_span::fatal_error::FatalError {
 /// When implemented manually, it should be generic over the emission
 /// guarantee, i.e.:
 /// ```ignore (fragment)
-/// impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for Foo { ... }
+/// impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for Foo { ... }
 /// ```
 /// rather than being specific:
 /// ```ignore (fragment)
-/// impl<'a> IntoDiagnostic<'a> for Bar { ... }  // the default type param is `ErrorGuaranteed`
-/// impl<'a> IntoDiagnostic<'a, ()> for Baz { ... }
+/// impl<'a> Diagnostic<'a> for Bar { ... }  // the default type param is `ErrorGuaranteed`
+/// impl<'a> Diagnostic<'a, ()> for Baz { ... }
 /// ```
 /// There are two reasons for this.
 /// - A diagnostic like `Foo` *could* be emitted at any level -- `level` is
-///   passed in to `into_diagnostic` from outside. Even if in practice it is
+///   passed in to `into_diag` from outside. Even if in practice it is
 ///   always emitted at a single level, we let the diagnostic creation/emission
 ///   site determine the level (by using `create_err`, `emit_warn`, etc.)
-///   rather than the `IntoDiagnostic` impl.
+///   rather than the `Diagnostic` impl.
 /// - Derived impls are always generic, and it's good for the hand-written
 ///   impls to be consistent with them.
-#[rustc_diagnostic_item = "IntoDiagnostic"]
-pub trait IntoDiagnostic<'a, G: EmissionGuarantee = ErrorGuaranteed> {
+#[rustc_diagnostic_item = "Diagnostic"]
+pub trait Diagnostic<'a, G: EmissionGuarantee = ErrorGuaranteed> {
     /// Write out as a diagnostic out of `DiagCtxt`.
     #[must_use]
-    fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G>;
+    fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G>;
 }
 
-impl<'a, T, G> IntoDiagnostic<'a, G> for Spanned<T>
+impl<'a, T, G> Diagnostic<'a, G> for Spanned<T>
 where
-    T: IntoDiagnostic<'a, G>,
+    T: Diagnostic<'a, G>,
     G: EmissionGuarantee,
 {
-    fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
-        self.node.into_diagnostic(dcx, level).with_span(self.span)
+    fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
+        self.node.into_diag(dcx, level).with_span(self.span)
     }
 }
 
-/// Converts a value of a type into a `DiagArg` (typically a field of an `IntoDiagnostic` struct).
+/// Converts a value of a type into a `DiagArg` (typically a field of an `Diag` struct).
 /// Implemented as a custom trait rather than `From` so that it is implemented on the type being
 /// converted rather than on `DiagArgValue`, which enables types from other `rustc_*` crates to
 /// implement this.
-pub trait IntoDiagnosticArg {
-    fn into_diagnostic_arg(self) -> DiagArgValue;
+pub trait IntoDiagArg {
+    fn into_diag_arg(self) -> DiagArgValue;
 }
 
-impl IntoDiagnosticArg for DiagArgValue {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for DiagArgValue {
+    fn into_diag_arg(self) -> DiagArgValue {
         self
     }
 }
@@ -170,19 +170,19 @@ impl Into<FluentValue<'static>> for DiagArgValue {
 
 /// Trait implemented by error types. This should not be implemented manually. Instead, use
 /// `#[derive(Subdiagnostic)]` -- see [rustc_macros::Subdiagnostic].
-#[rustc_diagnostic_item = "AddToDiagnostic"]
-pub trait AddToDiagnostic
+#[rustc_diagnostic_item = "Subdiagnostic"]
+pub trait Subdiagnostic
 where
     Self: Sized,
 {
     /// Add a subdiagnostic to an existing diagnostic.
-    fn add_to_diagnostic<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
-        self.add_to_diagnostic_with(diag, |_, m| m);
+    fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
+        self.add_to_diag_with(diag, |_, m| m);
     }
 
     /// Add a subdiagnostic to an existing diagnostic where `f` is invoked on every message used
     /// (to optionally perform eager translation).
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         f: F,
@@ -193,8 +193,8 @@ pub trait SubdiagMessageOp<G> = Fn(&mut Diag<'_, G>, SubdiagMessage) -> SubdiagM
 
 /// Trait implemented by lint types. This should not be implemented manually. Instead, use
 /// `#[derive(LintDiagnostic)]` -- see [rustc_macros::LintDiagnostic].
-#[rustc_diagnostic_item = "DecorateLint"]
-pub trait DecorateLint<'a, G: EmissionGuarantee> {
+#[rustc_diagnostic_item = "LintDiagnostic"]
+pub trait LintDiagnostic<'a, G: EmissionGuarantee> {
     /// Decorate and emit a lint.
     fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, G>);
 
@@ -419,8 +419,8 @@ impl DiagInner {
         self.children.push(sub);
     }
 
-    pub(crate) fn arg(&mut self, name: impl Into<DiagArgName>, arg: impl IntoDiagnosticArg) {
-        self.args.insert(name.into(), arg.into_diagnostic_arg());
+    pub(crate) fn arg(&mut self, name: impl Into<DiagArgName>, arg: impl IntoDiagArg) {
+        self.args.insert(name.into(), arg.into_diag_arg());
     }
 
     /// Fields used for Hash, and PartialEq trait.
@@ -482,7 +482,7 @@ pub struct Subdiag {
 /// - The `EmissionGuarantee`, which determines the type returned from `emit`.
 ///
 /// Each constructed `Diag` must be consumed by a function such as `emit`,
-/// `cancel`, `delay_as_bug`, or `into_diagnostic`. A panic occurrs if a `Diag`
+/// `cancel`, `delay_as_bug`, or `into_diag`. A panic occurrs if a `Diag`
 /// is dropped without being consumed by one of these functions.
 ///
 /// If there is some state in a downstream crate you would like to access in
@@ -1194,9 +1194,9 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     pub fn subdiagnostic(
         &mut self,
         dcx: &crate::DiagCtxt,
-        subdiagnostic: impl AddToDiagnostic,
+        subdiagnostic: impl Subdiagnostic,
     ) -> &mut Self {
-        subdiagnostic.add_to_diagnostic_with(self, |diag, msg| {
+        subdiagnostic.add_to_diag_with(self, |diag, msg| {
             let args = diag.args.iter();
             let msg = diag.subdiagnostic_message_to_diagnostic_message(msg);
             dcx.eagerly_translate(msg, args)
@@ -1243,7 +1243,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     pub fn arg(
         &mut self,
         name: impl Into<DiagArgName>,
-        arg: impl IntoDiagnosticArg,
+        arg: impl IntoDiagArg,
     ) -> &mut Self {
         self.deref_mut().arg(name, arg);
         self
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index 839bd65e4a6..f90190797ae 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -1,8 +1,8 @@
 use crate::diagnostic::DiagLocation;
-use crate::{fluent_generated as fluent, AddToDiagnostic};
+use crate::{fluent_generated as fluent, Subdiagnostic};
 use crate::{
-    Diag, DiagArgValue, DiagCtxt, EmissionGuarantee, ErrCode, IntoDiagnostic, IntoDiagnosticArg,
-    Level, SubdiagMessageOp,
+    Diag, DiagArgValue, DiagCtxt, Diagnostic, EmissionGuarantee, ErrCode, IntoDiagArg, Level,
+    SubdiagMessageOp,
 };
 use rustc_ast as ast;
 use rustc_ast_pretty::pprust;
@@ -22,9 +22,9 @@ use std::process::ExitStatus;
 
 pub struct DiagArgFromDisplay<'a>(pub &'a dyn fmt::Display);
 
-impl IntoDiagnosticArg for DiagArgFromDisplay<'_> {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
-        self.0.to_string().into_diagnostic_arg()
+impl IntoDiagArg for DiagArgFromDisplay<'_> {
+    fn into_diag_arg(self) -> DiagArgValue {
+        self.0.to_string().into_diag_arg()
     }
 }
 
@@ -40,34 +40,34 @@ impl<'a, T: fmt::Display> From<&'a T> for DiagArgFromDisplay<'a> {
     }
 }
 
-impl<'a, T: Clone + IntoDiagnosticArg> IntoDiagnosticArg for &'a T {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
-        self.clone().into_diagnostic_arg()
+impl<'a, T: Clone + IntoDiagArg> IntoDiagArg for &'a T {
+    fn into_diag_arg(self) -> DiagArgValue {
+        self.clone().into_diag_arg()
     }
 }
 
-macro_rules! into_diagnostic_arg_using_display {
+macro_rules! into_diag_arg_using_display {
     ($( $ty:ty ),+ $(,)?) => {
         $(
-            impl IntoDiagnosticArg for $ty {
-                fn into_diagnostic_arg(self) -> DiagArgValue {
-                    self.to_string().into_diagnostic_arg()
+            impl IntoDiagArg for $ty {
+                fn into_diag_arg(self) -> DiagArgValue {
+                    self.to_string().into_diag_arg()
                 }
             }
         )+
     }
 }
 
-macro_rules! into_diagnostic_arg_for_number {
+macro_rules! into_diag_arg_for_number {
     ($( $ty:ty ),+ $(,)?) => {
         $(
-            impl IntoDiagnosticArg for $ty {
-                fn into_diagnostic_arg(self) -> DiagArgValue {
+            impl IntoDiagArg for $ty {
+                fn into_diag_arg(self) -> DiagArgValue {
                     // Convert to a string if it won't fit into `Number`.
                     if let Ok(n) = TryInto::<i32>::try_into(self) {
                         DiagArgValue::Number(n)
                     } else {
-                        self.to_string().into_diagnostic_arg()
+                        self.to_string().into_diag_arg()
                     }
                 }
             }
@@ -75,7 +75,7 @@ macro_rules! into_diagnostic_arg_for_number {
     }
 }
 
-into_diagnostic_arg_using_display!(
+into_diag_arg_using_display!(
     ast::ParamKindOrd,
     std::io::Error,
     Box<dyn std::error::Error>,
@@ -92,10 +92,10 @@ into_diagnostic_arg_using_display!(
     ErrCode,
 );
 
-into_diagnostic_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize);
+into_diag_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize);
 
-impl IntoDiagnosticArg for bool {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for bool {
+    fn into_diag_arg(self) -> DiagArgValue {
         if self {
             DiagArgValue::Str(Cow::Borrowed("true"))
         } else {
@@ -104,64 +104,64 @@ impl IntoDiagnosticArg for bool {
     }
 }
 
-impl IntoDiagnosticArg for char {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for char {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(Cow::Owned(format!("{self:?}")))
     }
 }
 
-impl IntoDiagnosticArg for Vec<char> {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for Vec<char> {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::StrListSepByAnd(
             self.into_iter().map(|c| Cow::Owned(format!("{c:?}"))).collect(),
         )
     }
 }
 
-impl IntoDiagnosticArg for Symbol {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
-        self.to_ident_string().into_diagnostic_arg()
+impl IntoDiagArg for Symbol {
+    fn into_diag_arg(self) -> DiagArgValue {
+        self.to_ident_string().into_diag_arg()
     }
 }
 
-impl<'a> IntoDiagnosticArg for &'a str {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
-        self.to_string().into_diagnostic_arg()
+impl<'a> IntoDiagArg for &'a str {
+    fn into_diag_arg(self) -> DiagArgValue {
+        self.to_string().into_diag_arg()
     }
 }
 
-impl IntoDiagnosticArg for String {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for String {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(Cow::Owned(self))
     }
 }
 
-impl<'a> IntoDiagnosticArg for Cow<'a, str> {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl<'a> IntoDiagArg for Cow<'a, str> {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(Cow::Owned(self.into_owned()))
     }
 }
 
-impl<'a> IntoDiagnosticArg for &'a Path {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl<'a> IntoDiagArg for &'a Path {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(Cow::Owned(self.display().to_string()))
     }
 }
 
-impl IntoDiagnosticArg for PathBuf {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for PathBuf {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(Cow::Owned(self.display().to_string()))
     }
 }
 
-impl IntoDiagnosticArg for PanicStrategy {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for PanicStrategy {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(Cow::Owned(self.desc().to_string()))
     }
 }
 
-impl IntoDiagnosticArg for hir::ConstContext {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for hir::ConstContext {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(Cow::Borrowed(match self {
             hir::ConstContext::ConstFn => "const_fn",
             hir::ConstContext::Static(_) => "static",
@@ -170,58 +170,58 @@ impl IntoDiagnosticArg for hir::ConstContext {
     }
 }
 
-impl IntoDiagnosticArg for ast::Expr {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for ast::Expr {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(Cow::Owned(pprust::expr_to_string(&self)))
     }
 }
 
-impl IntoDiagnosticArg for ast::Path {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for ast::Path {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(Cow::Owned(pprust::path_to_string(&self)))
     }
 }
 
-impl IntoDiagnosticArg for ast::token::Token {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for ast::token::Token {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(pprust::token_to_string(&self))
     }
 }
 
-impl IntoDiagnosticArg for ast::token::TokenKind {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for ast::token::TokenKind {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(pprust::token_kind_to_string(&self))
     }
 }
 
-impl IntoDiagnosticArg for type_ir::FloatTy {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for type_ir::FloatTy {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(Cow::Borrowed(self.name_str()))
     }
 }
 
-impl IntoDiagnosticArg for std::ffi::CString {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for std::ffi::CString {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned()))
     }
 }
 
-impl IntoDiagnosticArg for rustc_data_structures::small_c_str::SmallCStr {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for rustc_data_structures::small_c_str::SmallCStr {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(Cow::Owned(self.to_string_lossy().into_owned()))
     }
 }
 
-impl IntoDiagnosticArg for ast::Visibility {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for ast::Visibility {
+    fn into_diag_arg(self) -> DiagArgValue {
         let s = pprust::vis_to_string(&self);
         let s = s.trim_end().to_string();
         DiagArgValue::Str(Cow::Owned(s))
     }
 }
 
-impl IntoDiagnosticArg for rustc_lint_defs::Level {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for rustc_lint_defs::Level {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(Cow::Borrowed(self.to_cmd_flag()))
     }
 }
@@ -235,22 +235,22 @@ impl From<Vec<Symbol>> for DiagSymbolList {
     }
 }
 
-impl IntoDiagnosticArg for DiagSymbolList {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for DiagSymbolList {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::StrListSepByAnd(
             self.0.into_iter().map(|sym| Cow::Owned(format!("`{sym}`"))).collect(),
         )
     }
 }
 
-impl<Id> IntoDiagnosticArg for hir::def::Res<Id> {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl<Id> IntoDiagArg for hir::def::Res<Id> {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(Cow::Borrowed(self.descr()))
     }
 }
 
-impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TargetDataLayoutErrors<'_> {
-    fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> Diag<'_, G> {
+impl<G: EmissionGuarantee> Diagnostic<'_, G> for TargetDataLayoutErrors<'_> {
+    fn into_diag(self, dcx: &DiagCtxt, level: Level) -> Diag<'_, G> {
         match self {
             TargetDataLayoutErrors::InvalidAddressSpace { addr_space, err, cause } => {
                 Diag::new(dcx, level, fluent::errors_target_invalid_address_space)
@@ -297,8 +297,8 @@ pub struct SingleLabelManySpans {
     pub spans: Vec<Span>,
     pub label: &'static str,
 }
-impl AddToDiagnostic for SingleLabelManySpans {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for SingleLabelManySpans {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _: F,
@@ -315,20 +315,20 @@ pub struct ExpectedLifetimeParameter {
     pub count: usize,
 }
 
-impl IntoDiagnosticArg for DiagLocation {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for DiagLocation {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(Cow::from(self.to_string()))
     }
 }
 
-impl IntoDiagnosticArg for Backtrace {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for Backtrace {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(Cow::from(self.to_string()))
     }
 }
 
-impl IntoDiagnosticArg for Level {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for Level {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(Cow::from(self.to_string()))
     }
 }
@@ -342,8 +342,8 @@ pub struct IndicateAnonymousLifetime {
     pub suggestion: String,
 }
 
-impl IntoDiagnosticArg for type_ir::ClosureKind {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for type_ir::ClosureKind {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(self.as_str().into())
     }
 }
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 76b44f73f47..d4f884d49ea 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -37,9 +37,9 @@ extern crate self as rustc_errors;
 
 pub use codes::*;
 pub use diagnostic::{
-    AddToDiagnostic, BugAbort, DecorateLint, Diag, DiagArg, DiagArgMap, DiagArgName, DiagArgValue,
-    DiagInner, DiagStyledString, EmissionGuarantee, FatalAbort, IntoDiagnostic, IntoDiagnosticArg,
-    StringPart, Subdiag, SubdiagMessageOp,
+    BugAbort, Diag, DiagArg, DiagArgMap, DiagArgName, DiagArgValue, DiagInner, DiagStyledString,
+    Diagnostic, EmissionGuarantee, FatalAbort, IntoDiagArg, LintDiagnostic, StringPart, Subdiag,
+    SubdiagMessageOp, Subdiagnostic,
 };
 pub use diagnostic_impls::{
     DiagArgFromDisplay, DiagSymbolList, ExpectedLifetimeParameter, IndicateAnonymousLifetime,
@@ -442,8 +442,8 @@ struct DiagCtxtInner {
     emitter: Box<DynEmitter>,
 
     /// Must we produce a diagnostic to justify the use of the expensive
-    /// `trimmed_def_paths` function?
-    must_produce_diag: bool,
+    /// `trimmed_def_paths` function? Backtrace is the location of the call.
+    must_produce_diag: Option<Backtrace>,
 
     /// Has this diagnostic context printed any diagnostics? (I.e. has
     /// `self.emitter.emit_diagnostic()` been called?
@@ -572,10 +572,11 @@ impl Drop for DiagCtxtInner {
         }
 
         if !self.has_printed && !self.suppressed_expected_diag && !std::thread::panicking() {
-            if self.must_produce_diag {
+            if let Some(backtrace) = &self.must_produce_diag {
                 panic!(
-                    "must_produce_diag: trimmed_def_paths called but no diagnostics emitted; \
-                       use `DelayDm` for lints or `with_no_trimmed_paths` for debugging"
+                    "must_produce_diag: `trimmed_def_paths` called but no diagnostics emitted; \
+                       use `DelayDm` for lints or `with_no_trimmed_paths` for debugging. \
+                       called at: {backtrace}"
                 );
             }
         }
@@ -721,7 +722,7 @@ impl DiagCtxt {
         *delayed_bugs = Default::default();
         *deduplicated_err_count = 0;
         *deduplicated_warn_count = 0;
-        *must_produce_diag = false;
+        *must_produce_diag = None;
         *has_printed = false;
         *suppressed_expected_diag = false;
         *taught_diagnostics = Default::default();
@@ -1091,8 +1092,13 @@ impl DiagCtxt {
 
     /// Used when trimmed_def_paths is called and we must produce a diagnostic
     /// to justify its cost.
+    #[track_caller]
     pub fn set_must_produce_diag(&self) {
-        self.inner.borrow_mut().must_produce_diag = true;
+        assert!(
+            self.inner.borrow().must_produce_diag.is_none(),
+            "should only need to collect a backtrace once"
+        );
+        self.inner.borrow_mut().must_produce_diag = Some(Backtrace::capture());
     }
 }
 
@@ -1134,12 +1140,12 @@ impl DiagCtxt {
     }
 
     #[track_caller]
-    pub fn create_bug<'a>(&'a self, bug: impl IntoDiagnostic<'a, BugAbort>) -> Diag<'a, BugAbort> {
-        bug.into_diagnostic(self, Bug)
+    pub fn create_bug<'a>(&'a self, bug: impl Diagnostic<'a, BugAbort>) -> Diag<'a, BugAbort> {
+        bug.into_diag(self, Bug)
     }
 
     #[track_caller]
-    pub fn emit_bug<'a>(&'a self, bug: impl IntoDiagnostic<'a, BugAbort>) -> ! {
+    pub fn emit_bug<'a>(&'a self, bug: impl Diagnostic<'a, BugAbort>) -> ! {
         self.create_bug(bug).emit()
     }
 
@@ -1174,29 +1180,26 @@ impl DiagCtxt {
     #[track_caller]
     pub fn create_fatal<'a>(
         &'a self,
-        fatal: impl IntoDiagnostic<'a, FatalAbort>,
+        fatal: impl Diagnostic<'a, FatalAbort>,
     ) -> Diag<'a, FatalAbort> {
-        fatal.into_diagnostic(self, Fatal)
+        fatal.into_diag(self, Fatal)
     }
 
     #[track_caller]
-    pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, FatalAbort>) -> ! {
+    pub fn emit_fatal<'a>(&'a self, fatal: impl Diagnostic<'a, FatalAbort>) -> ! {
         self.create_fatal(fatal).emit()
     }
 
     #[track_caller]
     pub fn create_almost_fatal<'a>(
         &'a self,
-        fatal: impl IntoDiagnostic<'a, FatalError>,
+        fatal: impl Diagnostic<'a, FatalError>,
     ) -> Diag<'a, FatalError> {
-        fatal.into_diagnostic(self, Fatal)
+        fatal.into_diag(self, Fatal)
     }
 
     #[track_caller]
-    pub fn emit_almost_fatal<'a>(
-        &'a self,
-        fatal: impl IntoDiagnostic<'a, FatalError>,
-    ) -> FatalError {
+    pub fn emit_almost_fatal<'a>(&'a self, fatal: impl Diagnostic<'a, FatalError>) -> FatalError {
         self.create_almost_fatal(fatal).emit()
     }
 
@@ -1234,12 +1237,12 @@ impl DiagCtxt {
     }
 
     #[track_caller]
-    pub fn create_err<'a>(&'a self, err: impl IntoDiagnostic<'a>) -> Diag<'a> {
-        err.into_diagnostic(self, Error)
+    pub fn create_err<'a>(&'a self, err: impl Diagnostic<'a>) -> Diag<'a> {
+        err.into_diag(self, Error)
     }
 
     #[track_caller]
-    pub fn emit_err<'a>(&'a self, err: impl IntoDiagnostic<'a>) -> ErrorGuaranteed {
+    pub fn emit_err<'a>(&'a self, err: impl Diagnostic<'a>) -> ErrorGuaranteed {
         self.create_err(err).emit()
     }
 
@@ -1297,12 +1300,12 @@ impl DiagCtxt {
     }
 
     #[track_caller]
-    pub fn create_warn<'a>(&'a self, warning: impl IntoDiagnostic<'a, ()>) -> Diag<'a, ()> {
-        warning.into_diagnostic(self, Warning)
+    pub fn create_warn<'a>(&'a self, warning: impl Diagnostic<'a, ()>) -> Diag<'a, ()> {
+        warning.into_diag(self, Warning)
     }
 
     #[track_caller]
-    pub fn emit_warn<'a>(&'a self, warning: impl IntoDiagnostic<'a, ()>) {
+    pub fn emit_warn<'a>(&'a self, warning: impl Diagnostic<'a, ()>) {
         self.create_warn(warning).emit()
     }
 
@@ -1335,12 +1338,12 @@ impl DiagCtxt {
     }
 
     #[track_caller]
-    pub fn create_note<'a>(&'a self, note: impl IntoDiagnostic<'a, ()>) -> Diag<'a, ()> {
-        note.into_diagnostic(self, Note)
+    pub fn create_note<'a>(&'a self, note: impl Diagnostic<'a, ()>) -> Diag<'a, ()> {
+        note.into_diag(self, Note)
     }
 
     #[track_caller]
-    pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, ()>) {
+    pub fn emit_note<'a>(&'a self, note: impl Diagnostic<'a, ()>) {
         self.create_note(note).emit()
     }
 
@@ -1387,7 +1390,7 @@ impl DiagCtxtInner {
             deduplicated_err_count: 0,
             deduplicated_warn_count: 0,
             emitter,
-            must_produce_diag: false,
+            must_produce_diag: None,
             has_printed: false,
             suppressed_expected_diag: false,
             taught_diagnostics: Default::default(),
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 0d51e1e46e0..38848b22cb2 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -389,7 +389,7 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ),
 
     // Entry point:
-    gated!(unix_sigpipe, Normal, template!(Word, NameValueStr: "inherit|sig_ign|sig_dfl"), ErrorFollowing, experimental!(unix_sigpipe)),
+    gated!(unix_sigpipe, Normal, template!(NameValueStr: "inherit|sig_ign|sig_dfl"), ErrorFollowing, experimental!(unix_sigpipe)),
     ungated!(start, Normal, template!(Word), WarnFollowing, @only_local: true),
     ungated!(no_start, CrateLevel, template!(Word), WarnFollowing, @only_local: true),
     ungated!(no_main, CrateLevel, template!(Word), WarnFollowing, @only_local: true),
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index a10f4b934ea..52421fce867 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -471,6 +471,8 @@ declare_features! (
     (unstable, fn_align, "1.53.0", Some(82232)),
     /// Support delegating implementation of functions to other already implemented functions.
     (incomplete, fn_delegation, "1.76.0", Some(118212)),
+    /// Allows impls for the Freeze trait.
+    (internal, freeze_impls, "CURRENT_RUSTC_VERSION", Some(121675)),
     /// Allows defining gen blocks and `gen fn`.
     (unstable, gen_blocks, "1.75.0", Some(117078)),
     /// Infer generic args for both consts and types.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 7d5b4c0f06d..18dabe67dae 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1510,7 +1510,7 @@ impl fmt::Display for ConstContext {
     }
 }
 
-// NOTE: `IntoDiagnosticArg` impl for `ConstContext` lives in `rustc_errors`
+// NOTE: `IntoDiagArg` impl for `ConstContext` lives in `rustc_errors`
 // due to a cyclical dependency between hir that crate.
 
 /// A literal.
diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
index 6d8a5bc0e90..17e0aeb044c 100644
--- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
@@ -408,7 +408,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
             // Create the generic arguments for the associated type or constant by joining the
             // parent arguments (the arguments of the trait) and the own arguments (the ones of
             // the associated item itself) and construct an alias type using them.
-            candidate.map_bound(|trait_ref| {
+            let alias_ty = candidate.map_bound(|trait_ref| {
                 let ident = Ident::new(assoc_item.name, binding.ident.span);
                 let item_segment = hir::PathSegment {
                     ident,
@@ -430,7 +430,25 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
                 // *constants* to represent *const projections*. Alias *term* would be a more
                 // appropriate name but alas.
                 ty::AliasTy::new(tcx, assoc_item.def_id, alias_args)
-            })
+            });
+
+            // Provide the resolved type of the associated constant to `type_of(AnonConst)`.
+            if !speculative
+                && let hir::TypeBindingKind::Equality { term: hir::Term::Const(anon_const) } =
+                    binding.kind
+            {
+                let ty = alias_ty.map_bound(|ty| tcx.type_of(ty.def_id).instantiate(tcx, ty.args));
+                // Since the arguments passed to the alias type above may contain early-bound
+                // generic parameters, the instantiated type may contain some as well.
+                // Therefore wrap it in `EarlyBinder`.
+                // FIXME(fmease): Reject escaping late-bound vars.
+                tcx.feed_anon_const_type(
+                    anon_const.def_id,
+                    ty::EarlyBinder::bind(ty.skip_binder()),
+                );
+            }
+
+            alias_ty
         };
 
         match binding.kind {
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 1b24c2b61fd..cb739ac48a8 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -347,7 +347,7 @@ fn check_opaque_meets_bounds<'tcx>(
 
     let infcx = tcx
         .infer_ctxt()
-        .with_opaque_type_inference(DefiningAnchor::Bind(defining_use_anchor))
+        .with_opaque_type_inference(DefiningAnchor::bind(tcx, defining_use_anchor))
         .build();
     let ocx = ObligationCtxt::new(&infcx);
 
@@ -1558,7 +1558,7 @@ pub(super) fn check_coroutine_obligations(
         .ignoring_regions()
         // Bind opaque types to type checking root, as they should have been checked by borrowck,
         // but may show up in some cases, like when (root) obligations are stalled in the new solver.
-        .with_opaque_type_inference(DefiningAnchor::Bind(typeck.hir_owner.def_id))
+        .with_opaque_type_inference(DefiningAnchor::bind(tcx, typeck.hir_owner.def_id))
         .build();
 
     let mut fulfillment_cx = <dyn TraitEngine<'_>>::new(&infcx);
diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs
index fc7a73e12be..054a3af212a 100644
--- a/compiler/rustc_hir_analysis/src/coherence/mod.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs
@@ -10,6 +10,7 @@ use rustc_errors::{codes::*, struct_span_code_err};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
+use rustc_session::parse::feature_err;
 use rustc_span::{sym, ErrorGuaranteed};
 use rustc_trait_selection::traits;
 
@@ -49,6 +50,19 @@ fn enforce_trait_manually_implementable(
 ) -> Result<(), ErrorGuaranteed> {
     let impl_header_span = tcx.def_span(impl_def_id);
 
+    if tcx.lang_items().freeze_trait() == Some(trait_def_id) {
+        if !tcx.features().freeze_impls {
+            feature_err(
+                &tcx.sess,
+                sym::freeze_impls,
+                impl_header_span,
+                "explicit impls for the `Freeze` trait are not permitted",
+            )
+            .with_span_label(impl_header_span, format!("impl of `Freeze` not allowed"))
+            .emit();
+        }
+    }
+
     // Disallow *all* explicit impls of traits marked `#[rustc_deny_explicit_impl]`
     if trait_def.deny_explicit_impl {
         let trait_name = tcx.item_name(trait_def_id);
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index a1345c2d81b..598dba922d0 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -79,37 +79,6 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
                 .expect("const parameter types cannot be generic");
         }
 
-        Node::TypeBinding(binding @ &TypeBinding { hir_id: binding_id, .. })
-            if let Node::TraitRef(trait_ref) = tcx.parent_hir_node(binding_id) =>
-        {
-            let Some(trait_def_id) = trait_ref.trait_def_id() else {
-                return Ty::new_error_with_message(
-                    tcx,
-                    tcx.def_span(def_id),
-                    "Could not find trait",
-                );
-            };
-            let assoc_items = tcx.associated_items(trait_def_id);
-            let assoc_item = assoc_items.find_by_name_and_kind(
-                tcx,
-                binding.ident,
-                ty::AssocKind::Const,
-                def_id.to_def_id(),
-            );
-            return if let Some(assoc_item) = assoc_item {
-                tcx.type_of(assoc_item.def_id)
-                    .no_bound_vars()
-                    .expect("const parameter types cannot be generic")
-            } else {
-                // FIXME(associated_const_equality): add a useful error message here.
-                Ty::new_error_with_message(
-                    tcx,
-                    tcx.def_span(def_id),
-                    "Could not find associated const on trait",
-                )
-            };
-        }
-
         // This match arm is for when the def_id appears in a GAT whose
         // path can't be resolved without typechecking e.g.
         //
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
index dcb01a117b0..d370efc9d0e 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -5,22 +5,20 @@ use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::{self as hir, def, Expr, ImplItem, Item, Node, TraitItem};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
-use rustc_span::{sym, ErrorGuaranteed, DUMMY_SP};
+use rustc_span::{sym, DUMMY_SP};
 
 use crate::errors::{TaitForwardCompat, TypeOf, UnconstrainedOpaqueType};
 
-pub fn test_opaque_hidden_types(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
-    let mut res = Ok(());
+pub fn test_opaque_hidden_types(tcx: TyCtxt<'_>) {
     if tcx.has_attr(CRATE_DEF_ID, sym::rustc_hidden_type_of_opaques) {
         for id in tcx.hir().items() {
             if matches!(tcx.def_kind(id.owner_id), DefKind::OpaqueTy) {
                 let type_of = tcx.type_of(id.owner_id).instantiate_identity();
 
-                res = Err(tcx.dcx().emit_err(TypeOf { span: tcx.def_span(id.owner_id), type_of }));
+                tcx.dcx().emit_err(TypeOf { span: tcx.def_span(id.owner_id), type_of });
             }
         }
     }
-    res
 }
 
 /// Checks "defining uses" of opaque `impl Trait` in associated types.
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 26349cd1c65..175991b1be2 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -2,7 +2,7 @@
 
 use crate::fluent_generated as fluent;
 use rustc_errors::{
-    codes::*, Applicability, Diag, DiagCtxt, EmissionGuarantee, IntoDiagnostic, Level, MultiSpan,
+    codes::*, Applicability, Diag, DiagCtxt, Diagnostic, EmissionGuarantee, Level, MultiSpan,
 };
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_middle::ty::Ty;
@@ -355,10 +355,10 @@ pub struct MissingTypeParams {
     pub empty_generic_args: bool,
 }
 
-// Manual implementation of `IntoDiagnostic` to be able to call `span_to_snippet`.
-impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for MissingTypeParams {
+// Manual implementation of `Diagnostic` to be able to call `span_to_snippet`.
+impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for MissingTypeParams {
     #[track_caller]
-    fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
+    fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
         let mut err = Diag::new(dcx, level, fluent::hir_analysis_missing_type_params);
         err.span(self.span);
         err.code(E0393);
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index e056c0e84cf..696c47710c2 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -98,7 +98,6 @@ mod outlives;
 pub mod structured_errors;
 mod variance;
 
-use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_middle::middle;
 use rustc_middle::query::Providers;
@@ -156,11 +155,13 @@ pub fn provide(providers: &mut Providers) {
     hir_wf_check::provide(providers);
 }
 
-pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
+pub fn check_crate(tcx: TyCtxt<'_>) {
     let _prof_timer = tcx.sess.timer("type_check_crate");
 
     if tcx.features().rustc_attrs {
-        tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx))?;
+        tcx.sess.time("outlives_testing", || outlives::test::test_inferred_outlives(tcx));
+        tcx.sess.time("variance_testing", || variance::test::test_variance(tcx));
+        collect::test_opaque_hidden_types(tcx);
     }
 
     tcx.sess.time("coherence_checking", || {
@@ -176,14 +177,6 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
         let _ = tcx.ensure().crate_inherent_impls_overlap_check(());
     });
 
-    if tcx.features().rustc_attrs {
-        tcx.sess.time("variance_testing", || variance::test::test_variance(tcx))?;
-    }
-
-    if tcx.features().rustc_attrs {
-        collect::test_opaque_hidden_types(tcx)?;
-    }
-
     // Make sure we evaluate all static and (non-associated) const items, even if unused.
     // If any of these fail to evaluate, we do not want this crate to pass compilation.
     tcx.hir().par_body_owners(|item_def_id| {
@@ -198,21 +191,6 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
     // Freeze definitions as we don't add new ones at this point. This improves performance by
     // allowing lock-free access to them.
     tcx.untracked().definitions.freeze();
-
-    // FIXME: Remove this when we implement creating `DefId`s
-    // for anon constants during their parents' typeck.
-    // Typeck all body owners in parallel will produce queries
-    // cycle errors because it may typeck on anon constants directly.
-    tcx.hir().par_body_owners(|item_def_id| {
-        let def_kind = tcx.def_kind(item_def_id);
-        if !matches!(def_kind, DefKind::AnonConst) {
-            tcx.ensure().typeck(item_def_id);
-        }
-    });
-
-    tcx.ensure().check_unused_traits(());
-
-    Ok(())
 }
 
 /// A quasi-deprecated helper used in rustdoc and clippy to get
diff --git a/compiler/rustc_hir_analysis/src/outlives/test.rs b/compiler/rustc_hir_analysis/src/outlives/test.rs
index 60cd8c39fa0..dea3f1a9930 100644
--- a/compiler/rustc_hir_analysis/src/outlives/test.rs
+++ b/compiler/rustc_hir_analysis/src/outlives/test.rs
@@ -1,8 +1,7 @@
 use rustc_middle::ty::{self, TyCtxt};
-use rustc_span::{symbol::sym, ErrorGuaranteed};
+use rustc_span::symbol::sym;
 
-pub fn test_inferred_outlives(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
-    let mut res = Ok(());
+pub fn test_inferred_outlives(tcx: TyCtxt<'_>) {
     for id in tcx.hir().items() {
         // For unit testing: check for a special "rustc_outlives"
         // attribute and report an error with various results if found.
@@ -23,8 +22,7 @@ pub fn test_inferred_outlives(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
             for p in pred {
                 err.note(p);
             }
-            res = Err(err.emit());
+            err.emit();
         }
     }
-    res
 }
diff --git a/compiler/rustc_hir_analysis/src/variance/test.rs b/compiler/rustc_hir_analysis/src/variance/test.rs
index c211e1af046..5264d5aa26f 100644
--- a/compiler/rustc_hir_analysis/src/variance/test.rs
+++ b/compiler/rustc_hir_analysis/src/variance/test.rs
@@ -2,21 +2,19 @@ use rustc_hir::def::DefKind;
 use rustc_hir::def_id::CRATE_DEF_ID;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::sym;
-use rustc_span::ErrorGuaranteed;
 
 use crate::errors;
 
-pub fn test_variance(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
-    let mut res = Ok(());
+pub fn test_variance(tcx: TyCtxt<'_>) {
     if tcx.has_attr(CRATE_DEF_ID, sym::rustc_variance_of_opaques) {
         for id in tcx.hir().items() {
             if matches!(tcx.def_kind(id.owner_id), DefKind::OpaqueTy) {
                 let variances_of = tcx.variances_of(id.owner_id);
 
-                res = Err(tcx.dcx().emit_err(errors::VariancesOf {
+                tcx.dcx().emit_err(errors::VariancesOf {
                     span: tcx.def_span(id.owner_id),
                     variances_of: format!("{variances_of:?}"),
-                }));
+                });
             }
         }
     }
@@ -27,11 +25,10 @@ pub fn test_variance(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> {
         if tcx.has_attr(id.owner_id, sym::rustc_variance) {
             let variances_of = tcx.variances_of(id.owner_id);
 
-            res = Err(tcx.dcx().emit_err(errors::VariancesOf {
+            tcx.dcx().emit_err(errors::VariancesOf {
                 span: tcx.def_span(id.owner_id),
                 variances_of: format!("{variances_of:?}"),
-            }));
+            });
         }
     }
-    res
 }
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 502b9ba6451..df21b84f92e 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -3,8 +3,8 @@ use std::borrow::Cow;
 
 use crate::fluent_generated as fluent;
 use rustc_errors::{
-    codes::*, AddToDiagnostic, Applicability, Diag, DiagArgValue, EmissionGuarantee,
-    IntoDiagnosticArg, MultiSpan, SubdiagMessageOp,
+    codes::*, Applicability, Diag, DiagArgValue, EmissionGuarantee, IntoDiagArg, MultiSpan,
+    SubdiagMessageOp, Subdiagnostic,
 };
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_middle::ty::Ty;
@@ -42,8 +42,8 @@ pub enum ReturnLikeStatementKind {
     Become,
 }
 
-impl IntoDiagnosticArg for ReturnLikeStatementKind {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for ReturnLikeStatementKind {
+    fn into_diag_arg(self) -> DiagArgValue {
         let kind = match self {
             Self::Return => "return",
             Self::Become => "become",
@@ -194,8 +194,8 @@ pub struct TypeMismatchFruTypo {
     pub expr: Option<String>,
 }
 
-impl AddToDiagnostic for TypeMismatchFruTypo {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for TypeMismatchFruTypo {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -373,8 +373,8 @@ pub struct RemoveSemiForCoerce {
     pub semi: Span,
 }
 
-impl AddToDiagnostic for RemoveSemiForCoerce {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for RemoveSemiForCoerce {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -549,8 +549,8 @@ pub enum CastUnknownPointerSub {
     From(Span),
 }
 
-impl rustc_errors::AddToDiagnostic for CastUnknownPointerSub {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl rustc_errors::Subdiagnostic for CastUnknownPointerSub {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         f: F,
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index ceaae9cf49f..7e19e577d7d 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -26,8 +26,8 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_data_structures::unord::UnordMap;
 use rustc_errors::{
-    codes::*, pluralize, struct_span_code_err, AddToDiagnostic, Applicability, Diag,
-    ErrorGuaranteed, StashKey,
+    codes::*, pluralize, struct_span_code_err, Applicability, Diag, ErrorGuaranteed, StashKey,
+    Subdiagnostic,
 };
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
@@ -2600,7 +2600,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // We know by construction that `<expr>.await` is either on Rust 2015
             // or results in `ExprKind::Await`. Suggest switching the edition to 2018.
             err.note("to `.await` a `Future`, switch to Rust 2018 or later");
-            HelpUseLatestEdition::new().add_to_diagnostic(&mut err);
+            HelpUseLatestEdition::new().add_to_diag(&mut err);
         }
 
         err.emit()
diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs
index 4ad46845f0b..b0950ed2800 100644
--- a/compiler/rustc_hir_typeck/src/inherited.rs
+++ b/compiler/rustc_hir_typeck/src/inherited.rs
@@ -79,7 +79,7 @@ impl<'tcx> Inherited<'tcx> {
         let infcx = tcx
             .infer_ctxt()
             .ignoring_regions()
-            .with_opaque_type_inference(DefiningAnchor::Bind(def_id))
+            .with_opaque_type_inference(DefiningAnchor::bind(tcx, def_id))
             .build();
         let typeck_results = RefCell::new(ty::TypeckResults::new(hir_owner));
 
diff --git a/compiler/rustc_infer/messages.ftl b/compiler/rustc_infer/messages.ftl
index 2de87cbe631..e44a6ae3b3f 100644
--- a/compiler/rustc_infer/messages.ftl
+++ b/compiler/rustc_infer/messages.ftl
@@ -181,14 +181,6 @@ infer_more_targeted = {$has_param_name ->
 
 infer_msl_introduces_static = introduces a `'static` lifetime requirement
 infer_msl_unmet_req = because this has an unmet lifetime requirement
-infer_need_type_info_in_coroutine =
-    type inside {$coroutine_kind ->
-    [async_block] `async` block
-    [async_closure] `async` closure
-    [async_fn] `async fn` body
-    *[coroutine] coroutine
-    } must be known in this context
-
 
 infer_nothing = {""}
 
diff --git a/compiler/rustc_infer/src/errors/mod.rs b/compiler/rustc_infer/src/errors/mod.rs
index af09ac2de96..a3cf0d8e520 100644
--- a/compiler/rustc_infer/src/errors/mod.rs
+++ b/compiler/rustc_infer/src/errors/mod.rs
@@ -1,7 +1,7 @@
 use hir::GenericParamKind;
 use rustc_errors::{
-    codes::*, AddToDiagnostic, Applicability, Diag, DiagMessage, DiagStyledString,
-    EmissionGuarantee, IntoDiagnosticArg, MultiSpan, SubdiagMessageOp,
+    codes::*, Applicability, Diag, DiagMessage, DiagStyledString, EmissionGuarantee, IntoDiagArg,
+    MultiSpan, SubdiagMessageOp, Subdiagnostic,
 };
 use rustc_hir as hir;
 use rustc_hir::FnRetTy;
@@ -224,8 +224,8 @@ pub enum RegionOriginNote<'a> {
     },
 }
 
-impl AddToDiagnostic for RegionOriginNote<'_> {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for RegionOriginNote<'_> {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -289,8 +289,8 @@ pub enum LifetimeMismatchLabels {
     },
 }
 
-impl AddToDiagnostic for LifetimeMismatchLabels {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for LifetimeMismatchLabels {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -337,8 +337,8 @@ pub struct AddLifetimeParamsSuggestion<'a> {
     pub add_note: bool,
 }
 
-impl AddToDiagnostic for AddLifetimeParamsSuggestion<'_> {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -439,8 +439,8 @@ pub struct IntroducesStaticBecauseUnmetLifetimeReq {
     pub binding_span: Span,
 }
 
-impl AddToDiagnostic for IntroducesStaticBecauseUnmetLifetimeReq {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for IntroducesStaticBecauseUnmetLifetimeReq {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         mut self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -537,11 +537,11 @@ pub enum TyOrSig<'tcx> {
     ClosureSig(Highlighted<'tcx, Binder<'tcx, FnSig<'tcx>>>),
 }
 
-impl IntoDiagnosticArg for TyOrSig<'_> {
-    fn into_diagnostic_arg(self) -> rustc_errors::DiagArgValue {
+impl IntoDiagArg for TyOrSig<'_> {
+    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
         match self {
-            TyOrSig::Ty(ty) => ty.into_diagnostic_arg(),
-            TyOrSig::ClosureSig(sig) => sig.into_diagnostic_arg(),
+            TyOrSig::Ty(ty) => ty.into_diag_arg(),
+            TyOrSig::ClosureSig(sig) => sig.into_diag_arg(),
         }
     }
 }
@@ -758,8 +758,8 @@ pub struct ConsiderBorrowingParamHelp {
     pub spans: Vec<Span>,
 }
 
-impl AddToDiagnostic for ConsiderBorrowingParamHelp {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for ConsiderBorrowingParamHelp {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         f: F,
@@ -803,8 +803,8 @@ pub struct DynTraitConstraintSuggestion {
     pub ident: Ident,
 }
 
-impl AddToDiagnostic for DynTraitConstraintSuggestion {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for DynTraitConstraintSuggestion {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         f: F,
@@ -850,8 +850,8 @@ pub struct ReqIntroducedLocations {
     pub add_label: bool,
 }
 
-impl AddToDiagnostic for ReqIntroducedLocations {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for ReqIntroducedLocations {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         mut self,
         diag: &mut Diag<'_, G>,
         f: F,
@@ -873,8 +873,8 @@ pub struct MoreTargeted {
     pub ident: Symbol,
 }
 
-impl AddToDiagnostic for MoreTargeted {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for MoreTargeted {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -1296,8 +1296,8 @@ pub struct SuggestTuplePatternMany {
     pub compatible_variants: Vec<String>,
 }
 
-impl AddToDiagnostic for SuggestTuplePatternMany {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for SuggestTuplePatternMany {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         f: F,
diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs
index 7bb71d47031..7b962b01408 100644
--- a/compiler/rustc_infer/src/errors/note_and_explain.rs
+++ b/compiler/rustc_infer/src/errors/note_and_explain.rs
@@ -1,6 +1,6 @@
 use crate::fluent_generated as fluent;
 use crate::infer::error_reporting::nice_region_error::find_anon_type;
-use rustc_errors::{AddToDiagnostic, Diag, EmissionGuarantee, IntoDiagnosticArg, SubdiagMessageOp};
+use rustc_errors::{Diag, EmissionGuarantee, IntoDiagArg, SubdiagMessageOp, Subdiagnostic};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::{symbol::kw, Span};
 
@@ -107,8 +107,8 @@ pub enum SuffixKind {
     ReqByBinding,
 }
 
-impl IntoDiagnosticArg for PrefixKind {
-    fn into_diagnostic_arg(self) -> rustc_errors::DiagArgValue {
+impl IntoDiagArg for PrefixKind {
+    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
         let kind = match self {
             Self::Empty => "empty",
             Self::RefValidFor => "ref_valid_for",
@@ -129,8 +129,8 @@ impl IntoDiagnosticArg for PrefixKind {
     }
 }
 
-impl IntoDiagnosticArg for SuffixKind {
-    fn into_diagnostic_arg(self) -> rustc_errors::DiagArgValue {
+impl IntoDiagArg for SuffixKind {
+    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
         let kind = match self {
             Self::Empty => "empty",
             Self::Continues => "continues",
@@ -159,8 +159,8 @@ impl RegionExplanation<'_> {
     }
 }
 
-impl AddToDiagnostic for RegionExplanation<'_> {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for RegionExplanation<'_> {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         f: F,
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index ea5c6b8c057..222c0a39542 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -61,7 +61,7 @@ use crate::traits::{
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_errors::{
     codes::*, pluralize, struct_span_code_err, Applicability, Diag, DiagCtxt, DiagStyledString,
-    ErrorGuaranteed, IntoDiagnosticArg,
+    ErrorGuaranteed, IntoDiagArg,
 };
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
@@ -2895,11 +2895,11 @@ impl<'tcx> ObligationCause<'tcx> {
     }
 }
 
-/// Newtype to allow implementing IntoDiagnosticArg
+/// Newtype to allow implementing IntoDiagArg
 pub struct ObligationCauseAsDiagArg<'tcx>(pub ObligationCause<'tcx>);
 
-impl IntoDiagnosticArg for ObligationCauseAsDiagArg<'_> {
-    fn into_diagnostic_arg(self) -> rustc_errors::DiagArgValue {
+impl IntoDiagArg for ObligationCauseAsDiagArg<'_> {
+    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
         use crate::traits::ObligationCauseCode::*;
         let kind = match self.0.code() {
             CompareImplItemObligation { kind: ty::AssocKind::Fn, .. } => "method_compat",
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index 6c968c488fe..13e2152e45e 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -5,7 +5,7 @@ use crate::errors::{
 use crate::infer::error_reporting::TypeErrCtxt;
 use crate::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use crate::infer::InferCtxt;
-use rustc_errors::{codes::*, Diag, IntoDiagnosticArg};
+use rustc_errors::{codes::*, Diag, IntoDiagArg};
 use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_hir::def::{CtorOf, DefKind, Namespace};
@@ -133,8 +133,8 @@ impl InferenceDiagnosticsParentData {
     }
 }
 
-impl IntoDiagnosticArg for UnderspecifiedArgKind {
-    fn into_diagnostic_arg(self) -> rustc_errors::DiagArgValue {
+impl IntoDiagArg for UnderspecifiedArgKind {
+    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
         let kind = match self {
             Self::Type { .. } => "type",
             Self::Const { is_parameter: true } => "const_with_param",
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
index aa700005a3a..84bfa5b5af7 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/different_lifetimes.rs
@@ -11,7 +11,7 @@ use crate::infer::lexical_region_resolve::RegionResolutionError;
 use crate::infer::SubregionOrigin;
 use crate::infer::TyCtxt;
 
-use rustc_errors::AddToDiagnostic;
+use rustc_errors::Subdiagnostic;
 use rustc_errors::{Diag, ErrorGuaranteed};
 use rustc_hir::Ty;
 use rustc_middle::ty::Region;
@@ -145,5 +145,5 @@ pub fn suggest_adding_lifetime_params<'tcx>(
     err: &mut Diag<'_>,
 ) {
     let suggestion = AddLifetimeParamsSuggestion { tcx, sub, ty_sup, ty_sub, add_note: false };
-    suggestion.add_to_diagnostic(err);
+    suggestion.add_to_diag(err);
 }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
index d6595a0c114..98719e240bd 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
@@ -8,7 +8,7 @@ use crate::infer::ValuePairs;
 use crate::infer::{SubregionOrigin, TypeTrace};
 use crate::traits::{ObligationCause, ObligationCauseCode};
 use rustc_data_structures::intern::Interned;
-use rustc_errors::{Diag, IntoDiagnosticArg};
+use rustc_errors::{Diag, IntoDiagArg};
 use rustc_hir::def::Namespace;
 use rustc_hir::def_id::DefId;
 use rustc_middle::ty::error::ExpectedFound;
@@ -26,11 +26,11 @@ pub struct Highlighted<'tcx, T> {
     value: T,
 }
 
-impl<'tcx, T> IntoDiagnosticArg for Highlighted<'tcx, T>
+impl<'tcx, T> IntoDiagArg for Highlighted<'tcx, T>
 where
     T: for<'a> Print<'tcx, FmtPrinter<'a, 'tcx>>,
 {
-    fn into_diagnostic_arg(self) -> rustc_errors::DiagArgValue {
+    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
         rustc_errors::DiagArgValue::Str(self.to_string().into())
     }
 }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
index adde45f081a..afcb4a182fa 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -9,7 +9,7 @@ use crate::infer::lexical_region_resolve::RegionResolutionError;
 use crate::infer::{SubregionOrigin, TypeTrace};
 use crate::traits::{ObligationCauseCode, UnifyReceiverContext};
 use rustc_data_structures::fx::FxIndexSet;
-use rustc_errors::{AddToDiagnostic, Applicability, Diag, ErrorGuaranteed, MultiSpan};
+use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, Subdiagnostic};
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{walk_ty, Visitor};
 use rustc_hir::{
@@ -234,7 +234,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         if let (Some(ident), true) = (override_error_code, fn_returns.is_empty()) {
             // Provide a more targeted error code and description.
             let retarget_subdiag = MoreTargeted { ident };
-            retarget_subdiag.add_to_diagnostic(&mut err);
+            retarget_subdiag.add_to_diag(&mut err);
         }
 
         let arg = match param.param.pat.simple_ident() {
@@ -532,7 +532,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             hir_v.visit_ty(self_ty);
             for &span in &traits {
                 let subdiag = DynTraitConstraintSuggestion { span, ident };
-                subdiag.add_to_diagnostic(err);
+                subdiag.add_to_diag(err);
                 suggested = true;
             }
         }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs
index 2c369b5ad60..3ae1165d2a4 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs
@@ -5,7 +5,7 @@ use crate::errors::{
 use crate::fluent_generated as fluent;
 use crate::infer::error_reporting::{note_and_explain_region, TypeErrCtxt};
 use crate::infer::{self, SubregionOrigin};
-use rustc_errors::{AddToDiagnostic, Diag};
+use rustc_errors::{Diag, Subdiagnostic};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_middle::traits::ObligationCauseCode;
 use rustc_middle::ty::error::TypeError;
@@ -22,13 +22,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                 requirement: ObligationCauseAsDiagArg(trace.cause.clone()),
                 expected_found: self.values_str(trace.values).map(|(e, f, _)| (e, f)),
             }
-            .add_to_diagnostic(err),
+            .add_to_diag(err),
             infer::Reborrow(span) => {
-                RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diagnostic(err)
+                RegionOriginNote::Plain { span, msg: fluent::infer_reborrow }.add_to_diag(err)
             }
             infer::RelateObjectBound(span) => {
                 RegionOriginNote::Plain { span, msg: fluent::infer_relate_object_bound }
-                    .add_to_diagnostic(err);
+                    .add_to_diag(err);
             }
             infer::ReferenceOutlivesReferent(ty, span) => {
                 RegionOriginNote::WithName {
@@ -37,7 +37,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     name: &self.ty_to_string(ty),
                     continues: false,
                 }
-                .add_to_diagnostic(err);
+                .add_to_diag(err);
             }
             infer::RelateParamBound(span, ty, opt_span) => {
                 RegionOriginNote::WithName {
@@ -46,19 +46,19 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     name: &self.ty_to_string(ty),
                     continues: opt_span.is_some(),
                 }
-                .add_to_diagnostic(err);
+                .add_to_diag(err);
                 if let Some(span) = opt_span {
                     RegionOriginNote::Plain { span, msg: fluent::infer_relate_param_bound_2 }
-                        .add_to_diagnostic(err);
+                        .add_to_diag(err);
                 }
             }
             infer::RelateRegionParamBound(span) => {
                 RegionOriginNote::Plain { span, msg: fluent::infer_relate_region_param_bound }
-                    .add_to_diagnostic(err);
+                    .add_to_diag(err);
             }
             infer::CompareImplItemObligation { span, .. } => {
                 RegionOriginNote::Plain { span, msg: fluent::infer_compare_impl_item_obligation }
-                    .add_to_diagnostic(err);
+                    .add_to_diag(err);
             }
             infer::CheckAssociatedTypeBounds { ref parent, .. } => {
                 self.note_region_origin(err, parent);
@@ -68,7 +68,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     span,
                     msg: fluent::infer_ascribe_user_type_prove_predicate,
                 }
-                .add_to_diagnostic(err);
+                .add_to_diag(err);
             }
         }
     }
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 15cdd6a910e..89e4e88b3df 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -242,9 +242,10 @@ pub struct InferCtxt<'tcx> {
     /// short lived InferCtxt within queries. The opaque type obligations are forwarded
     /// to the outside until the end up in an `InferCtxt` for typeck or borrowck.
     ///
-    /// Its default value is `DefiningAnchor::Error`, this way it is easier to catch errors that
+    /// Its default value is `DefiningAnchor::Bind(&[])`, which means no opaque types may be defined.
+    /// This way it is easier to catch errors that
     /// might come up during inference or typeck.
-    pub defining_use_anchor: DefiningAnchor,
+    pub defining_use_anchor: DefiningAnchor<'tcx>,
 
     /// Whether this inference context should care about region obligations in
     /// the root universe. Most notably, this is used during hir typeck as region
@@ -605,7 +606,7 @@ impl fmt::Display for FixupError {
 /// Used to configure inference contexts before their creation.
 pub struct InferCtxtBuilder<'tcx> {
     tcx: TyCtxt<'tcx>,
-    defining_use_anchor: DefiningAnchor,
+    defining_use_anchor: DefiningAnchor<'tcx>,
     considering_regions: bool,
     skip_leak_check: bool,
     /// Whether we are in coherence mode.
@@ -620,7 +621,7 @@ impl<'tcx> TyCtxt<'tcx> {
     fn infer_ctxt(self) -> InferCtxtBuilder<'tcx> {
         InferCtxtBuilder {
             tcx: self,
-            defining_use_anchor: DefiningAnchor::Error,
+            defining_use_anchor: DefiningAnchor::Bind(ty::List::empty()),
             considering_regions: true,
             skip_leak_check: false,
             intercrate: false,
@@ -636,7 +637,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> {
     /// It is only meant to be called in two places, for typeck
     /// (via `Inherited::build`) and for the inference context used
     /// in mir borrowck.
-    pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor) -> Self {
+    pub fn with_opaque_type_inference(mut self, defining_use_anchor: DefiningAnchor<'tcx>) -> Self {
         self.defining_use_anchor = defining_use_anchor;
         self
     }
@@ -1208,13 +1209,11 @@ impl<'tcx> InferCtxt<'tcx> {
 
     #[instrument(level = "debug", skip(self), ret)]
     pub fn take_opaque_types(&self) -> opaque_types::OpaqueTypeMap<'tcx> {
-        debug_assert_ne!(self.defining_use_anchor, DefiningAnchor::Error);
         std::mem::take(&mut self.inner.borrow_mut().opaque_type_storage.opaque_types)
     }
 
     #[instrument(level = "debug", skip(self), ret)]
     pub fn clone_opaque_types(&self) -> opaque_types::OpaqueTypeMap<'tcx> {
-        debug_assert_ne!(self.defining_use_anchor, DefiningAnchor::Error);
         self.inner.borrow().opaque_type_storage.opaque_types.clone()
     }
 
diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
index 3d6829ba657..a6f8115c27e 100644
--- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs
@@ -150,9 +150,6 @@ impl<'tcx> InferCtxt<'tcx> {
                         }
                     }
                     DefiningAnchor::Bubble => {}
-                    DefiningAnchor::Error => {
-                        return None;
-                    }
                 }
                 if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: b_def_id, .. }) = *b.kind() {
                     // We could accept this, but there are various ways to handle this situation, and we don't
@@ -378,28 +375,14 @@ impl<'tcx> InferCtxt<'tcx> {
     /// in its defining scope.
     #[instrument(skip(self), level = "trace", ret)]
     pub fn opaque_type_origin(&self, def_id: LocalDefId) -> Option<OpaqueTyOrigin> {
-        let opaque_hir_id = self.tcx.local_def_id_to_hir_id(def_id);
-        let parent_def_id = match self.defining_use_anchor {
-            DefiningAnchor::Bubble | DefiningAnchor::Error => return None,
+        let defined_opaque_types = match self.defining_use_anchor {
+            DefiningAnchor::Bubble => return None,
             DefiningAnchor::Bind(bind) => bind,
         };
 
         let origin = self.tcx.opaque_type_origin(def_id);
-        let in_definition_scope = match origin {
-            // Async `impl Trait`
-            hir::OpaqueTyOrigin::AsyncFn(parent) => parent == parent_def_id,
-            // Anonymous `impl Trait`
-            hir::OpaqueTyOrigin::FnReturn(parent) => parent == parent_def_id,
-            // Named `type Foo = impl Bar;`
-            hir::OpaqueTyOrigin::TyAlias { in_assoc_ty, .. } => {
-                if in_assoc_ty {
-                    self.tcx.opaque_types_defined_by(parent_def_id).contains(&def_id)
-                } else {
-                    may_define_opaque_type(self.tcx, parent_def_id, opaque_hir_id)
-                }
-            }
-        };
-        in_definition_scope.then_some(origin)
+
+        defined_opaque_types.contains(&def_id).then_some(origin)
     }
 }
 
@@ -656,43 +639,3 @@ impl<'tcx> InferCtxt<'tcx> {
         }
     }
 }
-
-/// Returns `true` if `opaque_hir_id` is a sibling or a child of a sibling of `def_id`.
-///
-/// Example:
-/// ```ignore UNSOLVED (is this a bug?)
-/// # #![feature(type_alias_impl_trait)]
-/// pub mod foo {
-///     pub mod bar {
-///         pub trait Bar { /* ... */ }
-///         pub type Baz = impl Bar;
-///
-///         # impl Bar for () {}
-///         fn f1() -> Baz { /* ... */ }
-///     }
-///     fn f2() -> bar::Baz { /* ... */ }
-/// }
-/// ```
-///
-/// Here, `def_id` is the `LocalDefId` of the defining use of the opaque type (e.g., `f1` or `f2`),
-/// and `opaque_hir_id` is the `HirId` of the definition of the opaque type `Baz`.
-/// For the above example, this function returns `true` for `f1` and `false` for `f2`.
-fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: LocalDefId, opaque_hir_id: hir::HirId) -> bool {
-    let mut hir_id = tcx.local_def_id_to_hir_id(def_id);
-
-    // Named opaque types can be defined by any siblings or children of siblings.
-    let scope = tcx.hir().get_defining_scope(opaque_hir_id);
-    // We walk up the node tree until we hit the root or the scope of the opaque type.
-    while hir_id != scope && hir_id != hir::CRATE_HIR_ID {
-        hir_id = tcx.hir().get_parent_item(hir_id).into();
-    }
-    // Syntactically, we are allowed to define the concrete type if:
-    let res = hir_id == scope;
-    trace!(
-        "may_define_opaque_type(def={:?}, opaque_node={:?}) = {}",
-        tcx.hir_node(hir_id),
-        tcx.hir_node(opaque_hir_id),
-        res
-    );
-    res
-}
diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs
index 284d965979e..1a82e6c6910 100644
--- a/compiler/rustc_interface/src/interface.rs
+++ b/compiler/rustc_interface/src/interface.rs
@@ -16,7 +16,7 @@ use rustc_parse::maybe_new_parser_from_source_str;
 use rustc_query_impl::QueryCtxt;
 use rustc_query_system::query::print_query_stack;
 use rustc_session::config::{self, Cfg, CheckCfg, ExpectedValues, Input, OutFileName};
-use rustc_session::filesearch::sysroot_candidates;
+use rustc_session::filesearch::{self, sysroot_candidates};
 use rustc_session::parse::ParseSess;
 use rustc_session::{lint, CompilerIO, EarlyDiagCtxt, Session};
 use rustc_span::source_map::FileLoader;
@@ -339,16 +339,53 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
 
             let early_dcx = EarlyDiagCtxt::new(config.opts.error_format);
 
-            let codegen_backend = if let Some(make_codegen_backend) = config.make_codegen_backend {
-                make_codegen_backend(&config.opts)
-            } else {
-                util::get_codegen_backend(
-                    &early_dcx,
-                    &config.opts.maybe_sysroot,
-                    config.opts.unstable_opts.codegen_backend.as_deref(),
-                )
+            let sysroot = filesearch::materialize_sysroot(config.opts.maybe_sysroot.clone());
+
+            let (codegen_backend, target_override) = match config.make_codegen_backend {
+                None => {
+                    // Build a target without override, so that it can override the backend if needed
+                    let target =
+                        config::build_target_config(&early_dcx, &config.opts, None, &sysroot);
+
+                    let backend = util::get_codegen_backend(
+                        &early_dcx,
+                        &sysroot,
+                        config.opts.unstable_opts.codegen_backend.as_deref(),
+                        &target,
+                    );
+
+                    // target_override is documented to be called before init(), so this is okay
+                    let target_override = backend.target_override(&config.opts);
+
+                    // Assert that we don't use target's override of the backend and
+                    // backend's override of the target at the same time
+                    if config.opts.unstable_opts.codegen_backend.is_none()
+                        && target.default_codegen_backend.is_some()
+                        && target_override.is_some()
+                    {
+                        rustc_middle::bug!(
+                            "Codegen backend requested target override even though the target requested the backend"
+                        );
+                    }
+
+                    (backend, target_override)
+                }
+                Some(make_codegen_backend) => {
+                    // N.B. `make_codegen_backend` takes precedence over `target.default_codegen_backend`,
+                    //      which is ignored in this case.
+                    let backend = make_codegen_backend(&config.opts);
+
+                    // target_override is documented to be called before init(), so this is okay
+                    let target_override = backend.target_override(&config.opts);
+
+                    (backend, target_override)
+                }
             };
 
+            // Re-build target with the (potential) override
+            let target_cfg =
+                config::build_target_config(&early_dcx, &config.opts, target_override, &sysroot);
+
             let temps_dir = config.opts.unstable_opts.temps_dir.as_deref().map(PathBuf::from);
 
             let bundle = match rustc_errors::fluent_bundle(
@@ -367,9 +404,6 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
             let mut locale_resources = Vec::from(config.locale_resources);
             locale_resources.push(codegen_backend.locale_resource());
 
-            // target_override is documented to be called before init(), so this is okay
-            let target_override = codegen_backend.target_override(&config.opts);
-
             let mut sess = rustc_session::build_session(
                 early_dcx,
                 config.opts,
@@ -384,7 +418,8 @@ pub fn run_compiler<R: Send>(config: Config, f: impl FnOnce(&Compiler) -> R + Se
                 locale_resources,
                 config.lint_caps,
                 config.file_loader,
-                target_override,
+                target_cfg,
+                sysroot,
                 util::rustc_version_str().unwrap_or("unknown"),
                 config.ice_file,
                 config.using_internal_features,
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 4b4c1d6cf67..4cc9ffdbb2f 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -734,19 +734,22 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
     });
 
     // passes are timed inside typeck
-    rustc_hir_analysis::check_crate(tcx)?;
+    rustc_hir_analysis::check_crate(tcx);
 
-    sess.time("MIR_borrow_checking", || {
+    sess.time("typeck_and_mir_analyses", || {
         tcx.hir().par_body_owners(|def_id| {
+            let def_kind = tcx.def_kind(def_id);
+            // FIXME: Remove this when we implement creating `DefId`s
+            // for anon constants during their parents' typeck.
+            // Typeck all body owners in parallel will produce queries
+            // cycle errors because it may typeck on anon constants directly.
+            if !matches!(def_kind, rustc_hir::def::DefKind::AnonConst) {
+                tcx.ensure().typeck(def_id);
+            }
             // Run unsafety check because it's responsible for stealing and
             // deallocating THIR.
             tcx.ensure().check_unsafety(def_id);
-            tcx.ensure().mir_borrowck(def_id)
-        });
-    });
-
-    sess.time("MIR_effect_checking", || {
-        for def_id in tcx.hir().body_owners() {
+            tcx.ensure().mir_borrowck(def_id);
             if !tcx.sess.opts.unstable_opts.thir_unsafeck {
                 rustc_mir_transform::check_unsafety::check_unsafety(tcx, def_id);
             }
@@ -761,16 +764,16 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
                 tcx.ensure().mir_drops_elaborated_and_const_checked(def_id);
                 tcx.ensure().unused_generic_params(ty::InstanceDef::Item(def_id.to_def_id()));
             }
-        }
-    });
 
-    tcx.hir().par_body_owners(|def_id| {
-        if tcx.is_coroutine(def_id.to_def_id()) {
-            tcx.ensure().mir_coroutine_witnesses(def_id);
-            tcx.ensure().check_coroutine_obligations(def_id);
-        }
+            if tcx.is_coroutine(def_id.to_def_id()) {
+                tcx.ensure().mir_coroutine_witnesses(def_id);
+                tcx.ensure().check_coroutine_obligations(def_id);
+            }
+        })
     });
 
+    tcx.ensure().check_unused_traits(());
+
     sess.time("layout_testing", || layout_test::test_layout(tcx));
     sess.time("abi_testing", || abi_test::test_abi(tcx));
 
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 4f15d1c1d3a..42fff01c11c 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -13,7 +13,7 @@ use rustc_session::config::{
 use rustc_session::lint::Level;
 use rustc_session::search_paths::SearchPath;
 use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
-use rustc_session::{build_session, getopts, CompilerIO, EarlyDiagCtxt, Session};
+use rustc_session::{build_session, filesearch, getopts, CompilerIO, EarlyDiagCtxt, Session};
 use rustc_span::edition::{Edition, DEFAULT_EDITION};
 use rustc_span::symbol::sym;
 use rustc_span::{FileName, SourceFileHashAlgorithm};
@@ -37,6 +37,12 @@ fn mk_session(matches: getopts::Matches) -> (Session, Cfg) {
         output_file: None,
         temps_dir,
     };
+
+    let sysroot = filesearch::materialize_sysroot(sessopts.maybe_sysroot.clone());
+
+    let target_cfg =
+        rustc_session::config::build_target_config(&early_dcx, &sessopts, None, &sysroot);
+
     let sess = build_session(
         early_dcx,
         sessopts,
@@ -46,7 +52,8 @@ fn mk_session(matches: getopts::Matches) -> (Session, Cfg) {
         vec![],
         Default::default(),
         None,
-        None,
+        target_cfg,
+        sysroot,
         "",
         None,
         Arc::default(),
@@ -685,7 +692,7 @@ fn test_unstable_options_tracking_hash() {
     untracked!(nll_facts, true);
     untracked!(no_analysis, true);
     untracked!(no_leak_check, true);
-    untracked!(no_parallel_llvm, true);
+    untracked!(no_parallel_backend, true);
     untracked!(parse_only, true);
     // `pre_link_arg` is omitted because it just forwards to `pre_link_args`.
     untracked!(pre_link_args, vec![String::from("abc"), String::from("def")]);
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 23bd2dac57e..829b00aabc1 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -14,13 +14,14 @@ use rustc_session::{filesearch, output, Session};
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::edition::Edition;
 use rustc_span::symbol::{sym, Symbol};
+use rustc_target::spec::Target;
 use session::EarlyDiagCtxt;
-use std::env;
 use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
 use std::path::{Path, PathBuf};
 use std::sync::atomic::{AtomicBool, Ordering};
 use std::sync::OnceLock;
 use std::thread;
+use std::{env, iter};
 
 /// Function pointer type that constructs a new CodegenBackend.
 pub type MakeBackendFn = fn() -> Box<dyn CodegenBackend>;
@@ -195,21 +196,25 @@ fn load_backend_from_dylib(early_dcx: &EarlyDiagCtxt, path: &Path) -> MakeBacken
 /// A name of `None` indicates that the default backend should be used.
 pub fn get_codegen_backend(
     early_dcx: &EarlyDiagCtxt,
-    maybe_sysroot: &Option<PathBuf>,
+    sysroot: &Path,
     backend_name: Option<&str>,
+    target: &Target,
 ) -> Box<dyn CodegenBackend> {
     static LOAD: OnceLock<unsafe fn() -> Box<dyn CodegenBackend>> = OnceLock::new();
 
     let load = LOAD.get_or_init(|| {
-        let default_codegen_backend = option_env!("CFG_DEFAULT_CODEGEN_BACKEND").unwrap_or("llvm");
+        let backend = backend_name
+            .or(target.default_codegen_backend.as_deref())
+            .or(option_env!("CFG_DEFAULT_CODEGEN_BACKEND"))
+            .unwrap_or("llvm");
 
-        match backend_name.unwrap_or(default_codegen_backend) {
+        match backend {
             filename if filename.contains('.') => {
                 load_backend_from_dylib(early_dcx, filename.as_ref())
             }
             #[cfg(feature = "llvm")]
             "llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new,
-            backend_name => get_codegen_sysroot(early_dcx, maybe_sysroot, backend_name),
+            backend_name => get_codegen_sysroot(early_dcx, sysroot, backend_name),
         }
     });
 
@@ -244,7 +249,7 @@ fn get_rustc_path_inner(bin_path: &str) -> Option<PathBuf> {
 #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
 fn get_codegen_sysroot(
     early_dcx: &EarlyDiagCtxt,
-    maybe_sysroot: &Option<PathBuf>,
+    sysroot: &Path,
     backend_name: &str,
 ) -> MakeBackendFn {
     // For now we only allow this function to be called once as it'll dlopen a
@@ -261,28 +266,28 @@ fn get_codegen_sysroot(
     let target = session::config::host_triple();
     let sysroot_candidates = sysroot_candidates();
 
-    let sysroot = maybe_sysroot
-        .iter()
-        .chain(sysroot_candidates.iter())
+    let sysroot = iter::once(sysroot)
+        .chain(sysroot_candidates.iter().map(<_>::as_ref))
         .map(|sysroot| {
             filesearch::make_target_lib_path(sysroot, target).with_file_name("codegen-backends")
         })
         .find(|f| {
             info!("codegen backend candidate: {}", f.display());
             f.exists()
-        });
-    let sysroot = sysroot.unwrap_or_else(|| {
-        let candidates = sysroot_candidates
-            .iter()
-            .map(|p| p.display().to_string())
-            .collect::<Vec<_>>()
-            .join("\n* ");
-        let err = format!(
-            "failed to find a `codegen-backends` folder \
+        })
+        .unwrap_or_else(|| {
+            let candidates = sysroot_candidates
+                .iter()
+                .map(|p| p.display().to_string())
+                .collect::<Vec<_>>()
+                .join("\n* ");
+            let err = format!(
+                "failed to find a `codegen-backends` folder \
                            in the sysroot candidates:\n* {candidates}"
-        );
-        early_dcx.early_fatal(err);
-    });
+            );
+            early_dcx.early_fatal(err);
+        });
+
     info!("probing {} for a codegen backend", sysroot.display());
 
     let d = sysroot.read_dir().unwrap_or_else(|e| {
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 63e2fe47659..d938a0ccb39 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -186,7 +186,7 @@ lint_deprecated_lint_name =
     .help = change it to {$replace}
 
 lint_diag_out_of_impl =
-    diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
+    diagnostics should only be created in `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls
 
 lint_drop_glue =
     types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped
@@ -562,8 +562,6 @@ lint_suspicious_double_ref_clone =
 lint_suspicious_double_ref_deref =
     using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type
 
-lint_trivial_untranslatable_diag = diagnostic with static strings only
-
 lint_ty_qualified = usage of qualified `ty::{$ty}`
     .suggestion = try importing it and using it unqualified
 
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 5f0af6aee6a..595dc08b081 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -44,7 +44,7 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree};
 use rustc_ast::visit::{FnCtxt, FnKind};
 use rustc_ast::{self as ast, *};
 use rustc_ast_pretty::pprust::{self, expr_to_string};
-use rustc_errors::{Applicability, DecorateLint, MultiSpan};
+use rustc_errors::{Applicability, LintDiagnostic, MultiSpan};
 use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, GateIssue, Stability};
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
@@ -327,7 +327,7 @@ impl UnsafeCode {
         &self,
         cx: &EarlyContext<'_>,
         span: Span,
-        decorate: impl for<'a> DecorateLint<'a, ()>,
+        decorate: impl for<'a> LintDiagnostic<'a, ()>,
     ) {
         // This comes from a macro that has `#[allow_internal_unsafe]`.
         if span.allows_unsafe() {
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 89cdde11726..8c0e5b17fd8 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -21,7 +21,7 @@ use crate::passes::{EarlyLintPassObject, LateLintPassObject};
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::sync;
 use rustc_data_structures::unord::UnordMap;
-use rustc_errors::{DecorateLint, Diag, DiagMessage, MultiSpan};
+use rustc_errors::{Diag, DiagMessage, LintDiagnostic, MultiSpan};
 use rustc_feature::Features;
 use rustc_hir as hir;
 use rustc_hir::def::Res;
@@ -563,13 +563,13 @@ pub trait LintContext {
         decorate: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>),
     );
 
-    /// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`,
+    /// Emit a lint at `span` from a lint struct (some type that implements `LintDiagnostic`,
     /// typically generated by `#[derive(LintDiagnostic)]`).
     fn emit_span_lint<S: Into<MultiSpan>>(
         &self,
         lint: &'static Lint,
         span: S,
-        decorator: impl for<'a> DecorateLint<'a, ()>,
+        decorator: impl for<'a> LintDiagnostic<'a, ()>,
     ) {
         self.opt_span_lint(lint, Some(span), decorator.msg(), |diag| {
             decorator.decorate_lint(diag);
@@ -590,9 +590,9 @@ pub trait LintContext {
         self.opt_span_lint(lint, Some(span), msg, decorate);
     }
 
-    /// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically
+    /// Emit a lint from a lint struct (some type that implements `LintDiagnostic`, typically
     /// generated by `#[derive(LintDiagnostic)]`).
-    fn emit_lint(&self, lint: &'static Lint, decorator: impl for<'a> DecorateLint<'a, ()>) {
+    fn emit_lint(&self, lint: &'static Lint, decorator: impl for<'a> LintDiagnostic<'a, ()>) {
         self.opt_span_lint(lint, None as Option<Span>, decorator.msg(), |diag| {
             decorator.decorate_lint(diag);
         });
diff --git a/compiler/rustc_lint/src/errors.rs b/compiler/rustc_lint/src/errors.rs
index d73f9e7a4a1..ee99e824a54 100644
--- a/compiler/rustc_lint/src/errors.rs
+++ b/compiler/rustc_lint/src/errors.rs
@@ -1,5 +1,5 @@
 use crate::fluent_generated as fluent;
-use rustc_errors::{codes::*, AddToDiagnostic, Diag, EmissionGuarantee, SubdiagMessageOp};
+use rustc_errors::{codes::*, Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic};
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_session::lint::Level;
 use rustc_span::{Span, Symbol};
@@ -23,8 +23,8 @@ pub enum OverruledAttributeSub {
     CommandLineSource,
 }
 
-impl AddToDiagnostic for OverruledAttributeSub {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for OverruledAttributeSub {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index e8fcf4132ea..153d91ce28c 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -351,15 +351,14 @@ declare_tool_lint! {
 
 declare_tool_lint! {
     /// The `diagnostic_outside_of_impl` lint detects calls to functions annotated with
-    /// `#[rustc_lint_diagnostics]` that are outside an `IntoDiagnostic`, `AddToDiagnostic`, or
-    /// `DecorateLint` impl, or a `#[derive(Diagnostic)]`, `#[derive(Subdiagnostic)]`,
-    /// `#[derive(DecorateLint)]` expansion.
+    /// `#[rustc_lint_diagnostics]` that are outside an `Diagnostic`, `Subdiagnostic`, or
+    /// `LintDiagnostic` impl (either hand-written or derived).
     ///
     /// More details on diagnostics implementations can be found
     /// [here](https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html).
     pub rustc::DIAGNOSTIC_OUTSIDE_OF_IMPL,
     Deny,
-    "prevent creation of diagnostics outside of `IntoDiagnostic`/`AddToDiagnostic` impls",
+    "prevent diagnostic creation outside of `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls",
     report_in_external_macro: true
 }
 
@@ -410,9 +409,8 @@ impl LateLintPass<'_> for Diagnostics {
             }
         };
 
-        // Does the callee have a `impl Into<{D,Subd}iagMessage>` parameter? (There should be at
-        // most one.)
-        let mut impl_into_diagnostic_message_param = None;
+        // Does the callee have one or more `impl Into<{D,Subd}iagMessage>` parameters?
+        let mut impl_into_diagnostic_message_params = vec![];
         let fn_sig = cx.tcx.fn_sig(def_id).instantiate_identity().skip_binder();
         let predicates = cx.tcx.predicates_of(def_id).instantiate_identity(cx.tcx).predicates;
         for (i, &param_ty) in fn_sig.inputs().iter().enumerate() {
@@ -426,20 +424,14 @@ impl LateLintPass<'_> for Diagnostics {
                         && let ty1 = trait_ref.args.type_at(1)
                         && is_diag_message(ty1)
                     {
-                        if impl_into_diagnostic_message_param.is_some() {
-                            cx.tcx.dcx().span_bug(
-                                span,
-                                "can't handle multiple `impl Into<{D,Sub}iagMessage>` params",
-                            );
-                        }
-                        impl_into_diagnostic_message_param = Some((i, p.name));
+                        impl_into_diagnostic_message_params.push((i, p.name));
                     }
                 }
             }
         }
 
         // Is the callee interesting?
-        if !has_attr && impl_into_diagnostic_message_param.is_none() {
+        if !has_attr && impl_into_diagnostic_message_params.is_empty() {
             return;
         }
 
@@ -455,7 +447,7 @@ impl LateLintPass<'_> for Diagnostics {
         }
 
         // Calls to `#[rustc_lint_diagnostics]`-marked functions should only occur:
-        // - inside an impl of `IntoDiagnostic`, `AddToDiagnostic`, or `DecorateLint`, or
+        // - inside an impl of `Diagnostic`, `Subdiagnostic`, or `LintDiagnostic`, or
         // - inside a parent function that is itself marked with `#[rustc_lint_diagnostics]`.
         //
         // Otherwise, emit a `DIAGNOSTIC_OUTSIDE_OF_IMPL` lint.
@@ -467,10 +459,7 @@ impl LateLintPass<'_> for Diagnostics {
                     && let Impl { of_trait: Some(of_trait), .. } = impl_
                     && let Some(def_id) = of_trait.trait_def_id()
                     && let Some(name) = cx.tcx.get_diagnostic_name(def_id)
-                    && matches!(
-                        name,
-                        sym::IntoDiagnostic | sym::AddToDiagnostic | sym::DecorateLint
-                    )
+                    && matches!(name, sym::Diagnostic | sym::Subdiagnostic | sym::LintDiagnostic)
                 {
                     is_inside_appropriate_impl = true;
                     break;
@@ -485,7 +474,7 @@ impl LateLintPass<'_> for Diagnostics {
         // Calls to methods with an `impl Into<{D,Subd}iagMessage>` parameter must be passed an arg
         // with type `{D,Subd}iagMessage` or `impl Into<{D,Subd}iagMessage>`. Otherwise, emit an
         // `UNTRANSLATABLE_DIAGNOSTIC` lint.
-        if let Some((param_i, param_i_p_name)) = impl_into_diagnostic_message_param {
+        for (param_i, param_i_p_name) in impl_into_diagnostic_message_params {
             // Is the arg type `{Sub,D}iagMessage`or `impl Into<{Sub,D}iagMessage>`?
             let arg_ty = call_tys[param_i];
             let is_translatable = is_diag_message(arg_ty)
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 2f08cd53b75..e89df1c9840 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -16,7 +16,7 @@ use crate::{
 use rustc_ast as ast;
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxIndexMap;
-use rustc_errors::{DecorateLint, Diag, DiagMessage, MultiSpan};
+use rustc_errors::{Diag, DiagMessage, LintDiagnostic, MultiSpan};
 use rustc_feature::{Features, GateIssue};
 use rustc_hir as hir;
 use rustc_hir::intravisit::{self, Visitor};
@@ -1119,7 +1119,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
         &self,
         lint: &'static Lint,
         span: MultiSpan,
-        decorate: impl for<'a> DecorateLint<'a, ()>,
+        decorate: impl for<'a> LintDiagnostic<'a, ()>,
     ) {
         let (level, src) = self.lint_level(lint);
         lint_level(self.sess, lint, level, src, Some(span), decorate.msg(), |lint| {
@@ -1128,7 +1128,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
     }
 
     #[track_caller]
-    pub fn emit_lint(&self, lint: &'static Lint, decorate: impl for<'a> DecorateLint<'a, ()>) {
+    pub fn emit_lint(&self, lint: &'static Lint, decorate: impl for<'a> LintDiagnostic<'a, ()>) {
         let (level, src) = self.lint_level(lint);
         lint_level(self.sess, lint, level, src, None, decorate.msg(), |lint| {
             decorate.decorate_lint(lint);
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 7e0ac1bfff1..1dac2d89c6b 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -5,8 +5,8 @@ use std::num::NonZero;
 use crate::errors::RequestedLevel;
 use crate::fluent_generated as fluent;
 use rustc_errors::{
-    codes::*, AddToDiagnostic, Applicability, DecorateLint, Diag, DiagMessage, DiagStyledString,
-    EmissionGuarantee, SubdiagMessageOp, SuggestionStyle,
+    codes::*, Applicability, Diag, DiagMessage, DiagStyledString, EmissionGuarantee,
+    LintDiagnostic, SubdiagMessageOp, Subdiagnostic, SuggestionStyle,
 };
 use rustc_hir::def_id::DefId;
 use rustc_macros::{LintDiagnostic, Subdiagnostic};
@@ -136,7 +136,7 @@ pub struct BuiltinMissingDebugImpl<'a> {
 }
 
 // Needed for def_path_str
-impl<'a> DecorateLint<'a, ()> for BuiltinMissingDebugImpl<'_> {
+impl<'a> LintDiagnostic<'a, ()> for BuiltinMissingDebugImpl<'_> {
     fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::Diag<'a, ()>) {
         diag.arg("debug", self.tcx.def_path_str(self.def_id));
     }
@@ -241,7 +241,7 @@ pub struct BuiltinUngatedAsyncFnTrackCaller<'a> {
     pub session: &'a Session,
 }
 
-impl<'a> DecorateLint<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> {
+impl<'a> LintDiagnostic<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> {
     fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
         diag.span_label(self.label, fluent::lint_label);
         rustc_session::parse::add_feature_diagnostics(
@@ -270,8 +270,8 @@ pub struct SuggestChangingAssocTypes<'a, 'b> {
     pub ty: &'a rustc_hir::Ty<'b>,
 }
 
-impl<'a, 'b> AddToDiagnostic for SuggestChangingAssocTypes<'a, 'b> {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl<'a, 'b> Subdiagnostic for SuggestChangingAssocTypes<'a, 'b> {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -326,8 +326,8 @@ pub struct BuiltinTypeAliasGenericBoundsSuggestion {
     pub suggestions: Vec<(Span, String)>,
 }
 
-impl AddToDiagnostic for BuiltinTypeAliasGenericBoundsSuggestion {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for BuiltinTypeAliasGenericBoundsSuggestion {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -423,7 +423,7 @@ pub struct BuiltinUnpermittedTypeInit<'a> {
     pub tcx: TyCtxt<'a>,
 }
 
-impl<'a> DecorateLint<'a, ()> for BuiltinUnpermittedTypeInit<'_> {
+impl<'a> LintDiagnostic<'a, ()> for BuiltinUnpermittedTypeInit<'_> {
     fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
         diag.arg("ty", self.ty);
         diag.span_label(self.label, fluent::lint_builtin_unpermitted_type_init_label);
@@ -434,7 +434,7 @@ impl<'a> DecorateLint<'a, ()> for BuiltinUnpermittedTypeInit<'_> {
                 fluent::lint_builtin_unpermitted_type_init_label_suggestion,
             );
         }
-        self.sub.add_to_diagnostic(diag);
+        self.sub.add_to_diag(diag);
     }
 
     fn msg(&self) -> DiagMessage {
@@ -447,8 +447,8 @@ pub struct BuiltinUnpermittedTypeInitSub {
     pub err: InitError,
 }
 
-impl AddToDiagnostic for BuiltinUnpermittedTypeInitSub {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for BuiltinUnpermittedTypeInitSub {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -502,8 +502,8 @@ pub struct BuiltinClashingExternSub<'a> {
     pub found: Ty<'a>,
 }
 
-impl AddToDiagnostic for BuiltinClashingExternSub<'_> {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for BuiltinClashingExternSub<'_> {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -784,8 +784,8 @@ pub struct HiddenUnicodeCodepointsDiagLabels {
     pub spans: Vec<(char, Span)>,
 }
 
-impl AddToDiagnostic for HiddenUnicodeCodepointsDiagLabels {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for HiddenUnicodeCodepointsDiagLabels {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -802,8 +802,8 @@ pub enum HiddenUnicodeCodepointsDiagSub {
 }
 
 // Used because of multiple multipart_suggestion and note
-impl AddToDiagnostic for HiddenUnicodeCodepointsDiagSub {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for HiddenUnicodeCodepointsDiagSub {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -950,8 +950,8 @@ pub struct NonBindingLetSub {
     pub is_assign_desugar: bool,
 }
 
-impl AddToDiagnostic for NonBindingLetSub {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for NonBindingLetSub {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -1159,7 +1159,7 @@ pub struct NonFmtPanicUnused {
 }
 
 // Used because of two suggestions based on one Option<Span>
-impl<'a> DecorateLint<'a, ()> for NonFmtPanicUnused {
+impl<'a> LintDiagnostic<'a, ()> for NonFmtPanicUnused {
     fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
         diag.arg("count", self.count);
         diag.note(fluent::lint_note);
@@ -1236,8 +1236,8 @@ pub enum NonSnakeCaseDiagSub {
     SuggestionAndNote { span: Span },
 }
 
-impl AddToDiagnostic for NonSnakeCaseDiagSub {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for NonSnakeCaseDiagSub {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -1397,7 +1397,7 @@ pub struct DropTraitConstraintsDiag<'a> {
 }
 
 // Needed for def_path_str
-impl<'a> DecorateLint<'a, ()> for DropTraitConstraintsDiag<'_> {
+impl<'a> LintDiagnostic<'a, ()> for DropTraitConstraintsDiag<'_> {
     fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
         diag.arg("predicate", self.predicate);
         diag.arg("needs_drop", self.tcx.def_path_str(self.def_id));
@@ -1414,7 +1414,7 @@ pub struct DropGlue<'a> {
 }
 
 // Needed for def_path_str
-impl<'a> DecorateLint<'a, ()> for DropGlue<'_> {
+impl<'a> LintDiagnostic<'a, ()> for DropGlue<'_> {
     fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
         diag.arg("needs_drop", self.tcx.def_path_str(self.def_id));
     }
@@ -1478,8 +1478,8 @@ pub enum OverflowingBinHexSign {
     Negative,
 }
 
-impl AddToDiagnostic for OverflowingBinHexSign {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for OverflowingBinHexSign {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -1689,7 +1689,7 @@ pub struct ImproperCTypes<'a> {
 }
 
 // Used because of the complexity of Option<DiagMessage>, DiagMessage, and Option<Span>
-impl<'a> DecorateLint<'a, ()> for ImproperCTypes<'_> {
+impl<'a> LintDiagnostic<'a, ()> for ImproperCTypes<'_> {
     fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
         diag.arg("ty", self.ty);
         diag.arg("desc", self.desc);
@@ -1832,7 +1832,7 @@ pub enum UnusedDefSuggestion {
 }
 
 // Needed because of def_path_str
-impl<'a> DecorateLint<'a, ()> for UnusedDef<'_, '_> {
+impl<'a> LintDiagnostic<'a, ()> for UnusedDef<'_, '_> {
     fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
         diag.arg("pre", self.pre);
         diag.arg("post", self.post);
@@ -1915,7 +1915,7 @@ pub struct AsyncFnInTraitDiag {
     pub sugg: Option<Vec<(Span, String)>>,
 }
 
-impl<'a> DecorateLint<'a, ()> for AsyncFnInTraitDiag {
+impl<'a> LintDiagnostic<'a, ()> for AsyncFnInTraitDiag {
     fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
         diag.note(fluent::lint_note);
         if let Some(sugg) = self.sugg {
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
index a1a7b19642b..9d21d88165e 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
@@ -10,7 +10,7 @@ use quote::quote;
 use syn::spanned::Spanned;
 use synstructure::Structure;
 
-/// The central struct for constructing the `into_diagnostic` method from an annotated struct.
+/// The central struct for constructing the `into_diag` method from an annotated struct.
 pub(crate) struct DiagnosticDerive<'a> {
     structure: Structure<'a>,
 }
@@ -72,14 +72,11 @@ impl<'a> DiagnosticDerive<'a> {
 
         // A lifetime of `'a` causes conflicts, but `_sess` is fine.
         let mut imp = structure.gen_impl(quote! {
-            gen impl<'_sess, G>
-                    rustc_errors::IntoDiagnostic<'_sess, G>
-                    for @Self
+            gen impl<'_sess, G> rustc_errors::Diagnostic<'_sess, G> for @Self
                 where G: rustc_errors::EmissionGuarantee
             {
-
                 #[track_caller]
-                fn into_diagnostic(
+                fn into_diag(
                     self,
                     dcx: &'_sess rustc_errors::DiagCtxt,
                     level: rustc_errors::Level
@@ -156,7 +153,7 @@ impl<'a> LintDiagnosticDerive<'a> {
         });
 
         let mut imp = structure.gen_impl(quote! {
-            gen impl<'__a> rustc_errors::DecorateLint<'__a, ()> for @Self {
+            gen impl<'__a> rustc_errors::LintDiagnostic<'__a, ()> for @Self {
                 #[track_caller]
                 fn decorate_lint<'__b>(
                     self,
diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs
index 044bbadf41c..389d88bebc7 100644
--- a/compiler/rustc_macros/src/diagnostics/mod.rs
+++ b/compiler/rustc_macros/src/diagnostics/mod.rs
@@ -6,7 +6,7 @@ mod utils;
 
 use diagnostic::{DiagnosticDerive, LintDiagnosticDerive};
 use proc_macro2::TokenStream;
-use subdiagnostic::SubdiagnosticDeriveBuilder;
+use subdiagnostic::SubdiagnosticDerive;
 use synstructure::Structure;
 
 /// Implements `#[derive(Diagnostic)]`, which allows for errors to be specified as a struct,
@@ -55,7 +55,7 @@ use synstructure::Structure;
 ///
 /// See rustc dev guide for more examples on using the `#[derive(Diagnostic)]`:
 /// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html>
-pub fn session_diagnostic_derive(mut s: Structure<'_>) -> TokenStream {
+pub fn diagnostic_derive(mut s: Structure<'_>) -> TokenStream {
     s.underscore_const(true);
     DiagnosticDerive::new(s).into_tokens()
 }
@@ -153,7 +153,7 @@ pub fn lint_diagnostic_derive(mut s: Structure<'_>) -> TokenStream {
 ///
 /// diag.subdiagnostic(RawIdentifierSuggestion { span, applicability, ident });
 /// ```
-pub fn session_subdiagnostic_derive(mut s: Structure<'_>) -> TokenStream {
+pub fn subdiagnostic_derive(mut s: Structure<'_>) -> TokenStream {
     s.underscore_const(true);
-    SubdiagnosticDeriveBuilder::new().into_tokens(s)
+    SubdiagnosticDerive::new().into_tokens(s)
 }
diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
index ef326106404..ced782cdbc0 100644
--- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs
@@ -16,13 +16,13 @@ use synstructure::{BindingInfo, Structure, VariantInfo};
 
 use super::utils::SubdiagnosticVariant;
 
-/// The central struct for constructing the `add_to_diagnostic` method from an annotated struct.
-pub(crate) struct SubdiagnosticDeriveBuilder {
+/// The central struct for constructing the `add_to_diag` method from an annotated struct.
+pub(crate) struct SubdiagnosticDerive {
     diag: syn::Ident,
     f: syn::Ident,
 }
 
-impl SubdiagnosticDeriveBuilder {
+impl SubdiagnosticDerive {
     pub(crate) fn new() -> Self {
         let diag = format_ident!("diag");
         let f = format_ident!("f");
@@ -86,8 +86,8 @@ impl SubdiagnosticDeriveBuilder {
         let diag = &self.diag;
         let f = &self.f;
         let ret = structure.gen_impl(quote! {
-            gen impl rustc_errors::AddToDiagnostic for @Self {
-                fn add_to_diagnostic_with<__G, __F>(
+            gen impl rustc_errors::Subdiagnostic for @Self {
+                fn add_to_diag_with<__G, __F>(
                     self,
                     #diag: &mut rustc_errors::Diag<'_, __G>,
                     #f: __F
@@ -109,7 +109,7 @@ impl SubdiagnosticDeriveBuilder {
 /// double mut borrow later on.
 struct SubdiagnosticDeriveVariantBuilder<'parent, 'a> {
     /// The identifier to use for the generated `Diag` instance.
-    parent: &'parent SubdiagnosticDeriveBuilder,
+    parent: &'parent SubdiagnosticDerive,
 
     /// Info for the current variant (or the type if not an enum).
     variant: &'a VariantInfo<'a>,
diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs
index 14e6a06839e..eedc508fb14 100644
--- a/compiler/rustc_macros/src/lib.rs
+++ b/compiler/rustc_macros/src/lib.rs
@@ -118,7 +118,7 @@ decl_derive!(
         suggestion,
         suggestion_short,
         suggestion_hidden,
-        suggestion_verbose)] => diagnostics::session_diagnostic_derive
+        suggestion_verbose)] => diagnostics::diagnostic_derive
 );
 decl_derive!(
     [LintDiagnostic, attributes(
@@ -156,5 +156,5 @@ decl_derive!(
         skip_arg,
         primary_span,
         suggestion_part,
-        applicability)] => diagnostics::session_subdiagnostic_derive
+        applicability)] => diagnostics::subdiagnostic_derive
 );
diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs
index b18ec85ca11..8bf6b665de8 100644
--- a/compiler/rustc_metadata/src/errors.rs
+++ b/compiler/rustc_metadata/src/errors.rs
@@ -3,7 +3,7 @@ use std::{
     path::{Path, PathBuf},
 };
 
-use rustc_errors::{codes::*, Diag, DiagCtxt, EmissionGuarantee, IntoDiagnostic, Level};
+use rustc_errors::{codes::*, Diag, DiagCtxt, Diagnostic, EmissionGuarantee, Level};
 use rustc_macros::Diagnostic;
 use rustc_session::config;
 use rustc_span::{sym, Span, Symbol};
@@ -495,8 +495,8 @@ pub(crate) struct MultipleCandidates {
     pub candidates: Vec<PathBuf>,
 }
 
-impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for MultipleCandidates {
-    fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> Diag<'_, G> {
+impl<G: EmissionGuarantee> Diagnostic<'_, G> for MultipleCandidates {
+    fn into_diag(self, dcx: &'_ DiagCtxt, level: Level) -> Diag<'_, G> {
         let mut diag = Diag::new(dcx, level, fluent::metadata_multiple_candidates);
         diag.arg("crate_name", self.crate_name);
         diag.arg("flavor", self.flavor);
@@ -593,9 +593,9 @@ pub struct InvalidMetadataFiles {
     pub crate_rejections: Vec<String>,
 }
 
-impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for InvalidMetadataFiles {
+impl<G: EmissionGuarantee> Diagnostic<'_, G> for InvalidMetadataFiles {
     #[track_caller]
-    fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> Diag<'_, G> {
+    fn into_diag(self, dcx: &'_ DiagCtxt, level: Level) -> Diag<'_, G> {
         let mut diag = Diag::new(dcx, level, fluent::metadata_invalid_meta_files);
         diag.arg("crate_name", self.crate_name);
         diag.arg("add_info", self.add_info);
@@ -622,9 +622,9 @@ pub struct CannotFindCrate {
     pub is_ui_testing: bool,
 }
 
-impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for CannotFindCrate {
+impl<G: EmissionGuarantee> Diagnostic<'_, G> for CannotFindCrate {
     #[track_caller]
-    fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> Diag<'_, G> {
+    fn into_diag(self, dcx: &'_ DiagCtxt, level: Level) -> Diag<'_, G> {
         let mut diag = Diag::new(dcx, level, fluent::metadata_cannot_find_crate);
         diag.arg("crate_name", self.crate_name);
         diag.arg("current_crate", self.current_crate);
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index 10bbebb3871..7de03be6da6 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -220,7 +220,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::memmap::Mmap;
 use rustc_data_structures::owned_slice::slice_owned;
 use rustc_data_structures::svh::Svh;
-use rustc_errors::{DiagArgValue, IntoDiagnosticArg};
+use rustc_errors::{DiagArgValue, IntoDiagArg};
 use rustc_fs_util::try_canonicalize;
 use rustc_session::config;
 use rustc_session::cstore::CrateSource;
@@ -290,8 +290,8 @@ impl fmt::Display for CrateFlavor {
     }
 }
 
-impl IntoDiagnosticArg for CrateFlavor {
-    fn into_diagnostic_arg(self) -> rustc_errors::DiagArgValue {
+impl IntoDiagArg for CrateFlavor {
+    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
         match self {
             CrateFlavor::Rlib => DiagArgValue::Str(Cow::Borrowed("rlib")),
             CrateFlavor::Rmeta => DiagArgValue::Str(Cow::Borrowed("rmeta")),
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs
index 9731d86fb17..5feee3c3ba1 100644
--- a/compiler/rustc_middle/src/mir/consts.rs
+++ b/compiler/rustc_middle/src/mir/consts.rs
@@ -7,6 +7,7 @@ use rustc_target::abi::{HasDataLayout, Size};
 
 use crate::mir::interpret::{alloc_range, AllocId, ConstAllocation, ErrorHandled, Scalar};
 use crate::mir::{pretty_print_const_value, Promoted};
+use crate::ty::print::with_no_trimmed_paths;
 use crate::ty::GenericArgsRef;
 use crate::ty::ScalarInt;
 use crate::ty::{self, print::pretty_print_const, Ty, TyCtxt};
@@ -489,9 +490,18 @@ impl<'tcx> Display for Const<'tcx> {
             Const::Ty(c) => pretty_print_const(c, fmt, true),
             Const::Val(val, ty) => pretty_print_const_value(val, ty, fmt),
             // FIXME(valtrees): Correctly print mir constants.
-            Const::Unevaluated(..) => {
-                fmt.write_str("_")?;
-                Ok(())
+            Const::Unevaluated(c, _ty) => {
+                ty::tls::with(move |tcx| {
+                    let c = tcx.lift(c).unwrap();
+                    // Matches `GlobalId` printing.
+                    let instance =
+                        with_no_trimmed_paths!(tcx.def_path_str_with_args(c.def, c.args));
+                    write!(fmt, "{instance}")?;
+                    if let Some(promoted) = c.promoted {
+                        write!(fmt, "::{promoted:?}")?;
+                    }
+                    Ok(())
+                })
             }
         }
     }
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs
index aea88c4588b..751d6de83f9 100644
--- a/compiler/rustc_middle/src/mir/interpret/error.rs
+++ b/compiler/rustc_middle/src/mir/interpret/error.rs
@@ -6,7 +6,7 @@ use crate::ty::{layout, tls, Ty, TyCtxt, ValTree};
 
 use rustc_ast_ir::Mutability;
 use rustc_data_structures::sync::Lock;
-use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, IntoDiagnosticArg};
+use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, IntoDiagArg};
 use rustc_macros::HashStable;
 use rustc_session::CtfeBacktrace;
 use rustc_span::{def_id::DefId, Span, DUMMY_SP};
@@ -234,8 +234,8 @@ pub enum InvalidMetaKind {
     TooBig,
 }
 
-impl IntoDiagnosticArg for InvalidMetaKind {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for InvalidMetaKind {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(Cow::Borrowed(match self {
             InvalidMetaKind::SliceTooBig => "slice_too_big",
             InvalidMetaKind::TooBig => "too_big",
@@ -266,10 +266,10 @@ pub struct Misalignment {
     pub required: Align,
 }
 
-macro_rules! impl_into_diagnostic_arg_through_debug {
+macro_rules! impl_into_diag_arg_through_debug {
     ($($ty:ty),*$(,)?) => {$(
-        impl IntoDiagnosticArg for $ty {
-            fn into_diagnostic_arg(self) -> DiagArgValue {
+        impl IntoDiagArg for $ty {
+            fn into_diag_arg(self) -> DiagArgValue {
                 DiagArgValue::Str(Cow::Owned(format!("{self:?}")))
             }
         }
@@ -277,7 +277,7 @@ macro_rules! impl_into_diagnostic_arg_through_debug {
 }
 
 // These types have nice `Debug` output so we can just use them in diagnostics.
-impl_into_diagnostic_arg_through_debug! {
+impl_into_diag_arg_through_debug! {
     AllocId,
     Pointer<AllocId>,
     AllocRange,
@@ -370,8 +370,8 @@ pub enum PointerKind {
     Box,
 }
 
-impl IntoDiagnosticArg for PointerKind {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for PointerKind {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(
             match self {
                 Self::Ref(_) => "ref",
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index 5be09b06d9e..94b9afa1dee 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -100,7 +100,7 @@ macro_rules! err_ub_custom {
                 msg: || $msg,
                 add_args: Box::new(move |mut set_arg| {
                     $($(
-                        set_arg(stringify!($name).into(), rustc_errors::IntoDiagnosticArg::into_diagnostic_arg($name));
+                        set_arg(stringify!($name).into(), rustc_errors::IntoDiagArg::into_diag_arg($name));
                     )*)?
                 })
             }
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 0221bc6c363..4b5a08d6af3 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -14,7 +14,7 @@ use crate::ty::{AdtDef, InstanceDef, UserTypeAnnotationIndex};
 use crate::ty::{GenericArg, GenericArgsRef};
 
 use rustc_data_structures::captures::Captures;
-use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, IntoDiagnosticArg};
+use rustc_errors::{DiagArgName, DiagArgValue, DiagMessage, ErrorGuaranteed, IntoDiagArg};
 use rustc_hir::def::{CtorKind, Namespace};
 use rustc_hir::def_id::{DefId, CRATE_DEF_ID};
 use rustc_hir::{self, CoroutineDesugaring, CoroutineKind, ImplicitSelfKind};
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 18069547a7e..090b84ff08f 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -496,7 +496,7 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn io::Write) -> io:
         _ => tcx.is_closure_like(def_id),
     };
     match (kind, body.source.promoted) {
-        (_, Some(i)) => write!(w, "{i:?} in ")?,
+        (_, Some(_)) => write!(w, "const ")?, // promoteds are the closest to consts
         (DefKind::Const | DefKind::AssocConst, _) => write!(w, "const ")?,
         (DefKind::Static(hir::Mutability::Not), _) => write!(w, "static ")?,
         (DefKind::Static(hir::Mutability::Mut), _) => write!(w, "static mut ")?,
@@ -509,6 +509,9 @@ fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn io::Write) -> io:
         // see notes on #41697 elsewhere
         write!(w, "{}", tcx.def_path_str(def_id))?
     }
+    if let Some(p) = body.source.promoted {
+        write!(w, "::{p:?}")?;
+    }
 
     if body.source.promoted.is_none() && is_function {
         write!(w, "(")?;
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index a4a4df55c48..94f8cba6fb5 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -311,7 +311,7 @@ impl<O> AssertKind<O> {
 
         macro_rules! add {
             ($name: expr, $value: expr) => {
-                adder($name.into(), $value.into_diagnostic_arg());
+                adder($name.into(), $value.into_diag_arg());
             };
         }
 
diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs
index 93a9bbf64c9..b798f078800 100644
--- a/compiler/rustc_middle/src/mir/type_foldable.rs
+++ b/compiler/rustc_middle/src/mir/type_foldable.rs
@@ -1,6 +1,7 @@
 //! `TypeFoldable` implementations for MIR types
 
 use rustc_ast::InlineAsmTemplatePiece;
+use rustc_hir::def_id::LocalDefId;
 
 use super::*;
 
@@ -44,6 +45,15 @@ impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx [Span] {
     }
 }
 
+impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<LocalDefId> {
+    fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
+        self,
+        _folder: &mut F,
+    ) -> Result<Self, F::Error> {
+        Ok(self)
+    }
+}
+
 impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<PlaceElem<'tcx>> {
     fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
         self,
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 913d0072c29..74b47d8b04e 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -9,7 +9,7 @@
 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/thir.html
 
 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
-use rustc_errors::{DiagArgValue, IntoDiagnosticArg};
+use rustc_errors::{DiagArgValue, IntoDiagArg};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::RangeEnd;
@@ -676,9 +676,9 @@ impl<'tcx> Pat<'tcx> {
     }
 }
 
-impl<'tcx> IntoDiagnosticArg for Pat<'tcx> {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
-        format!("{self}").into_diagnostic_arg()
+impl<'tcx> IntoDiagArg for Pat<'tcx> {
+    fn into_diag_arg(self) -> DiagArgValue {
+        format!("{self}").into_diag_arg()
     }
 }
 
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index a6e4702d819..aea58653351 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -12,8 +12,8 @@ pub mod util;
 use crate::infer::canonical::Canonical;
 use crate::mir::ConstraintCategory;
 use crate::ty::abstract_const::NotConstEvaluatable;
-use crate::ty::GenericArgsRef;
 use crate::ty::{self, AdtKind, Ty};
+use crate::ty::{GenericArgsRef, TyCtxt};
 
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Applicability, Diag, EmissionGuarantee};
@@ -1001,10 +1001,14 @@ pub enum CodegenObligationError {
 /// opaques are replaced with inference vars eagerly in the old solver (e.g.
 /// in projection, and in the signature during function type-checking).
 #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)]
-pub enum DefiningAnchor {
-    /// Define opaques which are in-scope of the `LocalDefId`. Also, eagerly
-    /// replace opaque types in `replace_opaque_types_with_inference_vars`.
-    Bind(LocalDefId),
+pub enum DefiningAnchor<'tcx> {
+    /// Define opaques which are in-scope of the current item being analyzed.
+    /// Also, eagerly replace these opaque types in `replace_opaque_types_with_inference_vars`.
+    ///
+    /// If the list is empty, do not allow any opaques to be defined. This is used to catch type mismatch
+    /// errors when handling opaque types, and also should be used when we would
+    /// otherwise reveal opaques (such as [`Reveal::All`] reveal mode).
+    Bind(&'tcx ty::List<LocalDefId>),
     /// In contexts where we don't currently know what opaques are allowed to be
     /// defined, such as (old solver) canonical queries, we will simply allow
     /// opaques to be defined, but "bubble" them up in the canonical response or
@@ -1013,8 +1017,10 @@ pub enum DefiningAnchor {
     /// We do not eagerly replace opaque types in `replace_opaque_types_with_inference_vars`,
     /// which may affect what predicates pass and fail in the old trait solver.
     Bubble,
-    /// Do not allow any opaques to be defined. This is used to catch type mismatch
-    /// errors when handling opaque types, and also should be used when we would
-    /// otherwise reveal opaques (such as [`Reveal::All`] reveal mode).
-    Error,
+}
+
+impl<'tcx> DefiningAnchor<'tcx> {
+    pub fn bind(tcx: TyCtxt<'tcx>, item: LocalDefId) -> Self {
+        Self::Bind(tcx.opaque_types_defined_by(item))
+    }
 }
diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs
index 95139b50cb8..dc4cd203415 100644
--- a/compiler/rustc_middle/src/traits/solve.rs
+++ b/compiler/rustc_middle/src/traits/solve.rs
@@ -114,7 +114,7 @@ impl MaybeCause {
 #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)]
 pub struct QueryInput<'tcx, T> {
     pub goal: Goal<'tcx, T>,
-    pub anchor: DefiningAnchor,
+    pub anchor: DefiningAnchor<'tcx>,
     pub predefined_opaques_in_body: PredefinedOpaques<'tcx>,
 }
 
diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs
index 69ae05ca820..ddbc0bffaed 100644
--- a/compiler/rustc_middle/src/ty/codec.rs
+++ b/compiler/rustc_middle/src/ty/codec.rs
@@ -17,6 +17,7 @@ use crate::traits;
 use crate::ty::GenericArgsRef;
 use crate::ty::{self, AdtDef, Ty};
 use rustc_data_structures::fx::FxHashMap;
+use rustc_hir::def_id::LocalDefId;
 use rustc_middle::ty::TyCtxt;
 use rustc_serialize::{Decodable, Encodable};
 use rustc_span::Span;
@@ -431,6 +432,15 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<Fi
     }
 }
 
+impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D> for ty::List<LocalDefId> {
+    fn decode(decoder: &mut D) -> &'tcx Self {
+        let len = decoder.read_usize();
+        decoder.interner().mk_local_def_ids_from_iter(
+            (0..len).map::<LocalDefId, _>(|_| Decodable::decode(decoder)),
+        )
+    }
+}
+
 impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> RefDecodable<'tcx, D>
     for ty::List<(VariantIdx, FieldIdx)>
 {
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs
index 221a9ceee1a..a70e01645f4 100644
--- a/compiler/rustc_middle/src/ty/consts/int.rs
+++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -1,6 +1,6 @@
 use rustc_apfloat::ieee::{Double, Single};
 use rustc_apfloat::Float;
-use rustc_errors::{DiagArgValue, IntoDiagnosticArg};
+use rustc_errors::{DiagArgValue, IntoDiagArg};
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use rustc_target::abi::Size;
 use std::fmt;
@@ -114,10 +114,10 @@ impl std::fmt::Debug for ConstInt {
     }
 }
 
-impl IntoDiagnosticArg for ConstInt {
+impl IntoDiagArg for ConstInt {
     // FIXME this simply uses the Debug impl, but we could probably do better by converting both
     // to an inherent method that returns `Cow`.
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(format!("{self:?}").into())
     }
 }
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index b35682df2c8..705987d92fe 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -14,9 +14,9 @@ pub struct UnevaluatedConst<'tcx> {
     pub args: GenericArgsRef<'tcx>,
 }
 
-impl rustc_errors::IntoDiagnosticArg for UnevaluatedConst<'_> {
-    fn into_diagnostic_arg(self) -> rustc_errors::DiagArgValue {
-        format!("{self:?}").into_diagnostic_arg()
+impl rustc_errors::IntoDiagArg for UnevaluatedConst<'_> {
+    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
+        format!("{self:?}").into_diag_arg()
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index f947832d28c..c415c06c21b 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -43,7 +43,7 @@ use rustc_data_structures::sync::{self, FreezeReadGuard, Lock, Lrc, WorkerLocal}
 #[cfg(parallel_compiler)]
 use rustc_data_structures::sync::{DynSend, DynSync};
 use rustc_data_structures::unord::UnordSet;
-use rustc_errors::{DecorateLint, Diag, DiagCtxt, DiagMessage, ErrorGuaranteed, MultiSpan};
+use rustc_errors::{Diag, DiagCtxt, DiagMessage, ErrorGuaranteed, LintDiagnostic, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
@@ -709,7 +709,7 @@ impl<'tcx> GlobalCtxt<'tcx> {
     }
 
     pub fn finish(&self) -> FileEncodeResult {
-        self.dep_graph.finish_encoding(&self.sess.prof)
+        self.dep_graph.finish_encoding()
     }
 }
 
@@ -2014,6 +2014,14 @@ impl<'tcx> TyCtxt<'tcx> {
         self.intern_local_def_ids(clauses)
     }
 
+    pub fn mk_local_def_ids_from_iter<I, T>(self, iter: I) -> T::Output
+    where
+        I: Iterator<Item = T>,
+        T: CollectAndApply<LocalDefId, &'tcx List<LocalDefId>>,
+    {
+        T::collect_and_apply(iter, |xs| self.mk_local_def_ids(xs))
+    }
+
     pub fn mk_const_list_from_iter<I, T>(self, iter: I) -> T::Output
     where
         I: Iterator<Item = T>,
@@ -2129,7 +2137,7 @@ impl<'tcx> TyCtxt<'tcx> {
         T::collect_and_apply(iter, |xs| self.mk_bound_variable_kinds(xs))
     }
 
-    /// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`,
+    /// Emit a lint at `span` from a lint struct (some type that implements `LintDiagnostic`,
     /// typically generated by `#[derive(LintDiagnostic)]`).
     #[track_caller]
     pub fn emit_node_span_lint(
@@ -2137,7 +2145,7 @@ impl<'tcx> TyCtxt<'tcx> {
         lint: &'static Lint,
         hir_id: HirId,
         span: impl Into<MultiSpan>,
-        decorator: impl for<'a> DecorateLint<'a, ()>,
+        decorator: impl for<'a> LintDiagnostic<'a, ()>,
     ) {
         let msg = decorator.msg();
         let (level, src) = self.lint_level_at_node(lint, hir_id);
@@ -2163,14 +2171,14 @@ impl<'tcx> TyCtxt<'tcx> {
         lint_level(self.sess, lint, level, src, Some(span.into()), msg, decorate);
     }
 
-    /// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically
+    /// Emit a lint from a lint struct (some type that implements `LintDiagnostic`, typically
     /// generated by `#[derive(LintDiagnostic)]`).
     #[track_caller]
     pub fn emit_node_lint(
         self,
         lint: &'static Lint,
         id: HirId,
-        decorator: impl for<'a> DecorateLint<'a, ()>,
+        decorator: impl for<'a> LintDiagnostic<'a, ()>,
     ) {
         self.node_lint(lint, id, decorator.msg(), |diag| {
             decorator.decorate_lint(diag);
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index 2506456f1fb..05463b8554f 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -11,7 +11,7 @@ use crate::ty::{
 };
 
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{Applicability, Diag, DiagArgValue, IntoDiagnosticArg};
+use rustc_errors::{Applicability, Diag, DiagArgValue, IntoDiagArg};
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
@@ -19,9 +19,9 @@ use rustc_hir::{PredicateOrigin, WherePredicate};
 use rustc_span::{BytePos, Span};
 use rustc_type_ir::TyKind::*;
 
-impl<'tcx> IntoDiagnosticArg for Ty<'tcx> {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
-        self.to_string().into_diagnostic_arg()
+impl<'tcx> IntoDiagArg for Ty<'tcx> {
+    fn into_diag_arg(self) -> DiagArgValue {
+        self.to_string().into_diag_arg()
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index 8079ad121ad..02b58c035d4 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -9,7 +9,7 @@ use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
 use rustc_ast_ir::visit::VisitorResult;
 use rustc_ast_ir::walk_visitable_list;
 use rustc_data_structures::intern::Interned;
-use rustc_errors::{DiagArgValue, IntoDiagnosticArg};
+use rustc_errors::{DiagArgValue, IntoDiagArg};
 use rustc_hir::def_id::DefId;
 use rustc_macros::HashStable;
 use rustc_serialize::{Decodable, Encodable};
@@ -57,9 +57,9 @@ unsafe impl<'tcx> Sync for GenericArg<'tcx> where
 {
 }
 
-impl<'tcx> IntoDiagnosticArg for GenericArg<'tcx> {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
-        self.to_string().into_diagnostic_arg()
+impl<'tcx> IntoDiagArg for GenericArg<'tcx> {
+    fn into_diag_arg(self) -> DiagArgValue {
+        self.to_string().into_diag_arg()
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index b1bfd2f1105..11fd73c9094 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -5,7 +5,7 @@ use crate::ty::normalize_erasing_regions::NormalizationError;
 use crate::ty::{self, ConstKind, Ty, TyCtxt, TypeVisitableExt};
 use rustc_error_messages::DiagMessage;
 use rustc_errors::{
-    Diag, DiagArgValue, DiagCtxt, EmissionGuarantee, IntoDiagnostic, IntoDiagnosticArg, Level,
+    Diag, DiagArgValue, DiagCtxt, Diagnostic, EmissionGuarantee, IntoDiagArg, Level,
 };
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
@@ -254,9 +254,9 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
     }
 }
 
-impl<'tcx> IntoDiagnosticArg for LayoutError<'tcx> {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
-        self.to_string().into_diagnostic_arg()
+impl<'tcx> IntoDiagArg for LayoutError<'tcx> {
+    fn into_diag_arg(self) -> DiagArgValue {
+        self.to_string().into_diag_arg()
     }
 }
 
@@ -1267,14 +1267,14 @@ pub enum FnAbiError<'tcx> {
     AdjustForForeignAbi(call::AdjustForForeignAbiError),
 }
 
-impl<'a, 'b, G: EmissionGuarantee> IntoDiagnostic<'a, G> for FnAbiError<'b> {
-    fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
+impl<'a, 'b, G: EmissionGuarantee> Diagnostic<'a, G> for FnAbiError<'b> {
+    fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
         match self {
-            Self::Layout(e) => e.into_diagnostic().into_diagnostic(dcx, level),
+            Self::Layout(e) => e.into_diagnostic().into_diag(dcx, level),
             Self::AdjustForForeignAbi(call::AdjustForForeignAbiError::Unsupported {
                 arch,
                 abi,
-            }) => UnsupportedFnAbi { arch, abi: abi.name() }.into_diagnostic(dcx, level),
+            }) => UnsupportedFnAbi { arch, abi: abi.name() }.into_diag(dcx, level),
         }
     }
 }
diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs
index 8dd95daed36..62822505fa5 100644
--- a/compiler/rustc_middle/src/ty/predicate.rs
+++ b/compiler/rustc_middle/src/ty/predicate.rs
@@ -1,6 +1,6 @@
 use rustc_data_structures::captures::Captures;
 use rustc_data_structures::intern::Interned;
-use rustc_errors::{DiagArgValue, IntoDiagnosticArg};
+use rustc_errors::{DiagArgValue, IntoDiagArg};
 use rustc_hir::def_id::DefId;
 use rustc_hir::LangItem;
 use rustc_span::Span;
@@ -120,14 +120,14 @@ impl<'tcx> Predicate<'tcx> {
     }
 }
 
-impl rustc_errors::IntoDiagnosticArg for Predicate<'_> {
-    fn into_diagnostic_arg(self) -> rustc_errors::DiagArgValue {
+impl rustc_errors::IntoDiagArg for Predicate<'_> {
+    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
         rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(self.to_string()))
     }
 }
 
-impl rustc_errors::IntoDiagnosticArg for Clause<'_> {
-    fn into_diagnostic_arg(self) -> rustc_errors::DiagArgValue {
+impl rustc_errors::IntoDiagArg for Clause<'_> {
+    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
         rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(self.to_string()))
     }
 }
@@ -407,9 +407,9 @@ impl<'tcx> PolyTraitRef<'tcx> {
     }
 }
 
-impl<'tcx> IntoDiagnosticArg for TraitRef<'tcx> {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
-        self.to_string().into_diagnostic_arg()
+impl<'tcx> IntoDiagArg for TraitRef<'tcx> {
+    fn into_diag_arg(self) -> DiagArgValue {
+        self.to_string().into_diag_arg()
     }
 }
 
@@ -453,9 +453,9 @@ impl<'tcx> ExistentialTraitRef<'tcx> {
     }
 }
 
-impl<'tcx> IntoDiagnosticArg for ExistentialTraitRef<'tcx> {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
-        self.to_string().into_diagnostic_arg()
+impl<'tcx> IntoDiagArg for ExistentialTraitRef<'tcx> {
+    fn into_diag_arg(self) -> DiagArgValue {
+        self.to_string().into_diag_arg()
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index c8c9afa7f4d..33d63c2a505 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -2722,9 +2722,9 @@ where
 #[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
 pub struct TraitRefPrintOnlyTraitPath<'tcx>(ty::TraitRef<'tcx>);
 
-impl<'tcx> rustc_errors::IntoDiagnosticArg for TraitRefPrintOnlyTraitPath<'tcx> {
-    fn into_diagnostic_arg(self) -> rustc_errors::DiagArgValue {
-        self.to_string().into_diagnostic_arg()
+impl<'tcx> rustc_errors::IntoDiagArg for TraitRefPrintOnlyTraitPath<'tcx> {
+    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
+        self.to_string().into_diag_arg()
     }
 }
 
@@ -2739,9 +2739,9 @@ impl<'tcx> fmt::Debug for TraitRefPrintOnlyTraitPath<'tcx> {
 #[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
 pub struct TraitRefPrintSugared<'tcx>(ty::TraitRef<'tcx>);
 
-impl<'tcx> rustc_errors::IntoDiagnosticArg for TraitRefPrintSugared<'tcx> {
-    fn into_diagnostic_arg(self) -> rustc_errors::DiagArgValue {
-        self.to_string().into_diagnostic_arg()
+impl<'tcx> rustc_errors::IntoDiagArg for TraitRefPrintSugared<'tcx> {
+    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
+        self.to_string().into_diag_arg()
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 39b5d3b6ea7..cac12e5ee0b 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -13,7 +13,7 @@ use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
 use crate::ty::{List, ParamEnv};
 use hir::def::DefKind;
 use rustc_data_structures::captures::Captures;
-use rustc_errors::{DiagArgValue, ErrorGuaranteed, IntoDiagnosticArg, MultiSpan};
+use rustc_errors::{DiagArgValue, ErrorGuaranteed, IntoDiagArg, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::LangItem;
@@ -1094,12 +1094,12 @@ impl<'tcx, T: IntoIterator> Binder<'tcx, T> {
     }
 }
 
-impl<'tcx, T> IntoDiagnosticArg for Binder<'tcx, T>
+impl<'tcx, T> IntoDiagArg for Binder<'tcx, T>
 where
-    T: IntoDiagnosticArg,
+    T: IntoDiagArg,
 {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
-        self.value.into_diagnostic_arg()
+    fn into_diag_arg(self) -> DiagArgValue {
+        self.value.into_diag_arg()
     }
 }
 
@@ -1307,9 +1307,9 @@ impl<'tcx> FnSig<'tcx> {
     }
 }
 
-impl<'tcx> IntoDiagnosticArg for FnSig<'tcx> {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
-        self.to_string().into_diagnostic_arg()
+impl<'tcx> IntoDiagArg for FnSig<'tcx> {
+    fn into_diag_arg(self) -> DiagArgValue {
+        self.to_string().into_diag_arg()
     }
 }
 
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index 31591983101..48c3ee1ba0f 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -506,13 +506,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             traverse_candidate(
                 candidate,
                 &mut Vec::new(),
-                &mut |leaf_candidate, parent_bindings| {
+                &mut |leaf_candidate, parent_data| {
                     if let Some(arm) = arm {
                         self.clear_top_scope(arm.scope);
                     }
                     let binding_end = self.bind_and_guard_matched_candidate(
                         leaf_candidate,
-                        parent_bindings,
+                        parent_data,
                         fake_borrow_temps,
                         scrutinee_span,
                         arm_match_scope,
@@ -524,12 +524,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     }
                     self.cfg.goto(binding_end, outer_source_info, target_block);
                 },
-                |inner_candidate, parent_bindings| {
-                    parent_bindings.push((inner_candidate.bindings, inner_candidate.ascriptions));
+                |inner_candidate, parent_data| {
+                    parent_data.push(inner_candidate.extra_data);
                     inner_candidate.subcandidates.into_iter()
                 },
-                |parent_bindings| {
-                    parent_bindings.pop();
+                |parent_data| {
+                    parent_data.pop();
                 },
             );
 
@@ -651,7 +651,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         if set_match_place {
             let mut next = Some(&candidate);
             while let Some(candidate_ref) = next.take() {
-                for binding in &candidate_ref.bindings {
+                for binding in &candidate_ref.extra_data.bindings {
                     let local = self.var_local_id(binding.var_id, OutsideGuard);
                     // `try_to_place` may fail if it is unable to resolve the given
                     // `PlaceBuilder` inside a closure. In this case, we don't want to include
@@ -924,22 +924,35 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     }
 }
 
-/// A pattern in a form suitable for generating code.
+/// Data extracted from a pattern that doesn't affect which branch is taken. Collected during
+/// pattern simplification and not mutated later.
 #[derive(Debug, Clone)]
-struct FlatPat<'pat, 'tcx> {
+struct PatternExtraData<'tcx> {
     /// [`Span`] of the original pattern.
     span: Span,
 
+    /// Bindings that must be established.
+    bindings: Vec<Binding<'tcx>>,
+
+    /// Types that must be asserted.
+    ascriptions: Vec<Ascription<'tcx>>,
+}
+
+impl<'tcx> PatternExtraData<'tcx> {
+    fn is_empty(&self) -> bool {
+        self.bindings.is_empty() && self.ascriptions.is_empty()
+    }
+}
+
+/// A pattern in a form suitable for generating code.
+#[derive(Debug, Clone)]
+struct FlatPat<'pat, 'tcx> {
     /// To match the pattern, all of these must be satisfied...
     // Invariant: all the `MatchPair`s are recursively simplified.
     // Invariant: or-patterns must be sorted to the end.
     match_pairs: Vec<MatchPair<'pat, 'tcx>>,
 
-    /// ...these bindings established...
-    bindings: Vec<Binding<'tcx>>,
-
-    /// ...and these types asserted.
-    ascriptions: Vec<Ascription<'tcx>>,
+    extra_data: PatternExtraData<'tcx>,
 }
 
 impl<'tcx, 'pat> FlatPat<'pat, 'tcx> {
@@ -948,43 +961,38 @@ impl<'tcx, 'pat> FlatPat<'pat, 'tcx> {
         pattern: &'pat Pat<'tcx>,
         cx: &mut Builder<'_, 'tcx>,
     ) -> Self {
-        let mut match_pairs = vec![MatchPair::new(place, pattern, cx)];
-        let mut bindings = Vec::new();
-        let mut ascriptions = Vec::new();
-
-        cx.simplify_match_pairs(&mut match_pairs, &mut bindings, &mut ascriptions);
-
-        FlatPat { span: pattern.span, match_pairs, bindings, ascriptions }
+        let mut flat_pat = FlatPat {
+            match_pairs: vec![MatchPair::new(place, pattern, cx)],
+            extra_data: PatternExtraData {
+                span: pattern.span,
+                bindings: Vec::new(),
+                ascriptions: Vec::new(),
+            },
+        };
+        cx.simplify_match_pairs(&mut flat_pat.match_pairs, &mut flat_pat.extra_data);
+        flat_pat
     }
 }
 
 #[derive(Debug)]
 struct Candidate<'pat, 'tcx> {
-    /// [`Span`] of the original pattern that gave rise to this candidate.
-    span: Span,
-
-    /// Whether this `Candidate` has a guard.
-    has_guard: bool,
-
-    /// All of these must be satisfied...
+    /// For the candidate to match, all of these must be satisfied...
     // Invariant: all the `MatchPair`s are recursively simplified.
     // Invariant: or-patterns must be sorted at the end.
     match_pairs: Vec<MatchPair<'pat, 'tcx>>,
 
-    /// ...these bindings established...
-    // Invariant: not mutated after candidate creation.
-    bindings: Vec<Binding<'tcx>>,
-
-    /// ...and these types asserted...
-    // Invariant: not mutated after candidate creation.
-    ascriptions: Vec<Ascription<'tcx>>,
-
     /// ...and if this is non-empty, one of these subcandidates also has to match...
     subcandidates: Vec<Candidate<'pat, 'tcx>>,
 
-    /// ...and the guard must be evaluated; if it's `false` then branch to `otherwise_block`.
+    /// ...and the guard must be evaluated if there is one.
+    has_guard: bool,
+
+    /// If the guard is `false` then branch to `otherwise_block`.
     otherwise_block: Option<BasicBlock>,
 
+    /// If the candidate matches, bindings and ascriptions must be established.
+    extra_data: PatternExtraData<'tcx>,
+
     /// The block before the `bindings` have been established.
     pre_binding_block: Option<BasicBlock>,
     /// The pre-binding block of the next candidate.
@@ -1003,10 +1011,8 @@ impl<'tcx, 'pat> Candidate<'pat, 'tcx> {
 
     fn from_flat_pat(flat_pat: FlatPat<'pat, 'tcx>, has_guard: bool) -> Self {
         Candidate {
-            span: flat_pat.span,
             match_pairs: flat_pat.match_pairs,
-            bindings: flat_pat.bindings,
-            ascriptions: flat_pat.ascriptions,
+            extra_data: flat_pat.extra_data,
             has_guard,
             subcandidates: Vec::new(),
             otherwise_block: None,
@@ -1518,9 +1524,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             self.merge_trivial_subcandidates(subcandidate, source_info);
 
             // FIXME(or_patterns; matthewjasper) Try to be more aggressive here.
-            can_merge &= subcandidate.subcandidates.is_empty()
-                && subcandidate.bindings.is_empty()
-                && subcandidate.ascriptions.is_empty();
+            can_merge &=
+                subcandidate.subcandidates.is_empty() && subcandidate.extra_data.is_empty();
         }
 
         if can_merge {
@@ -1943,7 +1948,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
     fn bind_and_guard_matched_candidate<'pat>(
         &mut self,
         candidate: Candidate<'pat, 'tcx>,
-        parent_bindings: &[(Vec<Binding<'tcx>>, Vec<Ascription<'tcx>>)],
+        parent_data: &[PatternExtraData<'tcx>],
         fake_borrows: &[(Place<'tcx>, Local)],
         scrutinee_span: Span,
         arm_match_scope: Option<(&Arm<'tcx>, region::Scope)>,
@@ -1954,7 +1959,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
         debug_assert!(candidate.match_pairs.is_empty());
 
-        let candidate_source_info = self.source_info(candidate.span);
+        let candidate_source_info = self.source_info(candidate.extra_data.span);
 
         let mut block = candidate.pre_binding_block.unwrap();
 
@@ -1971,11 +1976,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
 
         self.ascribe_types(
             block,
-            parent_bindings
+            parent_data
                 .iter()
-                .flat_map(|(_, ascriptions)| ascriptions)
+                .flat_map(|d| &d.ascriptions)
                 .cloned()
-                .chain(candidate.ascriptions),
+                .chain(candidate.extra_data.ascriptions),
         );
 
         // rust-lang/rust#27282: The `autoref` business deserves some
@@ -2063,10 +2068,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             && let Some(guard) = arm.guard
         {
             let tcx = self.tcx;
-            let bindings = parent_bindings
-                .iter()
-                .flat_map(|(bindings, _)| bindings)
-                .chain(&candidate.bindings);
+            let bindings =
+                parent_data.iter().flat_map(|d| &d.bindings).chain(&candidate.extra_data.bindings);
 
             self.bind_matched_candidate_for_guard(block, schedule_drops, bindings.clone());
             let guard_frame = GuardFrame {
@@ -2144,10 +2147,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             // ```
             //
             // and that is clearly not correct.
-            let by_value_bindings = parent_bindings
+            let by_value_bindings = parent_data
                 .iter()
-                .flat_map(|(bindings, _)| bindings)
-                .chain(&candidate.bindings)
+                .flat_map(|d| &d.bindings)
+                .chain(&candidate.extra_data.bindings)
                 .filter(|binding| matches!(binding.binding_mode, BindingMode::ByValue));
             // Read all of the by reference bindings to ensure that the
             // place they refer to can't be modified by the guard.
@@ -2172,10 +2175,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             self.bind_matched_candidate_for_arm_body(
                 block,
                 schedule_drops,
-                parent_bindings
-                    .iter()
-                    .flat_map(|(bindings, _)| bindings)
-                    .chain(&candidate.bindings),
+                parent_data.iter().flat_map(|d| &d.bindings).chain(&candidate.extra_data.bindings),
                 storages_alive,
             );
             block
diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs
index a3fccb7c319..97b94a0b362 100644
--- a/compiler/rustc_mir_build/src/build/matches/simplify.rs
+++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs
@@ -12,20 +12,19 @@
 //! sort of test: for example, testing which variant an enum is, or
 //! testing a value against a constant.
 
-use crate::build::matches::{Ascription, Binding, Candidate, FlatPat, MatchPair, TestCase};
+use crate::build::matches::{Candidate, FlatPat, MatchPair, PatternExtraData, TestCase};
 use crate::build::Builder;
 
 use std::mem;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
     /// Simplify a list of match pairs so they all require a test. Stores relevant bindings and
-    /// ascriptions in the provided `Vec`s.
+    /// ascriptions in `extra_data`.
     #[instrument(skip(self), level = "debug")]
     pub(super) fn simplify_match_pairs<'pat>(
         &mut self,
         match_pairs: &mut Vec<MatchPair<'pat, 'tcx>>,
-        candidate_bindings: &mut Vec<Binding<'tcx>>,
-        candidate_ascriptions: &mut Vec<Ascription<'tcx>>,
+        extra_data: &mut PatternExtraData<'tcx>,
     ) {
         // In order to please the borrow checker, in a pattern like `x @ pat` we must lower the
         // bindings in `pat` before `x`. E.g. (#69971):
@@ -45,17 +44,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         // after any bindings in `pat`. This doesn't work for or-patterns: the current structure of
         // match lowering forces us to lower bindings inside or-patterns last.
         for mut match_pair in mem::take(match_pairs) {
-            self.simplify_match_pairs(
-                &mut match_pair.subpairs,
-                candidate_bindings,
-                candidate_ascriptions,
-            );
+            self.simplify_match_pairs(&mut match_pair.subpairs, extra_data);
             if let TestCase::Irrefutable { binding, ascription } = match_pair.test_case {
                 if let Some(binding) = binding {
-                    candidate_bindings.push(binding);
+                    extra_data.bindings.push(binding);
                 }
                 if let Some(ascription) = ascription {
-                    candidate_ascriptions.push(ascription);
+                    extra_data.ascriptions.push(ascription);
                 }
                 // Simplifiable pattern; we replace it with its already simplified subpairs.
                 match_pairs.append(&mut match_pair.subpairs);
diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs
index 2351f69a914..d0d49c13f13 100644
--- a/compiler/rustc_mir_build/src/build/matches/util.rs
+++ b/compiler/rustc_mir_build/src/build/matches/util.rs
@@ -280,7 +280,7 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
     }
 
     fn visit_candidate(&mut self, candidate: &Candidate<'_, 'tcx>) {
-        for binding in &candidate.bindings {
+        for binding in &candidate.extra_data.bindings {
             self.visit_binding(binding);
         }
         for match_pair in &candidate.match_pairs {
@@ -289,7 +289,7 @@ impl<'a, 'b, 'tcx> FakeBorrowCollector<'a, 'b, 'tcx> {
     }
 
     fn visit_flat_pat(&mut self, flat_pat: &FlatPat<'_, 'tcx>) {
-        for binding in &flat_pat.bindings {
+        for binding in &flat_pat.extra_data.bindings {
             self.visit_binding(binding);
         }
         for match_pair in &flat_pat.match_pairs {
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index 961502566ba..88ac05cabb6 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -203,16 +203,31 @@ const ROOT_NODE: DropIdx = DropIdx::from_u32(0);
 /// in `build_mir`.
 #[derive(Debug)]
 struct DropTree {
-    /// Drops in the tree.
-    drops: IndexVec<DropIdx, (DropData, DropIdx)>,
-    /// Map for finding the inverse of the `next_drop` relation:
-    ///
-    /// `previous_drops[(drops[i].1, drops[i].0.local, drops[i].0.kind)] == i`
-    previous_drops: FxHashMap<(DropIdx, Local, DropKind), DropIdx>,
+    /// Nodes in the drop tree, containing drop data and a link to the next node.
+    drops: IndexVec<DropIdx, DropNode>,
+    /// Map for finding the index of an existing node, given its contents.
+    existing_drops_map: FxHashMap<DropNodeKey, DropIdx>,
     /// Edges into the `DropTree` that need to be added once it's lowered.
     entry_points: Vec<(DropIdx, BasicBlock)>,
 }
 
+/// A single node in the drop tree.
+#[derive(Debug)]
+struct DropNode {
+    /// Info about the drop to be performed at this node in the drop tree.
+    data: DropData,
+    /// Index of the "next" drop to perform (in drop order, not declaration order).
+    next: DropIdx,
+}
+
+/// Subset of [`DropNode`] used for reverse lookup in a hash table.
+#[derive(Debug, PartialEq, Eq, Hash)]
+struct DropNodeKey {
+    next: DropIdx,
+    local: Local,
+    kind: DropKind,
+}
+
 impl Scope {
     /// Whether there's anything to do for the cleanup path, that is,
     /// when unwinding through this scope. This includes destructors,
@@ -247,7 +262,7 @@ trait DropTreeBuilder<'tcx> {
 
     /// Links a block outside the drop tree, `from`, to the block `to` inside
     /// the drop tree.
-    fn add_entry(cfg: &mut CFG<'tcx>, from: BasicBlock, to: BasicBlock);
+    fn link_entry_point(cfg: &mut CFG<'tcx>, from: BasicBlock, to: BasicBlock);
 }
 
 impl DropTree {
@@ -258,20 +273,29 @@ impl DropTree {
         let fake_source_info = SourceInfo::outermost(DUMMY_SP);
         let fake_data =
             DropData { source_info: fake_source_info, local: Local::MAX, kind: DropKind::Storage };
-        let drop_idx = DropIdx::MAX;
-        let drops = IndexVec::from_elem_n((fake_data, drop_idx), 1);
-        Self { drops, entry_points: Vec::new(), previous_drops: FxHashMap::default() }
+        let drops = IndexVec::from_raw(vec![DropNode { data: fake_data, next: DropIdx::MAX }]);
+        Self { drops, entry_points: Vec::new(), existing_drops_map: FxHashMap::default() }
     }
 
-    fn add_drop(&mut self, drop: DropData, next: DropIdx) -> DropIdx {
+    /// Adds a node to the drop tree, consisting of drop data and the index of
+    /// the "next" drop (in drop order), which could be the sentinel [`ROOT_NODE`].
+    ///
+    /// If there is already an equivalent node in the tree, nothing is added, and
+    /// that node's index is returned. Otherwise, the new node's index is returned.
+    fn add_drop(&mut self, data: DropData, next: DropIdx) -> DropIdx {
         let drops = &mut self.drops;
         *self
-            .previous_drops
-            .entry((next, drop.local, drop.kind))
-            .or_insert_with(|| drops.push((drop, next)))
+            .existing_drops_map
+            .entry(DropNodeKey { next, local: data.local, kind: data.kind })
+            // Create a new node, and also add its index to the map.
+            .or_insert_with(|| drops.push(DropNode { data, next }))
     }
 
-    fn add_entry(&mut self, from: BasicBlock, to: DropIdx) {
+    /// Registers `from` as an entry point to this drop tree, at `to`.
+    ///
+    /// During [`Self::build_mir`], `from` will be linked to the corresponding
+    /// block within the drop tree.
+    fn add_entry_point(&mut self, from: BasicBlock, to: DropIdx) {
         debug_assert!(to < self.drops.next_index());
         self.entry_points.push((to, from));
     }
@@ -326,13 +350,13 @@ impl DropTree {
         let entry_points = &mut self.entry_points;
         entry_points.sort();
 
-        for (drop_idx, drop_data) in self.drops.iter_enumerated().rev() {
+        for (drop_idx, drop_node) in self.drops.iter_enumerated().rev() {
             if entry_points.last().is_some_and(|entry_point| entry_point.0 == drop_idx) {
                 let block = *blocks[drop_idx].get_or_insert_with(|| T::make_block(cfg));
                 needs_block[drop_idx] = Block::Own;
                 while entry_points.last().is_some_and(|entry_point| entry_point.0 == drop_idx) {
                     let entry_block = entry_points.pop().unwrap().1;
-                    T::add_entry(cfg, entry_block, block);
+                    T::link_entry_point(cfg, entry_block, block);
                 }
             }
             match needs_block[drop_idx] {
@@ -344,10 +368,10 @@ impl DropTree {
                     blocks[drop_idx] = blocks[pred];
                 }
             }
-            if let DropKind::Value = drop_data.0.kind {
-                needs_block[drop_data.1] = Block::Own;
+            if let DropKind::Value = drop_node.data.kind {
+                needs_block[drop_node.next] = Block::Own;
             } else if drop_idx != ROOT_NODE {
-                match &mut needs_block[drop_data.1] {
+                match &mut needs_block[drop_node.next] {
                     pred @ Block::None => *pred = Block::Shares(drop_idx),
                     pred @ Block::Shares(_) => *pred = Block::Own,
                     Block::Own => (),
@@ -364,34 +388,35 @@ impl DropTree {
         cfg: &mut CFG<'tcx>,
         blocks: &IndexSlice<DropIdx, Option<BasicBlock>>,
     ) {
-        for (drop_idx, drop_data) in self.drops.iter_enumerated().rev() {
+        for (drop_idx, drop_node) in self.drops.iter_enumerated().rev() {
             let Some(block) = blocks[drop_idx] else { continue };
-            match drop_data.0.kind {
+            match drop_node.data.kind {
                 DropKind::Value => {
                     let terminator = TerminatorKind::Drop {
-                        target: blocks[drop_data.1].unwrap(),
+                        target: blocks[drop_node.next].unwrap(),
                         // The caller will handle this if needed.
                         unwind: UnwindAction::Terminate(UnwindTerminateReason::InCleanup),
-                        place: drop_data.0.local.into(),
+                        place: drop_node.data.local.into(),
                         replace: false,
                     };
-                    cfg.terminate(block, drop_data.0.source_info, terminator);
+                    cfg.terminate(block, drop_node.data.source_info, terminator);
                 }
                 // Root nodes don't correspond to a drop.
                 DropKind::Storage if drop_idx == ROOT_NODE => {}
                 DropKind::Storage => {
                     let stmt = Statement {
-                        source_info: drop_data.0.source_info,
-                        kind: StatementKind::StorageDead(drop_data.0.local),
+                        source_info: drop_node.data.source_info,
+                        kind: StatementKind::StorageDead(drop_node.data.local),
                     };
                     cfg.push(block, stmt);
-                    let target = blocks[drop_data.1].unwrap();
+                    let target = blocks[drop_node.next].unwrap();
                     if target != block {
                         // Diagnostics don't use this `Span` but debuginfo
                         // might. Since we don't want breakpoints to be placed
                         // here, especially when this is on an unwind path, we
                         // use `DUMMY_SP`.
-                        let source_info = SourceInfo { span: DUMMY_SP, ..drop_data.0.source_info };
+                        let source_info =
+                            SourceInfo { span: DUMMY_SP, ..drop_node.data.source_info };
                         let terminator = TerminatorKind::Goto { target };
                         cfg.terminate(block, source_info, terminator);
                     }
@@ -673,11 +698,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             .flat_map(|scope| &scope.drops)
             .fold(ROOT_NODE, |drop_idx, &drop| drops.add_drop(drop, drop_idx));
 
-        drops.add_entry(block, drop_idx);
+        drops.add_entry_point(block, drop_idx);
 
         // `build_drop_trees` doesn't have access to our source_info, so we
         // create a dummy terminator now. `TerminatorKind::UnwindResume` is used
         // because MIR type checking will panic if it hasn't been overwritten.
+        // (See `<ExitScopes as DropTreeBuilder>::link_entry_point`.)
         self.cfg.terminate(block, source_info, TerminatorKind::UnwindResume);
 
         self.cfg.start_new_block().unit()
@@ -708,11 +734,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 drop_idx = drops.add_drop(*drop, drop_idx);
             }
         }
-        drops.add_entry(block, drop_idx);
+        drops.add_entry_point(block, drop_idx);
 
         // `build_drop_trees` doesn't have access to our source_info, so we
         // create a dummy terminator now. `TerminatorKind::UnwindResume` is used
         // because MIR type checking will panic if it hasn't been overwritten.
+        // (See `<ExitScopes as DropTreeBuilder>::link_entry_point`.)
         self.cfg.terminate(block, source_info, TerminatorKind::UnwindResume);
     }
 
@@ -1119,7 +1146,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         );
 
         let next_drop = self.diverge_cleanup();
-        self.scopes.unwind_drops.add_entry(start, next_drop);
+        self.scopes.unwind_drops.add_entry_point(start, next_drop);
     }
 
     /// Sets up a path that performs all required cleanup for dropping a
@@ -1153,7 +1180,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             scope.cached_coroutine_drop_block = Some(cached_drop);
         }
 
-        self.scopes.coroutine_drops.add_entry(yield_block, cached_drop);
+        self.scopes.coroutine_drops.add_entry_point(yield_block, cached_drop);
     }
 
     /// Utility function for *non*-scope code to build their own drops
@@ -1274,9 +1301,9 @@ fn build_scope_drops<'tcx>(
                 // `unwind_to` should drop the value that we're about to
                 // schedule. If dropping this value panics, then we continue
                 // with the *next* value on the unwind path.
-                debug_assert_eq!(unwind_drops.drops[unwind_to].0.local, drop_data.local);
-                debug_assert_eq!(unwind_drops.drops[unwind_to].0.kind, drop_data.kind);
-                unwind_to = unwind_drops.drops[unwind_to].1;
+                debug_assert_eq!(unwind_drops.drops[unwind_to].data.local, drop_data.local);
+                debug_assert_eq!(unwind_drops.drops[unwind_to].data.kind, drop_data.kind);
+                unwind_to = unwind_drops.drops[unwind_to].next;
 
                 // If the operand has been moved, and we are not on an unwind
                 // path, then don't generate the drop. (We only take this into
@@ -1286,7 +1313,7 @@ fn build_scope_drops<'tcx>(
                     continue;
                 }
 
-                unwind_drops.add_entry(block, unwind_to);
+                unwind_drops.add_entry_point(block, unwind_to);
 
                 let next = cfg.start_new_block();
                 cfg.terminate(
@@ -1303,9 +1330,9 @@ fn build_scope_drops<'tcx>(
             }
             DropKind::Storage => {
                 if storage_dead_on_unwind {
-                    debug_assert_eq!(unwind_drops.drops[unwind_to].0.local, drop_data.local);
-                    debug_assert_eq!(unwind_drops.drops[unwind_to].0.kind, drop_data.kind);
-                    unwind_to = unwind_drops.drops[unwind_to].1;
+                    debug_assert_eq!(unwind_drops.drops[unwind_to].data.local, drop_data.local);
+                    debug_assert_eq!(unwind_drops.drops[unwind_to].data.kind, drop_data.kind);
+                    unwind_to = unwind_drops.drops[unwind_to].next;
                 }
                 // Only temps and vars need their storage dead.
                 assert!(local.index() > arg_count);
@@ -1335,30 +1362,31 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
         let is_coroutine = self.coroutine.is_some();
 
         // Link the exit drop tree to unwind drop tree.
-        if drops.drops.iter().any(|(drop, _)| drop.kind == DropKind::Value) {
+        if drops.drops.iter().any(|drop_node| drop_node.data.kind == DropKind::Value) {
             let unwind_target = self.diverge_cleanup_target(else_scope, span);
             let mut unwind_indices = IndexVec::from_elem_n(unwind_target, 1);
-            for (drop_idx, drop_data) in drops.drops.iter_enumerated().skip(1) {
-                match drop_data.0.kind {
+            for (drop_idx, drop_node) in drops.drops.iter_enumerated().skip(1) {
+                match drop_node.data.kind {
                     DropKind::Storage => {
                         if is_coroutine {
                             let unwind_drop = self
                                 .scopes
                                 .unwind_drops
-                                .add_drop(drop_data.0, unwind_indices[drop_data.1]);
+                                .add_drop(drop_node.data, unwind_indices[drop_node.next]);
                             unwind_indices.push(unwind_drop);
                         } else {
-                            unwind_indices.push(unwind_indices[drop_data.1]);
+                            unwind_indices.push(unwind_indices[drop_node.next]);
                         }
                     }
                     DropKind::Value => {
                         let unwind_drop = self
                             .scopes
                             .unwind_drops
-                            .add_drop(drop_data.0, unwind_indices[drop_data.1]);
-                        self.scopes
-                            .unwind_drops
-                            .add_entry(blocks[drop_idx].unwrap(), unwind_indices[drop_data.1]);
+                            .add_drop(drop_node.data, unwind_indices[drop_node.next]);
+                        self.scopes.unwind_drops.add_entry_point(
+                            blocks[drop_idx].unwrap(),
+                            unwind_indices[drop_node.next],
+                        );
                         unwind_indices.push(unwind_drop);
                     }
                 }
@@ -1408,10 +1436,10 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
         // prevent drop elaboration from creating drop flags that would have
         // to be captured by the coroutine. I'm not sure how important this
         // optimization is, but it is here.
-        for (drop_idx, drop_data) in drops.drops.iter_enumerated() {
-            if let DropKind::Value = drop_data.0.kind {
-                debug_assert!(drop_data.1 < drops.drops.next_index());
-                drops.entry_points.push((drop_data.1, blocks[drop_idx].unwrap()));
+        for (drop_idx, drop_node) in drops.drops.iter_enumerated() {
+            if let DropKind::Value = drop_node.data.kind {
+                debug_assert!(drop_node.next < drops.drops.next_index());
+                drops.entry_points.push((drop_node.next, blocks[drop_idx].unwrap()));
             }
         }
         Self::build_unwind_tree(cfg, drops, fn_span, resume_block);
@@ -1442,8 +1470,16 @@ impl<'tcx> DropTreeBuilder<'tcx> for ExitScopes {
     fn make_block(cfg: &mut CFG<'tcx>) -> BasicBlock {
         cfg.start_new_block()
     }
-    fn add_entry(cfg: &mut CFG<'tcx>, from: BasicBlock, to: BasicBlock) {
-        cfg.block_data_mut(from).terminator_mut().kind = TerminatorKind::Goto { target: to };
+    fn link_entry_point(cfg: &mut CFG<'tcx>, from: BasicBlock, to: BasicBlock) {
+        // There should be an existing terminator with real source info and a
+        // dummy TerminatorKind. Replace it with a proper goto.
+        // (The dummy is added by `break_scope` and `break_for_else`.)
+        let term = cfg.block_data_mut(from).terminator_mut();
+        if let TerminatorKind::UnwindResume = term.kind {
+            term.kind = TerminatorKind::Goto { target: to };
+        } else {
+            span_bug!(term.source_info.span, "unexpected dummy terminator kind: {:?}", term.kind);
+        }
     }
 }
 
@@ -1453,7 +1489,7 @@ impl<'tcx> DropTreeBuilder<'tcx> for CoroutineDrop {
     fn make_block(cfg: &mut CFG<'tcx>) -> BasicBlock {
         cfg.start_new_block()
     }
-    fn add_entry(cfg: &mut CFG<'tcx>, from: BasicBlock, to: BasicBlock) {
+    fn link_entry_point(cfg: &mut CFG<'tcx>, from: BasicBlock, to: BasicBlock) {
         let term = cfg.block_data_mut(from).terminator_mut();
         if let TerminatorKind::Yield { ref mut drop, .. } = term.kind {
             *drop = Some(to);
@@ -1473,7 +1509,7 @@ impl<'tcx> DropTreeBuilder<'tcx> for Unwind {
     fn make_block(cfg: &mut CFG<'tcx>) -> BasicBlock {
         cfg.start_new_cleanup_block()
     }
-    fn add_entry(cfg: &mut CFG<'tcx>, from: BasicBlock, to: BasicBlock) {
+    fn link_entry_point(cfg: &mut CFG<'tcx>, from: BasicBlock, to: BasicBlock) {
         let term = &mut cfg.block_data_mut(from).terminator_mut();
         match &mut term.kind {
             TerminatorKind::Drop { unwind, .. } => {
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index 9a298a13eb6..2b4c6541857 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -1,8 +1,8 @@
 use crate::fluent_generated as fluent;
 use rustc_errors::DiagArgValue;
 use rustc_errors::{
-    codes::*, AddToDiagnostic, Applicability, Diag, DiagCtxt, EmissionGuarantee, IntoDiagnostic,
-    Level, MultiSpan, SubdiagMessageOp,
+    codes::*, Applicability, Diag, DiagCtxt, Diagnostic, EmissionGuarantee, Level, MultiSpan,
+    SubdiagMessageOp, Subdiagnostic,
 };
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_middle::ty::{self, Ty};
@@ -419,8 +419,8 @@ pub struct UnsafeNotInheritedLintNote {
     pub body_span: Span,
 }
 
-impl AddToDiagnostic for UnsafeNotInheritedLintNote {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for UnsafeNotInheritedLintNote {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
@@ -461,10 +461,8 @@ pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'p, 'tcx, 'm> {
     pub ty: Ty<'tcx>,
 }
 
-impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G>
-    for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_>
-{
-    fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'_, G> {
+impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> {
+    fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'_, G> {
         let mut diag =
             Diag::new(dcx, level, fluent::mir_build_non_exhaustive_patterns_type_not_empty);
         diag.span(self.span);
@@ -867,8 +865,8 @@ pub struct Variant {
     pub span: Span,
 }
 
-impl<'tcx> AddToDiagnostic for AdtDefinedHere<'tcx> {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl<'tcx> Subdiagnostic for AdtDefinedHere<'tcx> {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs
index 80e9172bbe1..9297bc51fad 100644
--- a/compiler/rustc_mir_transform/src/errors.rs
+++ b/compiler/rustc_mir_transform/src/errors.rs
@@ -1,8 +1,8 @@
 use std::borrow::Cow;
 
 use rustc_errors::{
-    codes::*, Applicability, DecorateLint, Diag, DiagArgValue, DiagCtxt, DiagMessage,
-    EmissionGuarantee, IntoDiagnostic, Level,
+    codes::*, Applicability, Diag, DiagArgValue, DiagCtxt, DiagMessage, Diagnostic,
+    EmissionGuarantee, Level, LintDiagnostic,
 };
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_middle::mir::{AssertKind, UnsafetyViolationDetails};
@@ -62,9 +62,9 @@ pub(crate) struct RequiresUnsafe {
 // so we need to eagerly translate the label here, which isn't supported by the derive API
 // We could also exhaustively list out the primary messages for all unsafe violations,
 // but this would result in a lot of duplication.
-impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for RequiresUnsafe {
+impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for RequiresUnsafe {
     #[track_caller]
-    fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
+    fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
         let mut diag = Diag::new(dcx, level, fluent::mir_transform_requires_unsafe);
         diag.code(E0133);
         diag.span(self.span);
@@ -181,7 +181,7 @@ pub(crate) struct UnsafeOpInUnsafeFn {
     pub suggest_unsafe_block: Option<(Span, Span, Span)>,
 }
 
-impl<'a> DecorateLint<'a, ()> for UnsafeOpInUnsafeFn {
+impl<'a> LintDiagnostic<'a, ()> for UnsafeOpInUnsafeFn {
     #[track_caller]
     fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
         let desc = diag.dcx.eagerly_translate_to_string(self.details.label(), [].into_iter());
@@ -215,7 +215,7 @@ pub(crate) enum AssertLintKind {
     UnconditionalPanic,
 }
 
-impl<'a, P: std::fmt::Debug> DecorateLint<'a, ()> for AssertLint<P> {
+impl<'a, P: std::fmt::Debug> LintDiagnostic<'a, ()> for AssertLint<P> {
     fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
         let message = self.assert_kind.diagnostic_message();
         self.assert_kind.add_args(&mut |name, value| {
@@ -269,7 +269,7 @@ pub(crate) struct MustNotSupend<'tcx, 'a> {
 }
 
 // Needed for def_path_str
-impl<'a> DecorateLint<'a, ()> for MustNotSupend<'_, '_> {
+impl<'a> LintDiagnostic<'a, ()> for MustNotSupend<'_, '_> {
     fn decorate_lint<'b>(self, diag: &'b mut rustc_errors::Diag<'a, ()>) {
         diag.span_label(self.yield_sp, fluent::_subdiag::label);
         if let Some(reason) = self.reason {
diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
index d9387ecd14c..0970c4de19f 100644
--- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
+++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
@@ -11,7 +11,7 @@ use rustc_target::spec::PanicStrategy;
 use crate::errors;
 
 /// Some of the functions declared as "may unwind" by `fn_can_unwind` can't actually unwind. In
-/// particular, `extern "C"` is still considered as can-unwind on stable, but we need to to consider
+/// particular, `extern "C"` is still considered as can-unwind on stable, but we need to consider
 /// it cannot-unwind here. So below we check `fn_can_unwind() && abi_can_unwind()` before concluding
 /// that a function call can unwind.
 fn abi_can_unwind(abi: Abi) -> bool {
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 32f823a5ac6..a18448eabf3 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -1339,14 +1339,12 @@ impl<'v> RootCollector<'_, 'v> {
             main_ret_ty.no_bound_vars().unwrap(),
         );
 
-        let start_instance = Instance::resolve(
+        let start_instance = Instance::expect_resolve(
             self.tcx,
             ty::ParamEnv::reveal_all(),
             start_def_id,
             self.tcx.mk_args(&[main_ret_ty.into()]),
-        )
-        .unwrap()
-        .unwrap();
+        );
 
         self.output.push(create_fn_mono_item(self.tcx, start_instance, DUMMY_SP));
     }
diff --git a/compiler/rustc_monomorphize/src/errors.rs b/compiler/rustc_monomorphize/src/errors.rs
index 1303ac9939c..35fc78f2045 100644
--- a/compiler/rustc_monomorphize/src/errors.rs
+++ b/compiler/rustc_monomorphize/src/errors.rs
@@ -1,7 +1,7 @@
 use std::path::PathBuf;
 
 use crate::fluent_generated as fluent;
-use rustc_errors::{Diag, DiagCtxt, EmissionGuarantee, IntoDiagnostic, Level};
+use rustc_errors::{Diag, DiagCtxt, Diagnostic, EmissionGuarantee, Level};
 use rustc_macros::{Diagnostic, LintDiagnostic};
 use rustc_span::{Span, Symbol};
 
@@ -46,9 +46,9 @@ pub struct UnusedGenericParamsHint {
     pub param_names: Vec<String>,
 }
 
-impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for UnusedGenericParamsHint {
+impl<G: EmissionGuarantee> Diagnostic<'_, G> for UnusedGenericParamsHint {
     #[track_caller]
-    fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> Diag<'_, G> {
+    fn into_diag(self, dcx: &'_ DiagCtxt, level: Level) -> Diag<'_, G> {
         let mut diag = Diag::new(dcx, level, fluent::monomorphize_unused_generic_params);
         diag.span(self.span);
         for (span, name) in self.param_spans.into_iter().zip(self.param_names) {
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 60cc138fd7b..a100e2d47bb 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -392,9 +392,6 @@ parse_invalid_identifier_with_leading_number = identifiers cannot start with a n
 
 parse_invalid_interpolated_expression = invalid interpolated expression
 
-parse_invalid_literal_suffix = suffixes on {$kind} literals are invalid
-    .label = invalid suffix `{$suffix}`
-
 parse_invalid_literal_suffix_on_tuple_index = suffixes on a tuple index are invalid
     .label = invalid suffix `{$suffix}`
     .tuple_exception_line_1 = `{$suffix}` is *temporarily* accepted on tuple index fields as it was incorrectly accepted on stable for a few releases
@@ -609,7 +606,6 @@ parse_nonterminal_expected_item_keyword = expected an item keyword
 parse_nonterminal_expected_lifetime = expected a lifetime, found `{$token}`
 
 parse_nonterminal_expected_statement = expected a statement
-parse_not_supported = not supported
 
 parse_note_edition_guide = for more on editions, read https://doc.rust-lang.org/edition-guide
 
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index c72b7e2cfa7..32b56bb7e87 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -3,8 +3,8 @@ use std::borrow::Cow;
 use rustc_ast::token::Token;
 use rustc_ast::{Path, Visibility};
 use rustc_errors::{
-    codes::*, AddToDiagnostic, Applicability, Diag, DiagCtxt, EmissionGuarantee, IntoDiagnostic,
-    Level, SubdiagMessageOp,
+    codes::*, Applicability, Diag, DiagCtxt, Diagnostic, EmissionGuarantee, Level,
+    SubdiagMessageOp, Subdiagnostic,
 };
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_session::errors::ExprParenthesesNeeded;
@@ -1065,9 +1065,9 @@ pub(crate) struct ExpectedIdentifier {
     pub help_cannot_start_number: Option<HelpIdentifierStartsWithNumber>,
 }
 
-impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedIdentifier {
+impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedIdentifier {
     #[track_caller]
-    fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
+    fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
         let token_descr = TokenDescription::from_token(&self.token);
 
         let mut diag = Diag::new(
@@ -1093,17 +1093,17 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedIdentifier {
         diag.arg("token", self.token);
 
         if let Some(sugg) = self.suggest_raw {
-            sugg.add_to_diagnostic(&mut diag);
+            sugg.add_to_diag(&mut diag);
         }
 
-        ExpectedIdentifierFound::new(token_descr, self.span).add_to_diagnostic(&mut diag);
+        ExpectedIdentifierFound::new(token_descr, self.span).add_to_diag(&mut diag);
 
         if let Some(sugg) = self.suggest_remove_comma {
-            sugg.add_to_diagnostic(&mut diag);
+            sugg.add_to_diag(&mut diag);
         }
 
         if let Some(help) = self.help_cannot_start_number {
-            help.add_to_diagnostic(&mut diag);
+            help.add_to_diag(&mut diag);
         }
 
         diag
@@ -1125,9 +1125,9 @@ pub(crate) struct ExpectedSemi {
     pub sugg: ExpectedSemiSugg,
 }
 
-impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedSemi {
+impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for ExpectedSemi {
     #[track_caller]
-    fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
+    fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
         let token_descr = TokenDescription::from_token(&self.token);
 
         let mut diag = Diag::new(
@@ -1154,7 +1154,7 @@ impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedSemi {
             diag.span_label(unexpected_token_label, fluent::parse_label_unexpected_token);
         }
 
-        self.sugg.add_to_diagnostic(&mut diag);
+        self.sugg.add_to_diag(&mut diag);
 
         diag
     }
@@ -1466,8 +1466,8 @@ pub(crate) struct FnTraitMissingParen {
     pub machine_applicable: bool,
 }
 
-impl AddToDiagnostic for FnTraitMissingParen {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for FnTraitMissingParen {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _: F,
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index de088b9364b..7038b8bbe47 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -36,8 +36,8 @@ use rustc_ast::{
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{
-    pluralize, AddToDiagnostic, Applicability, Diag, DiagCtxt, ErrorGuaranteed, FatalError, PErr,
-    PResult,
+    pluralize, Applicability, Diag, DiagCtxt, ErrorGuaranteed, FatalError, PErr, PResult,
+    Subdiagnostic,
 };
 use rustc_session::errors::ExprParenthesesNeeded;
 use rustc_span::source_map::Spanned;
@@ -298,7 +298,7 @@ impl<'a> Parser<'a> {
         {
             recovered_ident = Some((ident, IdentIsRaw::Yes));
 
-            // `Symbol::to_string()` is different from `Symbol::into_diagnostic_arg()`,
+            // `Symbol::to_string()` is different from `Symbol::into_diag_arg()`,
             // which uses `Symbol::to_ident_string()` and "helpfully" adds an implicit `r#`
             let ident_name = ident.name.to_string();
 
@@ -1271,7 +1271,7 @@ impl<'a> Parser<'a> {
                 Ok(_) => {
                     if self.token == token::Eq {
                         let sugg = SuggAddMissingLetStmt { span: prev_span };
-                        sugg.add_to_diagnostic(err);
+                        sugg.add_to_diag(err);
                     }
                 }
                 Err(e) => {
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 7a34bc7890c..e27a5f93799 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -27,7 +27,7 @@ use rustc_ast::{Arm, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLim
 use rustc_ast::{ClosureBinder, MetaItemLit, StmtKind};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::stack::ensure_sufficient_stack;
-use rustc_errors::{AddToDiagnostic, Applicability, Diag, PResult, StashKey};
+use rustc_errors::{Applicability, Diag, PResult, StashKey, Subdiagnostic};
 use rustc_lexer::unescape::unescape_char;
 use rustc_macros::Subdiagnostic;
 use rustc_session::errors::{report_lit_error, ExprParenthesesNeeded};
@@ -3451,8 +3451,8 @@ impl<'a> Parser<'a> {
         let in_if_guard = self.restrictions.contains(Restrictions::IN_IF_GUARD);
 
         let async_block_err = |e: &mut Diag<'_>, span: Span| {
-            errors::AsyncBlockIn2015 { span }.add_to_diagnostic(e);
-            errors::HelpUseLatestEdition::new().add_to_diagnostic(e);
+            errors::AsyncBlockIn2015 { span }.add_to_diag(e);
+            errors::HelpUseLatestEdition::new().add_to_diag(e);
         };
 
         while self.token != token::CloseDelim(close_delim) {
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 545db5138a3..2edf2111de7 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -1,6 +1,7 @@
 use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
 use super::{Parser, Restrictions, TokenType};
 use crate::errors::PathSingleColon;
+use crate::parser::{CommaRecoveryMode, RecoverColon, RecoverComma};
 use crate::{errors, maybe_whole};
 use ast::token::IdentIsRaw;
 use rustc_ast::ptr::P;
@@ -10,7 +11,7 @@ use rustc_ast::{
     AssocConstraintKind, BlockCheckMode, GenericArg, GenericArgs, Generics, ParenthesizedArgs,
     Path, PathSegment, QSelf,
 };
-use rustc_errors::{Applicability, PResult};
+use rustc_errors::{Applicability, Diag, PResult};
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{BytePos, Span};
 use std::mem;
@@ -373,7 +374,38 @@ impl<'a> Parser<'a> {
                     .into()
                 } else {
                     // `(T, U) -> R`
-                    let (inputs, _) = self.parse_paren_comma_seq(|p| p.parse_ty())?;
+
+                    let prev_token_before_parsing = self.prev_token.clone();
+                    let token_before_parsing = self.token.clone();
+                    let mut snapshot = None;
+                    if self.may_recover()
+                        && prev_token_before_parsing.kind == token::ModSep
+                        && (style == PathStyle::Expr && self.token.can_begin_expr()
+                            || style == PathStyle::Pat && self.token.can_begin_pattern())
+                    {
+                        snapshot = Some(self.create_snapshot_for_diagnostic());
+                    }
+
+                    let (inputs, _) = match self.parse_paren_comma_seq(|p| p.parse_ty()) {
+                        Ok(output) => output,
+                        Err(mut error) if prev_token_before_parsing.kind == token::ModSep => {
+                            error.span_label(
+                                prev_token_before_parsing.span.to(token_before_parsing.span),
+                                "while parsing this parenthesized list of type arguments starting here",
+                            );
+
+                            if let Some(mut snapshot) = snapshot {
+                                snapshot.recover_fn_call_leading_path_sep(
+                                    style,
+                                    prev_token_before_parsing,
+                                    &mut error,
+                                )
+                            }
+
+                            return Err(error);
+                        }
+                        Err(error) => return Err(error),
+                    };
                     let inputs_span = lo.to(self.prev_token.span);
                     let output =
                         self.parse_ret_ty(AllowPlus::No, RecoverQPath::No, RecoverReturnSign::No)?;
@@ -399,6 +431,56 @@ impl<'a> Parser<'a> {
         }
     }
 
+    /// Recover `$path::(...)` as `$path(...)`.
+    ///
+    /// ```ignore (diagnostics)
+    /// foo::(420, "bar")
+    ///    ^^ remove extra separator to make the function call
+    /// // or
+    /// match x {
+    ///    Foo::(420, "bar") => { ... },
+    ///       ^^ remove extra separator to turn this into tuple struct pattern
+    ///    _ => { ... },
+    /// }
+    /// ```
+    fn recover_fn_call_leading_path_sep(
+        &mut self,
+        style: PathStyle,
+        prev_token_before_parsing: Token,
+        error: &mut Diag<'_>,
+    ) {
+        if ((style == PathStyle::Expr && self.parse_paren_comma_seq(|p| p.parse_expr()).is_ok())
+            || (style == PathStyle::Pat
+                && self
+                    .parse_paren_comma_seq(|p| {
+                        p.parse_pat_allow_top_alt(
+                            None,
+                            RecoverComma::No,
+                            RecoverColon::No,
+                            CommaRecoveryMode::LikelyTuple,
+                        )
+                    })
+                    .is_ok()))
+            && !matches!(self.token.kind, token::ModSep | token::RArrow)
+        {
+            error.span_suggestion_verbose(
+                prev_token_before_parsing.span,
+                format!(
+                    "consider removing the `::` here to {}",
+                    match style {
+                        PathStyle::Expr => "call the expression",
+                        PathStyle::Pat => "turn this into a tuple struct pattern",
+                        _ => {
+                            return;
+                        }
+                    }
+                ),
+                "",
+                Applicability::MaybeIncorrect,
+            );
+        }
+    }
+
     /// Parses generic args (within a path segment) with recovery for extra leading angle brackets.
     /// For the purposes of understanding the parsing logic of generic arguments, this function
     /// can be thought of being the same as just calling `self.parse_angle_args()` if the source
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index c223b847528..7fc523ffe0d 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -302,9 +302,6 @@ passes_export_name =
     attribute should be applied to a free function, impl method or static
     .label = not a free function, impl method or static
 
-passes_expr_not_allowed_in_context =
-    {$expr} is not allowed in a `{$context}`
-
 passes_extern_main =
     the `main` function cannot be declared in an `extern` block
 
@@ -405,8 +402,6 @@ passes_lang_item_on_incorrect_target =
     `{$name}` language item must be applied to a {$expected_target}
     .label = attribute should be applied to a {$expected_target}, not a {$actual_target}
 
-passes_layout =
-    layout error: {$layout_error}
 passes_layout_abi =
     abi: {$abi}
 passes_layout_align =
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index a99db9cb8cc..91ab5b30dea 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -9,7 +9,7 @@ use rustc_ast::{ast, AttrKind, AttrStyle, Attribute, LitKind};
 use rustc_ast::{MetaItemKind, MetaItemLit, NestedMetaItem};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::StashKey;
-use rustc_errors::{Applicability, DiagCtxt, IntoDiagnosticArg, MultiSpan};
+use rustc_errors::{Applicability, DiagCtxt, IntoDiagArg, MultiSpan};
 use rustc_feature::{AttributeDuplicates, AttributeType, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalModDefId;
@@ -79,14 +79,14 @@ pub(crate) enum ProcMacroKind {
     Attribute,
 }
 
-impl IntoDiagnosticArg for ProcMacroKind {
-    fn into_diagnostic_arg(self) -> rustc_errors::DiagArgValue {
+impl IntoDiagArg for ProcMacroKind {
+    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
         match self {
             ProcMacroKind::Attribute => "attribute proc macro",
             ProcMacroKind::Derive => "derive proc macro",
             ProcMacroKind::FunctionLike => "function-like proc macro",
         }
-        .into_diagnostic_arg()
+        .into_diag_arg()
     }
 }
 
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index a3106856a67..cdfde2b9405 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -15,7 +15,7 @@ use rustc_hir::{Node, PatKind, TyKind};
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::middle::privacy::Level;
 use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, TyCtxt, Visibility};
+use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::lint;
 use rustc_session::lint::builtin::DEAD_CODE;
 use rustc_span::symbol::{sym, Symbol};
@@ -45,6 +45,18 @@ fn should_explore(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
     )
 }
 
+fn ty_ref_to_pub_struct(tcx: TyCtxt<'_>, ty: &hir::Ty<'_>) -> bool {
+    if let TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind
+        && let Res::Def(def_kind, def_id) = path.res
+        && def_id.is_local()
+        && matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union)
+    {
+        tcx.visibility(def_id).is_public()
+    } else {
+        true
+    }
+}
+
 /// Determine if a work from the worklist is coming from the a `#[allow]`
 /// or a `#[expect]` of `dead_code`
 #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
@@ -415,6 +427,13 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
                             && let ItemKind::Impl(impl_ref) =
                                 self.tcx.hir().expect_item(local_impl_id).kind
                         {
+                            if self.tcx.visibility(trait_id).is_public()
+                                && matches!(trait_item.kind, hir::TraitItemKind::Fn(..))
+                                && !ty_ref_to_pub_struct(self.tcx, impl_ref.self_ty)
+                            {
+                                continue;
+                            }
+
                             // mark self_ty live
                             intravisit::walk_ty(self, impl_ref.self_ty);
                             if let Some(&impl_item_id) =
@@ -465,6 +484,36 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
             }
         }
     }
+
+    fn solve_rest_impl_items(&mut self, mut unsolved_impl_items: Vec<(hir::ItemId, LocalDefId)>) {
+        let mut ready;
+        (ready, unsolved_impl_items) = unsolved_impl_items
+            .into_iter()
+            .partition(|&(impl_id, _)| self.impl_item_with_used_self(impl_id));
+
+        while !ready.is_empty() {
+            self.worklist =
+                ready.into_iter().map(|(_, id)| (id, ComesFromAllowExpect::No)).collect();
+            self.mark_live_symbols();
+
+            (ready, unsolved_impl_items) = unsolved_impl_items
+                .into_iter()
+                .partition(|&(impl_id, _)| self.impl_item_with_used_self(impl_id));
+        }
+    }
+
+    fn impl_item_with_used_self(&mut self, impl_id: hir::ItemId) -> bool {
+        if let TyKind::Path(hir::QPath::Resolved(_, path)) =
+            self.tcx.hir().item(impl_id).expect_impl().self_ty.kind
+            && let Res::Def(def_kind, def_id) = path.res
+            && let Some(local_def_id) = def_id.as_local()
+            && matches!(def_kind, DefKind::Struct | DefKind::Enum | DefKind::Union)
+        {
+            self.live_symbols.contains(&local_def_id)
+        } else {
+            false
+        }
+    }
 }
 
 impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
@@ -652,6 +701,7 @@ fn check_item<'tcx>(
     tcx: TyCtxt<'tcx>,
     worklist: &mut Vec<(LocalDefId, ComesFromAllowExpect)>,
     struct_constructors: &mut LocalDefIdMap<LocalDefId>,
+    unsolved_impl_items: &mut Vec<(hir::ItemId, LocalDefId)>,
     id: hir::ItemId,
 ) {
     let allow_dead_code = has_allow_dead_code_or_lang_attr(tcx, id.owner_id.def_id);
@@ -683,16 +733,33 @@ fn check_item<'tcx>(
                 .iter()
                 .filter_map(|def_id| def_id.as_local());
 
+            let ty_is_pub = ty_ref_to_pub_struct(tcx, tcx.hir().item(id).expect_impl().self_ty);
+
             // And we access the Map here to get HirId from LocalDefId
-            for id in local_def_ids {
+            for local_def_id in local_def_ids {
+                // check the function may construct Self
+                let mut may_construct_self = true;
+                if let Some(hir_id) = tcx.opt_local_def_id_to_hir_id(local_def_id)
+                    && let Some(fn_sig) = tcx.hir().fn_sig_by_hir_id(hir_id)
+                {
+                    may_construct_self =
+                        matches!(fn_sig.decl.implicit_self, hir::ImplicitSelfKind::None);
+                }
+
                 // for impl trait blocks, mark associate functions live if the trait is public
                 if of_trait
-                    && (!matches!(tcx.def_kind(id), DefKind::AssocFn)
-                        || tcx.local_visibility(id) == Visibility::Public)
+                    && (!matches!(tcx.def_kind(local_def_id), DefKind::AssocFn)
+                        || tcx.visibility(local_def_id).is_public()
+                            && (ty_is_pub || may_construct_self))
                 {
-                    worklist.push((id, ComesFromAllowExpect::No));
-                } else if let Some(comes_from_allow) = has_allow_dead_code_or_lang_attr(tcx, id) {
-                    worklist.push((id, comes_from_allow));
+                    worklist.push((local_def_id, ComesFromAllowExpect::No));
+                } else if of_trait && tcx.visibility(local_def_id).is_public() {
+                    // pub method && private ty & methods not construct self
+                    unsolved_impl_items.push((id, local_def_id));
+                } else if let Some(comes_from_allow) =
+                    has_allow_dead_code_or_lang_attr(tcx, local_def_id)
+                {
+                    worklist.push((local_def_id, comes_from_allow));
                 }
             }
         }
@@ -743,9 +810,14 @@ fn check_foreign_item(
 
 fn create_and_seed_worklist(
     tcx: TyCtxt<'_>,
-) -> (Vec<(LocalDefId, ComesFromAllowExpect)>, LocalDefIdMap<LocalDefId>) {
+) -> (
+    Vec<(LocalDefId, ComesFromAllowExpect)>,
+    LocalDefIdMap<LocalDefId>,
+    Vec<(hir::ItemId, LocalDefId)>,
+) {
     let effective_visibilities = &tcx.effective_visibilities(());
     // see `MarkSymbolVisitor::struct_constructors`
+    let mut unsolved_impl_item = Vec::new();
     let mut struct_constructors = Default::default();
     let mut worklist = effective_visibilities
         .iter()
@@ -764,7 +836,7 @@ fn create_and_seed_worklist(
 
     let crate_items = tcx.hir_crate_items(());
     for id in crate_items.items() {
-        check_item(tcx, &mut worklist, &mut struct_constructors, id);
+        check_item(tcx, &mut worklist, &mut struct_constructors, &mut unsolved_impl_item, id);
     }
 
     for id in crate_items.trait_items() {
@@ -775,14 +847,14 @@ fn create_and_seed_worklist(
         check_foreign_item(tcx, &mut worklist, id);
     }
 
-    (worklist, struct_constructors)
+    (worklist, struct_constructors, unsolved_impl_item)
 }
 
 fn live_symbols_and_ignored_derived_traits(
     tcx: TyCtxt<'_>,
     (): (),
 ) -> (LocalDefIdSet, LocalDefIdMap<Vec<(DefId, DefId)>>) {
-    let (worklist, struct_constructors) = create_and_seed_worklist(tcx);
+    let (worklist, struct_constructors, unsolved_impl_items) = create_and_seed_worklist(tcx);
     let mut symbol_visitor = MarkSymbolVisitor {
         worklist,
         tcx,
@@ -796,6 +868,8 @@ fn live_symbols_and_ignored_derived_traits(
         ignored_derived_traits: Default::default(),
     };
     symbol_visitor.mark_live_symbols();
+    symbol_visitor.solve_rest_impl_items(unsolved_impl_items);
+
     (symbol_visitor.live_symbols, symbol_visitor.ignored_derived_traits)
 }
 
diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs
index 5246389248e..0bab13037e4 100644
--- a/compiler/rustc_passes/src/entry.rs
+++ b/compiler/rustc_passes/src/entry.rs
@@ -156,13 +156,13 @@ fn sigpipe(tcx: TyCtxt<'_>, def_id: DefId) -> u8 {
             (Some(sym::inherit), None) => sigpipe::INHERIT,
             (Some(sym::sig_ign), None) => sigpipe::SIG_IGN,
             (Some(sym::sig_dfl), None) => sigpipe::SIG_DFL,
-            (_, Some(_)) => {
-                // Keep going so that `fn emit_malformed_attribute()` can print
-                // an excellent error message
+            (Some(_), None) => {
+                tcx.dcx().emit_err(UnixSigpipeValues { span: attr.span });
                 sigpipe::DEFAULT
             }
             _ => {
-                tcx.dcx().emit_err(UnixSigpipeValues { span: attr.span });
+                // Keep going so that `fn emit_malformed_attribute()` can print
+                // an excellent error message
                 sigpipe::DEFAULT
             }
         }
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 69104a30495..3f26ea4507d 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -6,8 +6,8 @@ use std::{
 use crate::fluent_generated as fluent;
 use rustc_ast::Label;
 use rustc_errors::{
-    codes::*, AddToDiagnostic, Applicability, Diag, DiagCtxt, DiagSymbolList, EmissionGuarantee,
-    IntoDiagnostic, Level, MultiSpan, SubdiagMessageOp,
+    codes::*, Applicability, Diag, DiagCtxt, DiagSymbolList, Diagnostic, EmissionGuarantee, Level,
+    MultiSpan, SubdiagMessageOp, Subdiagnostic,
 };
 use rustc_hir::{self as hir, ExprKind, Target};
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
@@ -862,9 +862,9 @@ pub struct ItemFollowingInnerAttr {
     pub kind: &'static str,
 }
 
-impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for InvalidAttrAtCrateLevel {
+impl<G: EmissionGuarantee> Diagnostic<'_, G> for InvalidAttrAtCrateLevel {
     #[track_caller]
-    fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> Diag<'_, G> {
+    fn into_diag(self, dcx: &'_ DiagCtxt, level: Level) -> Diag<'_, G> {
         let mut diag = Diag::new(dcx, level, fluent::passes_invalid_attr_at_crate_level);
         diag.span(self.span);
         diag.arg("name", self.name);
@@ -1012,9 +1012,9 @@ pub struct BreakNonLoop<'a> {
     pub break_expr_span: Span,
 }
 
-impl<'a, G: EmissionGuarantee> IntoDiagnostic<'_, G> for BreakNonLoop<'a> {
+impl<'a, G: EmissionGuarantee> Diagnostic<'_, G> for BreakNonLoop<'a> {
     #[track_caller]
-    fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> Diag<'_, G> {
+    fn into_diag(self, dcx: &DiagCtxt, level: Level) -> Diag<'_, G> {
         let mut diag = Diag::new(dcx, level, fluent::passes_break_non_loop);
         diag.span(self.span);
         diag.code(E0571);
@@ -1156,9 +1156,9 @@ pub struct NakedFunctionsAsmBlock {
     pub non_asms: Vec<Span>,
 }
 
-impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for NakedFunctionsAsmBlock {
+impl<G: EmissionGuarantee> Diagnostic<'_, G> for NakedFunctionsAsmBlock {
     #[track_caller]
-    fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> Diag<'_, G> {
+    fn into_diag(self, dcx: &DiagCtxt, level: Level) -> Diag<'_, G> {
         let mut diag = Diag::new(dcx, level, fluent::passes_naked_functions_asm_block);
         diag.span(self.span);
         diag.code(E0787);
@@ -1267,9 +1267,9 @@ pub struct NoMainErr {
     pub add_teach_note: bool,
 }
 
-impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for NoMainErr {
+impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for NoMainErr {
     #[track_caller]
-    fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
+    fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
         let mut diag = Diag::new(dcx, level, fluent::passes_no_main_function);
         diag.span(DUMMY_SP);
         diag.code(E0601);
@@ -1325,9 +1325,9 @@ pub struct DuplicateLangItem {
     pub(crate) duplicate: Duplicate,
 }
 
-impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for DuplicateLangItem {
+impl<G: EmissionGuarantee> Diagnostic<'_, G> for DuplicateLangItem {
     #[track_caller]
-    fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> Diag<'_, G> {
+    fn into_diag(self, dcx: &DiagCtxt, level: Level) -> Diag<'_, G> {
         let mut diag = Diag::new(
             dcx,
             level,
@@ -1751,8 +1751,8 @@ pub struct UnusedVariableStringInterp {
     pub hi: Span,
 }
 
-impl AddToDiagnostic for UnusedVariableStringInterp {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for UnusedVariableStringInterp {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
diff --git a/compiler/rustc_pattern_analysis/src/errors.rs b/compiler/rustc_pattern_analysis/src/errors.rs
index e471b8abd73..21a61d46ccb 100644
--- a/compiler/rustc_pattern_analysis/src/errors.rs
+++ b/compiler/rustc_pattern_analysis/src/errors.rs
@@ -1,4 +1,4 @@
-use rustc_errors::{AddToDiagnostic, Diag, EmissionGuarantee, SubdiagMessageOp};
+use rustc_errors::{Diag, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic};
 use rustc_macros::{LintDiagnostic, Subdiagnostic};
 use rustc_middle::thir::Pat;
 use rustc_middle::ty::Ty;
@@ -61,8 +61,8 @@ pub struct Overlap<'tcx> {
     pub range: Pat<'tcx>,
 }
 
-impl<'tcx> AddToDiagnostic for Overlap<'tcx> {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl<'tcx> Subdiagnostic for Overlap<'tcx> {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _: F,
@@ -109,8 +109,8 @@ pub struct GappedRange<'tcx> {
     pub first_range: Pat<'tcx>,
 }
 
-impl<'tcx> AddToDiagnostic for GappedRange<'tcx> {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl<'tcx> Subdiagnostic for GappedRange<'tcx> {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _: F,
diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs
index 30e775733de..16530960656 100644
--- a/compiler/rustc_pattern_analysis/src/lints.rs
+++ b/compiler/rustc_pattern_analysis/src/lints.rs
@@ -97,7 +97,7 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'p, 'tcx>(
                     lint_name: "non_exhaustive_omitted_patterns",
                 };
 
-                use rustc_errors::DecorateLint;
+                use rustc_errors::LintDiagnostic;
                 let mut err = rcx.tcx.dcx().struct_span_warn(arm.pat.data().unwrap().span, "");
                 err.primary_message(decorator.msg());
                 decorator.decorate_lint(&mut err);
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index 7dc1a1f7917..9f067273f35 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -1,9 +1,8 @@
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_data_structures::profiling::{EventId, QueryInvocationId, SelfProfilerRef};
+use rustc_data_structures::profiling::{QueryInvocationId, SelfProfilerRef};
 use rustc_data_structures::sharded::{self, Sharded};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-use rustc_data_structures::steal::Steal;
 use rustc_data_structures::sync::{AtomicU32, AtomicU64, Lock, Lrc};
 use rustc_data_structures::unord::UnordMap;
 use rustc_index::IndexVec;
@@ -134,7 +133,6 @@ impl<D: Deps> DepGraph<D> {
 
         // Instantiate a dependy-less node only once for anonymous queries.
         let _green_node_index = current.intern_new_node(
-            profiler,
             DepNode { kind: D::DEP_KIND_NULL, hash: current.anon_id_seed.into() },
             EdgesVec::new(),
             Fingerprint::ZERO,
@@ -143,7 +141,6 @@ impl<D: Deps> DepGraph<D> {
 
         // Instantiate a dependy-less red node only once for anonymous queries.
         let (red_node_index, red_node_prev_index_and_color) = current.intern_node(
-            profiler,
             &prev_graph,
             DepNode { kind: D::DEP_KIND_RED, hash: Fingerprint::ZERO.into() },
             EdgesVec::new(),
@@ -196,7 +193,7 @@ impl<D: Deps> DepGraph<D> {
 
     pub fn with_query(&self, f: impl Fn(&DepGraphQuery)) {
         if let Some(data) = &self.data {
-            data.current.encoder.borrow().with_query(f)
+            data.current.encoder.with_query(f)
         }
     }
 
@@ -372,13 +369,8 @@ impl<D: Deps> DepGraphData<D> {
             hash_result.map(|f| dcx.with_stable_hashing_context(|mut hcx| f(&mut hcx, &result)));
 
         // Intern the new `DepNode`.
-        let (dep_node_index, prev_and_color) = self.current.intern_node(
-            dcx.profiler(),
-            &self.previous,
-            key,
-            edges,
-            current_fingerprint,
-        );
+        let (dep_node_index, prev_and_color) =
+            self.current.intern_node(&self.previous, key, edges, current_fingerprint);
 
         hashing_timer.finish_with_query_invocation_id(dep_node_index.into());
 
@@ -443,12 +435,7 @@ impl<D: Deps> DepGraphData<D> {
                     hash: self.current.anon_id_seed.combine(hasher.finish()).into(),
                 };
 
-                self.current.intern_new_node(
-                    cx.profiler(),
-                    target_dep_node,
-                    task_deps,
-                    Fingerprint::ZERO,
-                )
+                self.current.intern_new_node(target_dep_node, task_deps, Fingerprint::ZERO)
             }
         };
 
@@ -585,13 +572,8 @@ impl<D: Deps> DepGraph<D> {
             });
 
             // Intern the new `DepNode` with the dependencies up-to-now.
-            let (dep_node_index, prev_and_color) = data.current.intern_node(
-                cx.profiler(),
-                &data.previous,
-                node,
-                edges,
-                current_fingerprint,
-            );
+            let (dep_node_index, prev_and_color) =
+                data.current.intern_node(&data.previous, node, edges, current_fingerprint);
 
             hashing_timer.finish_with_query_invocation_id(dep_node_index.into());
 
@@ -871,11 +853,8 @@ impl<D: Deps> DepGraphData<D> {
 
         // We allocating an entry for the node in the current dependency graph and
         // adding all the appropriate edges imported from the previous graph
-        let dep_node_index = self.current.promote_node_and_deps_to_current(
-            qcx.dep_context().profiler(),
-            &self.previous,
-            prev_dep_node_index,
-        );
+        let dep_node_index =
+            self.current.promote_node_and_deps_to_current(&self.previous, prev_dep_node_index);
 
         // ... emitting any stored diagnostic ...
 
@@ -974,19 +953,15 @@ impl<D: Deps> DepGraph<D> {
 
     pub fn print_incremental_info(&self) {
         if let Some(data) = &self.data {
-            data.current.encoder.borrow().print_incremental_info(
+            data.current.encoder.print_incremental_info(
                 data.current.total_read_count.load(Ordering::Relaxed),
                 data.current.total_duplicate_read_count.load(Ordering::Relaxed),
             )
         }
     }
 
-    pub fn finish_encoding(&self, profiler: &SelfProfilerRef) -> FileEncodeResult {
-        if let Some(data) = &self.data {
-            data.current.encoder.steal().finish(profiler)
-        } else {
-            Ok(0)
-        }
+    pub fn finish_encoding(&self) -> FileEncodeResult {
+        if let Some(data) = &self.data { data.current.encoder.finish() } else { Ok(0) }
     }
 
     pub(crate) fn next_virtual_depnode_index(&self) -> DepNodeIndex {
@@ -1069,7 +1044,7 @@ rustc_index::newtype_index! {
 /// manipulating both, we acquire `new_node_to_index` or `prev_index_to_index`
 /// first, and `data` second.
 pub(super) struct CurrentDepGraph<D: Deps> {
-    encoder: Steal<GraphEncoder<D>>,
+    encoder: GraphEncoder<D>,
     new_node_to_index: Sharded<FxHashMap<DepNode, DepNodeIndex>>,
     prev_index_to_index: Lock<IndexVec<SerializedDepNodeIndex, Option<DepNodeIndex>>>,
 
@@ -1100,12 +1075,6 @@ pub(super) struct CurrentDepGraph<D: Deps> {
     /// debugging and only active with `debug_assertions`.
     total_read_count: AtomicU64,
     total_duplicate_read_count: AtomicU64,
-
-    /// The cached event id for profiling node interning. This saves us
-    /// from having to look up the event id every time we intern a node
-    /// which may incur too much overhead.
-    /// This will be None if self-profiling is disabled.
-    node_intern_event_id: Option<EventId>,
 }
 
 impl<D: Deps> CurrentDepGraph<D> {
@@ -1140,17 +1109,14 @@ impl<D: Deps> CurrentDepGraph<D> {
 
         let new_node_count_estimate = 102 * prev_graph_node_count / 100 + 200;
 
-        let node_intern_event_id = profiler
-            .get_or_alloc_cached_string("incr_comp_intern_dep_graph_node")
-            .map(EventId::from_label);
-
         CurrentDepGraph {
-            encoder: Steal::new(GraphEncoder::new(
+            encoder: GraphEncoder::new(
                 encoder,
                 prev_graph_node_count,
                 record_graph,
                 record_stats,
-            )),
+                profiler,
+            ),
             new_node_to_index: Sharded::new(|| {
                 FxHashMap::with_capacity_and_hasher(
                     new_node_count_estimate / sharded::shards(),
@@ -1165,7 +1131,6 @@ impl<D: Deps> CurrentDepGraph<D> {
             fingerprints: Lock::new(IndexVec::from_elem_n(None, new_node_count_estimate)),
             total_read_count: AtomicU64::new(0),
             total_duplicate_read_count: AtomicU64::new(0),
-            node_intern_event_id,
         }
     }
 
@@ -1183,7 +1148,6 @@ impl<D: Deps> CurrentDepGraph<D> {
     #[inline(always)]
     fn intern_new_node(
         &self,
-        profiler: &SelfProfilerRef,
         key: DepNode,
         edges: EdgesVec,
         current_fingerprint: Fingerprint,
@@ -1191,8 +1155,7 @@ impl<D: Deps> CurrentDepGraph<D> {
         let dep_node_index = match self.new_node_to_index.lock_shard_by_value(&key).entry(key) {
             Entry::Occupied(entry) => *entry.get(),
             Entry::Vacant(entry) => {
-                let dep_node_index =
-                    self.encoder.borrow().send(profiler, key, current_fingerprint, edges);
+                let dep_node_index = self.encoder.send(key, current_fingerprint, edges);
                 entry.insert(dep_node_index);
                 dep_node_index
             }
@@ -1206,16 +1169,11 @@ impl<D: Deps> CurrentDepGraph<D> {
 
     fn intern_node(
         &self,
-        profiler: &SelfProfilerRef,
         prev_graph: &SerializedDepGraph,
         key: DepNode,
         edges: EdgesVec,
         fingerprint: Option<Fingerprint>,
     ) -> (DepNodeIndex, Option<(SerializedDepNodeIndex, DepNodeColor)>) {
-        // Get timer for profiling `DepNode` interning
-        let _node_intern_timer =
-            self.node_intern_event_id.map(|eid| profiler.generic_activity_with_event_id(eid));
-
         if let Some(prev_index) = prev_graph.node_to_index_opt(&key) {
             let get_dep_node_index = |fingerprint| {
                 let mut prev_index_to_index = self.prev_index_to_index.lock();
@@ -1223,8 +1181,7 @@ impl<D: Deps> CurrentDepGraph<D> {
                 let dep_node_index = match prev_index_to_index[prev_index] {
                     Some(dep_node_index) => dep_node_index,
                     None => {
-                        let dep_node_index =
-                            self.encoder.borrow().send(profiler, key, fingerprint, edges);
+                        let dep_node_index = self.encoder.send(key, fingerprint, edges);
                         prev_index_to_index[prev_index] = Some(dep_node_index);
                         dep_node_index
                     }
@@ -1261,7 +1218,7 @@ impl<D: Deps> CurrentDepGraph<D> {
             let fingerprint = fingerprint.unwrap_or(Fingerprint::ZERO);
 
             // This is a new node: it didn't exist in the previous compilation session.
-            let dep_node_index = self.intern_new_node(profiler, key, edges, fingerprint);
+            let dep_node_index = self.intern_new_node(key, edges, fingerprint);
 
             (dep_node_index, None)
         }
@@ -1269,7 +1226,6 @@ impl<D: Deps> CurrentDepGraph<D> {
 
     fn promote_node_and_deps_to_current(
         &self,
-        profiler: &SelfProfilerRef,
         prev_graph: &SerializedDepGraph,
         prev_index: SerializedDepNodeIndex,
     ) -> DepNodeIndex {
@@ -1286,7 +1242,7 @@ impl<D: Deps> CurrentDepGraph<D> {
                     .map(|i| prev_index_to_index[i].unwrap())
                     .collect();
                 let fingerprint = prev_graph.fingerprint_by_index(prev_index);
-                let dep_node_index = self.encoder.borrow().send(profiler, key, fingerprint, edges);
+                let dep_node_index = self.encoder.send(key, fingerprint, edges);
                 prev_index_to_index[prev_index] = Some(dep_node_index);
                 #[cfg(debug_assertions)]
                 self.record_edge(dep_node_index, key, fingerprint);
diff --git a/compiler/rustc_query_system/src/dep_graph/serialized.rs b/compiler/rustc_query_system/src/dep_graph/serialized.rs
index 3272a0ed167..cc823917ce8 100644
--- a/compiler/rustc_query_system/src/dep_graph/serialized.rs
+++ b/compiler/rustc_query_system/src/dep_graph/serialized.rs
@@ -504,7 +504,8 @@ impl<D: Deps> EncoderState<D> {
 }
 
 pub struct GraphEncoder<D: Deps> {
-    status: Lock<EncoderState<D>>,
+    profiler: SelfProfilerRef,
+    status: Lock<Option<EncoderState<D>>>,
     record_graph: Option<Lock<DepGraphQuery>>,
 }
 
@@ -514,10 +515,11 @@ impl<D: Deps> GraphEncoder<D> {
         prev_node_count: usize,
         record_graph: bool,
         record_stats: bool,
+        profiler: &SelfProfilerRef,
     ) -> Self {
         let record_graph = record_graph.then(|| Lock::new(DepGraphQuery::new(prev_node_count)));
-        let status = Lock::new(EncoderState::new(encoder, record_stats));
-        GraphEncoder { status, record_graph }
+        let status = Lock::new(Some(EncoderState::new(encoder, record_stats)));
+        GraphEncoder { status, record_graph, profiler: profiler.clone() }
     }
 
     pub(crate) fn with_query(&self, f: impl Fn(&DepGraphQuery)) {
@@ -531,7 +533,8 @@ impl<D: Deps> GraphEncoder<D> {
         total_read_count: u64,
         total_duplicate_read_count: u64,
     ) {
-        let status = self.status.lock();
+        let mut status = self.status.lock();
+        let status = status.as_mut().unwrap();
         if let Some(record_stats) = &status.stats {
             let mut stats: Vec<_> = record_stats.values().collect();
             stats.sort_by_key(|s| -(s.node_counter as i64));
@@ -580,18 +583,18 @@ impl<D: Deps> GraphEncoder<D> {
 
     pub(crate) fn send(
         &self,
-        profiler: &SelfProfilerRef,
         node: DepNode,
         fingerprint: Fingerprint,
         edges: EdgesVec,
     ) -> DepNodeIndex {
-        let _prof_timer = profiler.generic_activity("incr_comp_encode_dep_graph");
+        let _prof_timer = self.profiler.generic_activity("incr_comp_encode_dep_graph");
         let node = NodeInfo { node, fingerprint, edges };
-        self.status.lock().encode_node(&node, &self.record_graph)
+        self.status.lock().as_mut().unwrap().encode_node(&node, &self.record_graph)
     }
 
-    pub fn finish(self, profiler: &SelfProfilerRef) -> FileEncodeResult {
-        let _prof_timer = profiler.generic_activity("incr_comp_encode_dep_graph");
-        self.status.into_inner().finish(profiler)
+    pub fn finish(&self) -> FileEncodeResult {
+        let _prof_timer = self.profiler.generic_activity("incr_comp_encode_dep_graph_finish");
+
+        self.status.lock().take().unwrap().finish(&self.profiler)
     }
 }
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index a9f5ed9908b..5eee6a51fd2 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -521,7 +521,7 @@ pub(crate) struct ToolModuleImported {
 #[diag(resolve_module_only)]
 pub(crate) struct ModuleOnly(#[primary_span] pub(crate) Span);
 
-#[derive(Diagnostic, Default)]
+#[derive(Diagnostic)]
 #[diag(resolve_macro_expected_found)]
 pub(crate) struct MacroExpectedFound<'a> {
     #[primary_span]
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index d2aea0056b3..ea07ed9e654 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -17,7 +17,7 @@ use rustc_ast::visit::{walk_list, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor}
 use rustc_ast::*;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
 use rustc_errors::{
-    codes::*, struct_span_code_err, Applicability, DiagArgValue, IntoDiagnosticArg, StashKey,
+    codes::*, struct_span_code_err, Applicability, DiagArgValue, IntoDiagArg, StashKey,
 };
 use rustc_hir::def::Namespace::{self, *};
 use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS};
@@ -89,8 +89,8 @@ impl PatternSource {
     }
 }
 
-impl IntoDiagnosticArg for PatternSource {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
+impl IntoDiagArg for PatternSource {
+    fn into_diag_arg(self) -> DiagArgValue {
         DiagArgValue::Str(Cow::Borrowed(self.descr()))
     }
 }
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index c7bb2a573b1..d8fd8d22439 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -562,7 +562,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
                 expected,
                 found: res.descr(),
                 macro_path: &path_str,
-                ..Default::default() // Subdiagnostics default to None
+                remove_surrounding_derive: None,
+                add_as_non_derive: None,
             };
 
             // Suggest moving the macro out of the derive() if the macro isn't Derive
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 61a220428b0..b947ac81805 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -8,12 +8,12 @@ pub use crate::options::*;
 use crate::errors::FileWriteFail;
 use crate::search_paths::SearchPath;
 use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
-use crate::{lint, HashStableContext};
+use crate::{filesearch, lint, HashStableContext};
 use crate::{EarlyDiagCtxt, Session};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey};
 use rustc_errors::emitter::HumanReadableErrorType;
-use rustc_errors::{ColorConfig, DiagArgValue, DiagCtxtFlags, IntoDiagnosticArg};
+use rustc_errors::{ColorConfig, DiagArgValue, DiagCtxtFlags, IntoDiagArg};
 use rustc_feature::UnstableFeatures;
 use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION};
 use rustc_span::source_map::FilePathMapping;
@@ -1564,7 +1564,7 @@ pub fn build_configuration(sess: &Session, mut user_cfg: Cfg) -> Cfg {
     user_cfg
 }
 
-pub(super) fn build_target_config(
+pub fn build_target_config(
     early_dcx: &EarlyDiagCtxt,
     opts: &Options,
     target_override: Option<Target>,
@@ -2863,16 +2863,8 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
 
     let logical_env = parse_logical_env(early_dcx, matches);
 
-    // Try to find a directory containing the Rust `src`, for more details see
-    // the doc comment on the `real_rust_source_base_dir` field.
-    let tmp_buf;
-    let sysroot = match &sysroot_opt {
-        Some(s) => s,
-        None => {
-            tmp_buf = crate::filesearch::get_or_default_sysroot().expect("Failed finding sysroot");
-            &tmp_buf
-        }
-    };
+    let sysroot = filesearch::materialize_sysroot(sysroot_opt);
+
     let real_rust_source_base_dir = {
         // This is the location used by the `rust-src` `rustup` component.
         let mut candidate = sysroot.join("lib/rustlib/src/rust");
@@ -2916,7 +2908,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M
         describe_lints,
         output_types,
         search_paths,
-        maybe_sysroot: sysroot_opt,
+        maybe_sysroot: Some(sysroot),
         target_triple,
         test,
         incremental,
@@ -3098,9 +3090,9 @@ impl fmt::Display for CrateType {
     }
 }
 
-impl IntoDiagnosticArg for CrateType {
-    fn into_diagnostic_arg(self) -> DiagArgValue {
-        self.to_string().into_diagnostic_arg()
+impl IntoDiagArg for CrateType {
+    fn into_diag_arg(self) -> DiagArgValue {
+        self.to_string().into_diag_arg()
     }
 }
 
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index 3c8ad27c07c..5f04915a9e7 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -3,8 +3,8 @@ use std::num::NonZero;
 use rustc_ast::token;
 use rustc_ast::util::literal::LitError;
 use rustc_errors::{
-    codes::*, Diag, DiagCtxt, DiagMessage, EmissionGuarantee, ErrorGuaranteed, IntoDiagnostic,
-    Level, MultiSpan,
+    codes::*, Diag, DiagCtxt, DiagMessage, Diagnostic, EmissionGuarantee, ErrorGuaranteed, Level,
+    MultiSpan,
 };
 use rustc_macros::Diagnostic;
 use rustc_span::{Span, Symbol};
@@ -17,9 +17,9 @@ pub struct FeatureGateError {
     pub explain: DiagMessage,
 }
 
-impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for FeatureGateError {
+impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for FeatureGateError {
     #[track_caller]
-    fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
+    fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
         Diag::new(dcx, level, self.explain).with_span(self.span).with_code(E0658)
     }
 }
diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs
index 2456b4b3a15..4f0e3354680 100644
--- a/compiler/rustc_session/src/filesearch.rs
+++ b/compiler/rustc_session/src/filesearch.rs
@@ -193,6 +193,12 @@ pub fn sysroot_candidates() -> SmallVec<[PathBuf; 2]> {
     return sysroot_candidates;
 }
 
+/// Returns the provided sysroot or calls [`get_or_default_sysroot`] if it's none.
+/// Panics if [`get_or_default_sysroot`]  returns an error.
+pub fn materialize_sysroot(maybe_sysroot: Option<PathBuf>) -> PathBuf {
+    maybe_sysroot.unwrap_or_else(|| get_or_default_sysroot().expect("Failed finding sysroot"))
+}
+
 /// This function checks if sysroot is found using env::args().next(), and if it
 /// is not found, finds sysroot from current rustc_driver dll.
 pub fn get_or_default_sysroot() -> Result<PathBuf, String> {
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 93bef82e4ba..ea4b8f2463e 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1772,7 +1772,7 @@ options! {
         "disable the 'leak check' for subtyping; unsound, but useful for tests"),
     no_link: bool = (false, parse_no_flag, [TRACKED],
         "compile without linking"),
-    no_parallel_llvm: bool = (false, parse_no_flag, [UNTRACKED],
+    no_parallel_backend: bool = (false, parse_no_flag, [UNTRACKED],
         "run LLVM in non-parallel mode (while keeping codegen-units and ThinLTO)"),
     no_profiler_runtime: bool = (false, parse_no_flag, [TRACKED],
         "prevent automatic injection of the profiler_builtins crate"),
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index ae1dbd13204..ab636b14d19 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -22,8 +22,8 @@ use rustc_errors::emitter::{stderr_destination, DynEmitter, HumanEmitter, HumanR
 use rustc_errors::json::JsonEmitter;
 use rustc_errors::registry::Registry;
 use rustc_errors::{
-    codes::*, fallback_fluent_bundle, Diag, DiagCtxt, DiagMessage, ErrorGuaranteed, FatalAbort,
-    FluentBundle, IntoDiagnostic, LazyFallbackBundle, TerminalUrl,
+    codes::*, fallback_fluent_bundle, Diag, DiagCtxt, DiagMessage, Diagnostic, ErrorGuaranteed,
+    FatalAbort, FluentBundle, LazyFallbackBundle, TerminalUrl,
 };
 use rustc_macros::HashStable_Generic;
 pub use rustc_span::def_id::StableCrateId;
@@ -111,9 +111,9 @@ impl Mul<usize> for Limit {
     }
 }
 
-impl rustc_errors::IntoDiagnosticArg for Limit {
-    fn into_diagnostic_arg(self) -> rustc_errors::DiagArgValue {
-        self.to_string().into_diagnostic_arg()
+impl rustc_errors::IntoDiagArg for Limit {
+    fn into_diag_arg(self) -> rustc_errors::DiagArgValue {
+        self.to_string().into_diag_arg()
     }
 }
 
@@ -305,11 +305,7 @@ impl Session {
     }
 
     #[track_caller]
-    pub fn create_feature_err<'a>(
-        &'a self,
-        err: impl IntoDiagnostic<'a>,
-        feature: Symbol,
-    ) -> Diag<'a> {
+    pub fn create_feature_err<'a>(&'a self, err: impl Diagnostic<'a>, feature: Symbol) -> Diag<'a> {
         let mut err = self.dcx().create_err(err);
         if err.code.is_none() {
             #[allow(rustc::diagnostic_outside_of_impl)]
@@ -1020,7 +1016,8 @@ pub fn build_session(
     fluent_resources: Vec<&'static str>,
     driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
     file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
-    target_override: Option<Target>,
+    target_cfg: Target,
+    sysroot: PathBuf,
     cfg_version: &'static str,
     ice_file: Option<PathBuf>,
     using_internal_features: Arc<AtomicBool>,
@@ -1037,12 +1034,6 @@ pub fn build_session(
     let cap_lints_allow = sopts.lint_cap.is_some_and(|cap| cap == lint::Allow);
     let can_emit_warnings = !(warnings_allow || cap_lints_allow);
 
-    let sysroot = match &sopts.maybe_sysroot {
-        Some(sysroot) => sysroot.clone(),
-        None => filesearch::get_or_default_sysroot().expect("Failed finding sysroot"),
-    };
-
-    let target_cfg = config::build_target_config(&early_dcx, &sopts, target_override, &sysroot);
     let host_triple = TargetTriple::from_triple(config::host_triple());
     let (host, target_warnings) = Target::search(&host_triple, &sysroot).unwrap_or_else(|e| {
         early_dcx.early_fatal(format!("Error loading host specification: {e}"))
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 708349e85ae..f592c1d3dd3 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -129,7 +129,6 @@ symbols! {
         Abi,
         AcqRel,
         Acquire,
-        AddToDiagnostic,
         Any,
         Arc,
         ArcWeak,
@@ -184,10 +183,10 @@ symbols! {
         DebugStruct,
         Decodable,
         Decoder,
-        DecorateLint,
         Default,
         Deref,
         DiagMessage,
+        Diagnostic,
         DirBuilder,
         Display,
         DoubleEndedIterator,
@@ -223,7 +222,6 @@ symbols! {
         Input,
         Instant,
         Into,
-        IntoDiagnostic,
         IntoFuture,
         IntoIterator,
         IoLines,
@@ -243,6 +241,7 @@ symbols! {
         Layout,
         Left,
         LinkedList,
+        LintDiagnostic,
         LintPass,
         LocalKey,
         Mutex,
@@ -305,6 +304,7 @@ symbols! {
         String,
         StructuralPartialEq,
         SubdiagMessage,
+        Subdiagnostic,
         Sync,
         T,
         Target,
@@ -864,6 +864,7 @@ symbols! {
         format_placeholder,
         format_unsafe_arg,
         freeze,
+        freeze_impls,
         freg,
         frem_algebraic,
         frem_fast,
diff --git a/compiler/rustc_symbol_mangling/src/errors.rs b/compiler/rustc_symbol_mangling/src/errors.rs
index b84e2f7b4ea..b5721ee489d 100644
--- a/compiler/rustc_symbol_mangling/src/errors.rs
+++ b/compiler/rustc_symbol_mangling/src/errors.rs
@@ -1,6 +1,6 @@
 //! Errors emitted by symbol_mangling.
 
-use rustc_errors::{Diag, DiagCtxt, EmissionGuarantee, IntoDiagnostic, Level};
+use rustc_errors::{Diag, DiagCtxt, Diagnostic, EmissionGuarantee, Level};
 use rustc_span::Span;
 use std::fmt;
 
@@ -13,8 +13,8 @@ pub struct TestOutput {
 // This diagnostic doesn't need translation because (a) it doesn't contain any
 // natural language, and (b) it's only used in tests. So we construct it
 // manually and avoid the fluent machinery.
-impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for TestOutput {
-    fn into_diagnostic(self, dcx: &'_ DiagCtxt, level: Level) -> Diag<'_, G> {
+impl<G: EmissionGuarantee> Diagnostic<'_, G> for TestOutput {
+    fn into_diag(self, dcx: &'_ DiagCtxt, level: Level) -> Diag<'_, G> {
         let TestOutput { span, kind, content } = self;
 
         #[allow(rustc::untranslatable_diagnostic)]
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index f4967b94e93..cb587e28a6c 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -46,16 +46,24 @@ pub enum PassMode {
     ///
     /// The argument has a layout abi of `ScalarPair`.
     Pair(ArgAttributes, ArgAttributes),
-    /// Pass the argument after casting it. See the `CastTarget` docs for details. The bool
-    /// indicates if a `Reg::i32()` dummy argument is emitted before the real argument.
+    /// Pass the argument after casting it. See the `CastTarget` docs for details.
+    ///
+    /// `pad_i32` indicates if a `Reg::i32()` dummy argument is emitted before the real argument.
     Cast { pad_i32: bool, cast: Box<CastTarget> },
     /// Pass the argument indirectly via a hidden pointer.
+    ///
     /// The `meta_attrs` value, if any, is for the metadata (vtable or length) of an unsized
     /// argument. (This is the only mode that supports unsized arguments.)
+    ///
     /// `on_stack` defines that the value should be passed at a fixed stack offset in accordance to
     /// the ABI rather than passed using a pointer. This corresponds to the `byval` LLVM argument
-    /// attribute (using the Rust type of this argument). `on_stack` cannot be true for unsized
-    /// arguments, i.e., when `meta_attrs` is `Some`.
+    /// attribute. The `byval` argument will use a byte array with the same size as the Rust type
+    /// (which ensures that padding is preserved and that we do not rely on LLVM's struct layout),
+    /// and will use the alignment specified in `attrs.pointee_align` (if `Some`) or the type's
+    /// alignment (if `None`). This means that the alignment will not always
+    /// match the Rust type's alignment; see documentation of `make_indirect_byval` for more info.
+    ///
+    /// `on_stack` cannot be true for unsized arguments, i.e., when `meta_attrs` is `Some`.
     Indirect { attrs: ArgAttributes, meta_attrs: Option<ArgAttributes>, on_stack: bool },
 }
 
@@ -596,6 +604,8 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
         }
     }
 
+    /// Pass this argument indirectly, by passing a (thin or fat) pointer to the argument instead.
+    /// This is valid for both sized and unsized arguments.
     pub fn make_indirect(&mut self) {
         match self.mode {
             PassMode::Direct(_) | PassMode::Pair(_, _) => {
@@ -609,7 +619,26 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
         }
     }
 
+    /// Pass this argument indirectly, by placing it at a fixed stack offset.
+    /// This corresponds to the `byval` LLVM argument attribute.
+    /// This is only valid for sized arguments.
+    ///
+    /// `byval_align` specifies the alignment of the `byval` stack slot, which does not need to
+    /// correspond to the type's alignment. This will be `Some` if the target's ABI specifies that
+    /// stack slots used for arguments passed by-value have specific alignment requirements which
+    /// differ from the alignment used in other situations.
+    ///
+    /// If `None`, the type's alignment is used.
+    ///
+    /// If the resulting alignment differs from the type's alignment,
+    /// the argument will be copied to an alloca with sufficient alignment,
+    /// either in the caller (if the type's alignment is lower than the byval alignment)
+    /// or in the callee† (if the type's alignment is higher than the byval alignment),
+    /// to ensure that Rust code never sees an underaligned pointer.
+    ///
+    /// † This is currently broken, see <https://github.com/rust-lang/rust/pull/122212>.
     pub fn make_indirect_byval(&mut self, byval_align: Option<Align>) {
+        assert!(!self.layout.is_unsized(), "used byval ABI for unsized layout");
         self.make_indirect();
         match self.mode {
             PassMode::Indirect { ref mut attrs, meta_attrs: _, ref mut on_stack } => {
diff --git a/compiler/rustc_target/src/abi/call/x86_64.rs b/compiler/rustc_target/src/abi/call/x86_64.rs
index 2eb50cc8dea..f3208fe5d03 100644
--- a/compiler/rustc_target/src/abi/call/x86_64.rs
+++ b/compiler/rustc_target/src/abi/call/x86_64.rs
@@ -217,6 +217,8 @@ where
         match cls_or_mem {
             Err(Memory) => {
                 if is_arg {
+                    // The x86_64 ABI doesn't have any special requirements for `byval` alignment,
+                    // the type's alignment is always used.
                     arg.make_indirect_byval(None);
                 } else {
                     // `sret` parameter thus one less integer register available
diff --git a/compiler/rustc_target/src/json.rs b/compiler/rustc_target/src/json.rs
index f3aecaaab98..9436e34d380 100644
--- a/compiler/rustc_target/src/json.rs
+++ b/compiler/rustc_target/src/json.rs
@@ -2,7 +2,9 @@ use std::borrow::Cow;
 use std::collections::BTreeMap;
 
 pub use serde_json::Value as Json;
-use serde_json::{Map, Number};
+use serde_json::{json, Map, Number};
+
+use crate::spec::TargetMetadata;
 
 pub trait ToJson {
     fn to_json(&self) -> Json;
@@ -120,3 +122,14 @@ impl ToJson for crate::abi::call::Conv {
         Json::String(s.to_owned())
     }
 }
+
+impl ToJson for TargetMetadata {
+    fn to_json(&self) -> Json {
+        json!({
+            "description": self.description,
+            "tier": self.tier,
+            "host_tools": self.host_tools,
+            "std": self.std,
+        })
+    }
+}
diff --git a/compiler/rustc_target/src/spec/base/avr_gnu.rs b/compiler/rustc_target/src/spec/base/avr_gnu.rs
index 1e410cea8d6..211d52f5b07 100644
--- a/compiler/rustc_target/src/spec/base/avr_gnu.rs
+++ b/compiler/rustc_target/src/spec/base/avr_gnu.rs
@@ -8,7 +8,12 @@ use object::elf;
 pub fn target(target_cpu: &'static str, mmcu: &'static str) -> Target {
     Target {
         arch: "avr".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8".into(),
         llvm_target: "avr-unknown-unknown".into(),
         pointer_width: 16,
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 3b6e15fad46..6bca86af30c 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -123,6 +123,8 @@ pub enum LinkerFlavor {
     Bpf,
     /// Linker tool for Nvidia PTX.
     Ptx,
+    /// LLVM bitcode linker that can be used as a `self-contained` linker
+    Llbc,
 }
 
 /// Linker flavors available externally through command line (`-Clinker-flavor`)
@@ -141,6 +143,7 @@ pub enum LinkerFlavorCli {
     EmCc,
     Bpf,
     Ptx,
+    Llbc,
 
     // Legacy stable values
     Gcc,
@@ -160,6 +163,7 @@ impl LinkerFlavorCli {
             | LinkerFlavorCli::Msvc(Lld::Yes)
             | LinkerFlavorCli::EmCc
             | LinkerFlavorCli::Bpf
+            | LinkerFlavorCli::Llbc
             | LinkerFlavorCli::Ptx => true,
             LinkerFlavorCli::Gcc
             | LinkerFlavorCli::Ld
@@ -219,6 +223,7 @@ impl LinkerFlavor {
             LinkerFlavorCli::Msvc(lld) => LinkerFlavor::Msvc(lld),
             LinkerFlavorCli::EmCc => LinkerFlavor::EmCc,
             LinkerFlavorCli::Bpf => LinkerFlavor::Bpf,
+            LinkerFlavorCli::Llbc => LinkerFlavor::Llbc,
             LinkerFlavorCli::Ptx => LinkerFlavor::Ptx,
 
             // Below: legacy stable values
@@ -258,6 +263,7 @@ impl LinkerFlavor {
             LinkerFlavor::Msvc(..) => LinkerFlavorCli::Msvc(Lld::No),
             LinkerFlavor::EmCc => LinkerFlavorCli::Em,
             LinkerFlavor::Bpf => LinkerFlavorCli::Bpf,
+            LinkerFlavor::Llbc => LinkerFlavorCli::Llbc,
             LinkerFlavor::Ptx => LinkerFlavorCli::Ptx,
         }
     }
@@ -272,6 +278,7 @@ impl LinkerFlavor {
             LinkerFlavor::Msvc(lld) => LinkerFlavorCli::Msvc(lld),
             LinkerFlavor::EmCc => LinkerFlavorCli::EmCc,
             LinkerFlavor::Bpf => LinkerFlavorCli::Bpf,
+            LinkerFlavor::Llbc => LinkerFlavorCli::Llbc,
             LinkerFlavor::Ptx => LinkerFlavorCli::Ptx,
         }
     }
@@ -286,6 +293,7 @@ impl LinkerFlavor {
             LinkerFlavorCli::Msvc(lld) => (Some(Cc::No), Some(lld)),
             LinkerFlavorCli::EmCc => (Some(Cc::Yes), Some(Lld::Yes)),
             LinkerFlavorCli::Bpf | LinkerFlavorCli::Ptx => (None, None),
+            LinkerFlavorCli::Llbc => (None, None),
 
             // Below: legacy stable values
             LinkerFlavorCli::Gcc => (Some(Cc::Yes), None),
@@ -340,7 +348,7 @@ impl LinkerFlavor {
             LinkerFlavor::WasmLld(cc) => LinkerFlavor::WasmLld(cc_hint.unwrap_or(cc)),
             LinkerFlavor::Unix(cc) => LinkerFlavor::Unix(cc_hint.unwrap_or(cc)),
             LinkerFlavor::Msvc(lld) => LinkerFlavor::Msvc(lld_hint.unwrap_or(lld)),
-            LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Ptx => self,
+            LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Llbc | LinkerFlavor::Ptx => self,
         }
     }
 
@@ -355,8 +363,8 @@ impl LinkerFlavor {
     pub fn check_compatibility(self, cli: LinkerFlavorCli) -> Option<String> {
         let compatible = |cli| {
             // The CLI flavor should be compatible with the target if:
-            // 1. they are counterparts: they have the same principal flavor.
             match (self, cli) {
+                // 1. they are counterparts: they have the same principal flavor.
                 (LinkerFlavor::Gnu(..), LinkerFlavorCli::Gnu(..))
                 | (LinkerFlavor::Darwin(..), LinkerFlavorCli::Darwin(..))
                 | (LinkerFlavor::WasmLld(..), LinkerFlavorCli::WasmLld(..))
@@ -364,11 +372,14 @@ impl LinkerFlavor {
                 | (LinkerFlavor::Msvc(..), LinkerFlavorCli::Msvc(..))
                 | (LinkerFlavor::EmCc, LinkerFlavorCli::EmCc)
                 | (LinkerFlavor::Bpf, LinkerFlavorCli::Bpf)
+                | (LinkerFlavor::Llbc, LinkerFlavorCli::Llbc)
                 | (LinkerFlavor::Ptx, LinkerFlavorCli::Ptx) => return true,
+                // 2. The linker flavor is independent of target and compatible
+                (LinkerFlavor::Ptx, LinkerFlavorCli::Llbc) => return true,
                 _ => {}
             }
 
-            // 2. or, the flavor is legacy and survives this roundtrip.
+            // 3. or, the flavor is legacy and survives this roundtrip.
             cli == self.with_cli_hints(cli).to_cli()
         };
         (!compatible(cli)).then(|| {
@@ -387,6 +398,7 @@ impl LinkerFlavor {
             | LinkerFlavor::Unix(..)
             | LinkerFlavor::EmCc
             | LinkerFlavor::Bpf
+            | LinkerFlavor::Llbc
             | LinkerFlavor::Ptx => LldFlavor::Ld,
             LinkerFlavor::Darwin(..) => LldFlavor::Ld64,
             LinkerFlavor::WasmLld(..) => LldFlavor::Wasm,
@@ -412,6 +424,7 @@ impl LinkerFlavor {
             | LinkerFlavor::Msvc(_)
             | LinkerFlavor::Unix(_)
             | LinkerFlavor::Bpf
+            | LinkerFlavor::Llbc
             | LinkerFlavor::Ptx => false,
         }
     }
@@ -431,6 +444,7 @@ impl LinkerFlavor {
             | LinkerFlavor::Msvc(_)
             | LinkerFlavor::Unix(_)
             | LinkerFlavor::Bpf
+            | LinkerFlavor::Llbc
             | LinkerFlavor::Ptx => false,
         }
     }
@@ -480,6 +494,7 @@ linker_flavor_cli_impls! {
     (LinkerFlavorCli::Msvc(Lld::No)) "msvc"
     (LinkerFlavorCli::EmCc) "em-cc"
     (LinkerFlavorCli::Bpf) "bpf"
+    (LinkerFlavorCli::Llbc) "llbc"
     (LinkerFlavorCli::Ptx) "ptx"
 
     // Legacy stable flavors
@@ -1743,11 +1758,9 @@ impl TargetWarnings {
 pub struct Target {
     /// Target triple to pass to LLVM.
     pub llvm_target: StaticCow<str>,
-    /// A short description of the target including platform requirements,
-    /// for example "64-bit Linux (kernel 3.2+, glibc 2.17+)".
-    /// Optional for now, intended to be required in the future.
-    /// Part of #120745.
-    pub description: Option<StaticCow<str>>,
+    /// Metadata about a target, for example the description or tier.
+    /// Used for generating target documentation.
+    pub metadata: TargetMetadata,
     /// Number of bits in a pointer. Influences the `target_pointer_width` `cfg` variable.
     pub pointer_width: u32,
     /// Architecture to use for ABI considerations. Valid options include: "x86",
@@ -1759,6 +1772,23 @@ pub struct Target {
     pub options: TargetOptions,
 }
 
+/// Metadata about a target like the description or tier.
+/// Part of #120745.
+/// All fields are optional for now, but intended to be required in the future.
+#[derive(Default, PartialEq, Clone, Debug)]
+pub struct TargetMetadata {
+    /// A short description of the target including platform requirements,
+    /// for example "64-bit Linux (kernel 3.2+, glibc 2.17+)".
+    pub description: Option<StaticCow<str>>,
+    /// The tier of the target. 1, 2 or 3.
+    pub tier: Option<u64>,
+    /// Whether the Rust project ships host tools for a target.
+    pub host_tools: Option<bool>,
+    /// Whether a target has the `std` library. This is usually true for targets running
+    /// on an operating system.
+    pub std: Option<bool>,
+}
+
 impl Target {
     pub fn parse_data_layout(&self) -> Result<TargetDataLayout, TargetDataLayoutErrors<'_>> {
         let mut dl = TargetDataLayout::parse_from_llvm_datalayout_string(&self.data_layout)?;
@@ -2055,6 +2085,14 @@ pub struct TargetOptions {
     /// Default number of codegen units to use in debug mode
     pub default_codegen_units: Option<u64>,
 
+    /// Default codegen backend used for this target. Defaults to `None`.
+    ///
+    /// If `None`, then `CFG_DEFAULT_CODEGEN_BACKEND` environmental variable captured when
+    /// compiling `rustc` will be used instead (or llvm if it is not set).
+    ///
+    /// N.B. when *using* the compiler, backend can always be overriden with `-Zcodegen-backend`.
+    pub default_codegen_backend: Option<StaticCow<str>>,
+
     /// Whether to generate trap instructions in places where optimization would
     /// otherwise produce control flow that falls through into unrelated memory.
     pub trap_unreachable: bool,
@@ -2205,6 +2243,7 @@ fn add_link_args_iter(
         | LinkerFlavor::Unix(..)
         | LinkerFlavor::EmCc
         | LinkerFlavor::Bpf
+        | LinkerFlavor::Llbc
         | LinkerFlavor::Ptx => {}
     }
 }
@@ -2361,6 +2400,7 @@ impl Default for TargetOptions {
             stack_probes: StackProbeType::None,
             min_global_align: None,
             default_codegen_units: None,
+            default_codegen_backend: None,
             trap_unreachable: true,
             requires_lto: false,
             singlethread: false,
@@ -2549,7 +2589,7 @@ impl Target {
 
         let mut base = Target {
             llvm_target: get_req_field("llvm-target")?.into(),
-            description: get_req_field("description").ok().map(Into::into),
+            metadata: Default::default(),
             pointer_width: get_req_field("target-pointer-width")?
                 .parse::<u32>()
                 .map_err(|_| "target-pointer-width must be an integer".to_string())?,
@@ -2558,6 +2598,22 @@ impl Target {
             options: Default::default(),
         };
 
+        // FIXME: This doesn't properly validate anything and just ignores the data if it's invalid.
+        // That's okay for now, the only use of this is when generating docs, which we don't do for
+        // custom targets.
+        if let Some(Json::Object(mut metadata)) = obj.remove("metadata") {
+            base.metadata.description = metadata
+                .remove("description")
+                .and_then(|desc| desc.as_str().map(|desc| desc.to_owned().into()));
+            base.metadata.tier = metadata
+                .remove("tier")
+                .and_then(|tier| tier.as_u64())
+                .filter(|tier| (1..=3).contains(tier));
+            base.metadata.host_tools =
+                metadata.remove("host_tools").and_then(|host| host.as_bool());
+            base.metadata.std = metadata.remove("std").and_then(|host| host.as_bool());
+        }
+
         let mut incorrect_type = vec![];
 
         macro_rules! key {
@@ -3253,7 +3309,7 @@ impl ToJson for Target {
         }
 
         target_val!(llvm_target);
-        target_val!(description);
+        target_val!(metadata);
         d.insert("target-pointer-width".to_string(), self.pointer_width.to_string().to_json());
         target_val!(arch);
         target_val!(data_layout);
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
index 05912d93689..eff1617a4bf 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
@@ -15,7 +15,12 @@ pub fn target() -> Target {
         // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
         // correctly, we do too.
         llvm_target: macos_llvm_target(arch).into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
         arch: arch.target_arch(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
index 6591d85384d..e9dddc7fae7 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
@@ -12,7 +12,12 @@ pub fn target() -> Target {
         // This is required for the target to pick the right
         // MACH-O commands, so we do too.
         llvm_target: ios_llvm_target(arch).into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
         arch: arch.target_arch(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
index 2b3967a76ca..2d89b6083f7 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
@@ -8,7 +8,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: mac_catalyst_llvm_target(arch).into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
         arch: arch.target_arch(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
index c5c6b71023b..fb4ae023250 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
@@ -12,7 +12,12 @@ pub fn target() -> Target {
         // This is required for the simulator target to pick the right
         // MACH-O commands, so we do too.
         llvm_target: ios_sim_llvm_target(arch).into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
         arch: arch.target_arch(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
index 1a292a524f6..0deadbdb028 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
@@ -5,7 +5,12 @@ pub fn target() -> Target {
     let arch = Arch::Arm64;
     Target {
         llvm_target: tvos_llvm_target(arch).into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
         arch: arch.target_arch(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
index 0203b7cba93..f666c592524 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
@@ -5,7 +5,12 @@ pub fn target() -> Target {
     let arch = Arch::Arm64_sim;
     Target {
         llvm_target: tvos_sim_llvm_target(arch).into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
         arch: arch.target_arch(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
index 727a28b8566..5001444e1fa 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
@@ -5,7 +5,12 @@ pub fn target() -> Target {
     let base = opts("watchos", Arch::Arm64);
     Target {
         llvm_target: "aarch64-apple-watchos".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
index 504035f8b0d..5728f55baba 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
@@ -9,7 +9,12 @@ pub fn target() -> Target {
         // This is required for the simulator target to pick the right
         // MACH-O commands, so we do too.
         llvm_target: watchos_sim_llvm_target(arch).into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
         arch: arch.target_arch(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs
index da2f7ca4406..716c9b15c59 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu.rs
@@ -4,7 +4,12 @@ use crate::spec::{base, StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64_be-unknown-linux-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs
index 3226722be91..f3b6c4c6180 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_gnu_ilp32.rs
@@ -7,7 +7,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "aarch64_be-unknown-linux-gnu_ilp32".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs
index 180bb3e552a..54108cc1fe0 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_netbsd.rs
@@ -4,7 +4,12 @@ use crate::spec::{base, StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64_be-unknown-netbsd".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs b/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs
index df9dca16571..aa8c4cd0d08 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_kmc_solid_asp3.rs
@@ -4,7 +4,12 @@ pub fn target() -> Target {
     let base = base::solid::opts("asp3");
     Target {
         llvm_target: "aarch64-unknown-none".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs
index 6f760f0e36a..bb9bab4569b 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_linux_android.rs
@@ -6,7 +6,12 @@ use crate::spec::{base, SanitizerSet, StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64-linux-android".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs b/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs
index 221b550a3ac..15743b9e508 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_nintendo_switch_freestanding.rs
@@ -8,7 +8,12 @@ const LINKER_SCRIPT: &str = include_str!("./aarch64_nintendo_switch_freestanding
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-none".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs
index 8ef6bea6768..aed7f94bab7 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_gnullvm.rs
@@ -8,7 +8,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "aarch64-pc-windows-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs
index 29c191fc9ab..f253b014c31 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_pc_windows_msvc.rs
@@ -7,7 +7,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "aarch64-pc-windows-msvc".into(),
-        description: Some("ARM64 Windows MSVC".into()),
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs
index b4317508521..9fec76b891c 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_freebsd.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, SanitizerSet, StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-freebsd".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs
index 59ead79721b..21789e436ca 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_fuchsia.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, SanitizerSet, StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-fuchsia".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs
index 1a823400629..9ffea48cba7 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_hermit.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-hermit".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         arch: "aarch64".into(),
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs
index 8344578d894..90130880ace 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_illumos.rs
@@ -11,7 +11,12 @@ pub fn target() -> Target {
         // LLVM does not currently have a separate illumos target,
         // so we still pass Solaris to it
         llvm_target: "aarch64-unknown-solaris2.11".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs
index dd29ef7b530..2169e2971d8 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, SanitizerSet, StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-linux-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs
index d1fe5ed863d..81c6a183669 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_gnu_ilp32.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-linux-gnu_ilp32".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs
index 0a20c47d1ad..77689e26380 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_musl.rs
@@ -14,7 +14,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "aarch64-unknown-linux-musl".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs
index fdb5b8635b2..b6b25598bec 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_linux_ohos.rs
@@ -8,7 +8,12 @@ pub fn target() -> Target {
     Target {
         // LLVM 15 doesn't support OpenHarmony yet, use a linux target instead.
         llvm_target: "aarch64-unknown-linux-musl".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs
index 3aaebe85a0b..de88b3fe795 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_netbsd.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-netbsd".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs
index ca019a9a683..e5a428aade2 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none.rs
@@ -31,7 +31,12 @@ pub fn target() -> Target {
     };
     Target {
         llvm_target: "aarch64-unknown-none".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs
index 8f837865bfa..c75b0d468e8 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_none_softfloat.rs
@@ -25,7 +25,12 @@ pub fn target() -> Target {
     };
     Target {
         llvm_target: "aarch64-unknown-none".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs
index 3fb9fb7fd27..f2f1b477ff8 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_nto_qnx710.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-unknown".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         // from: https://llvm.org/docs/LangRef.html#data-layout
         // e         = little endian
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs
index 003f40c9803..f0d79d3c4b7 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_openbsd.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-openbsd".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs
index c50cb5a300d..b7e9d8cb9fc 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_redox.rs
@@ -8,7 +8,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "aarch64-unknown-redox".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs
index 1cb59879e47..cb48b7417b0 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_teeos.rs
@@ -8,7 +8,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "aarch64-unknown-none".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs
index bf14f6950eb..e8d8770546c 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_uefi.rs
@@ -12,7 +12,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "aarch64-unknown-windows".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs
index 8399e091c39..7a89237d0ff 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_uwp_windows_msvc.rs
@@ -7,7 +7,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "aarch64-pc-windows-msvc".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs
index a26d41f81f0..ab23ff6ad9b 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_wrs_vxworks.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "aarch64-unknown-linux-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
index 318764abab2..9bf09b4376d 100644
--- a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
@@ -5,7 +5,12 @@ pub fn target() -> Target {
     let base = opts("watchos", Arch::Arm64_32);
     Target {
         llvm_target: "arm64_32-apple-watchos".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:o-p:32:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "aarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
index fd3a52d2f1f..11c56cf411c 100644
--- a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
@@ -15,7 +15,12 @@ pub fn target() -> Target {
         // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
         // correctly, we do too.
         llvm_target: macos_llvm_target(arch).into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
         arch: arch.target_arch(),
diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
index 4d650921d39..fd8f0ddcb4d 100644
--- a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
@@ -12,7 +12,12 @@ pub fn target() -> Target {
         // This is required for the target to pick the right
         // MACH-O commands, so we do too.
         llvm_target: ios_llvm_target(arch).into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:o-i64:64-i128:128-n32:64-S128".into(),
         arch: arch.target_arch(),
diff --git a/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs
index f1af4d9a80e..bfd3364acac 100644
--- a/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64ec_pc_windows_msvc.rs
@@ -12,7 +12,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "arm64ec-pc-windows-msvc".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:w-p:64:64-i32:32-i64:64-i128:128-n32:64-S128".into(),
         arch: "arm64ec".into(),
diff --git a/compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs b/compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs
index a3563b19b13..12c6388a97b 100644
--- a/compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs
+++ b/compiler/rustc_target/src/spec/targets/arm_linux_androideabi.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, SanitizerSet, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "arm-linux-androideabi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabi.rs
index 1bd29d11cb4..8abf7dd5323 100644
--- a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabi.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "arm-unknown-linux-gnueabi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabihf.rs
index b705d67ad5c..922f51fd60d 100644
--- a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_gnueabihf.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "arm-unknown-linux-gnueabihf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs
index 5f48330f673..3c01c86c7d5 100644
--- a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs
+++ b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabi.rs
@@ -6,7 +6,12 @@ pub fn target() -> Target {
         // to determine the calling convention and float ABI, and it doesn't
         // support the "musleabi" value.
         llvm_target: "arm-unknown-linux-gnueabi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs
index 6b94e673785..5be5bb03979 100644
--- a/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/arm_unknown_linux_musleabihf.rs
@@ -6,7 +6,12 @@ pub fn target() -> Target {
         // uses it to determine the calling convention and float ABI, and it
         // doesn't support the "musleabihf" value.
         llvm_target: "arm-unknown-linux-gnueabihf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs
index 0cd8a7cdcb6..f95ec8c78dd 100644
--- a/compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armeb_unknown_linux_gnueabi.rs
@@ -4,7 +4,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armeb-unknown-linux-gnueabi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armebv7r_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armebv7r_none_eabi.rs
index 6317bef0559..d5ee10dbfc4 100644
--- a/compiler/rustc_target/src/spec/targets/armebv7r_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armebv7r_none_eabi.rs
@@ -6,7 +6,12 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ
 pub fn target() -> Target {
     Target {
         llvm_target: "armebv7r-none-eabi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armebv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armebv7r_none_eabihf.rs
index 13778ccb303..d9ebc7fbc1a 100644
--- a/compiler/rustc_target/src/spec/targets/armebv7r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armebv7r_none_eabihf.rs
@@ -6,7 +6,12 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ
 pub fn target() -> Target {
     Target {
         llvm_target: "armebv7r-none-eabihf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs
index e0f1756cdc2..42d165a6ca4 100644
--- a/compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv4t_none_eabi.rs
@@ -14,7 +14,12 @@ use crate::spec::{cvs, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target,
 pub fn target() -> Target {
     Target {
         llvm_target: "armv4t-none-eabi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         arch: "arm".into(),
         /* Data layout args are '-' separated:
diff --git a/compiler/rustc_target/src/spec/targets/armv4t_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/armv4t_unknown_linux_gnueabi.rs
index 94c9c77c252..d12bc241d06 100644
--- a/compiler/rustc_target/src/spec/targets/armv4t_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv4t_unknown_linux_gnueabi.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armv4t-unknown-linux-gnueabi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs
index 280aa3b84ca..512a175f2c9 100644
--- a/compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv5te_none_eabi.rs
@@ -5,7 +5,12 @@ use crate::spec::{base, cvs, FramePointer, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armv5te-none-eabi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         arch: "arm".into(),
         /* Data layout args are '-' separated:
diff --git a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_gnueabi.rs
index 6a4cc7fb78e..6b31d0ee25f 100644
--- a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_gnueabi.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armv5te-unknown-linux-gnueabi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs
index eb1c67650fc..ea14a2ec252 100644
--- a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_musleabi.rs
@@ -7,7 +7,12 @@ pub fn target() -> Target {
         // uses it to determine the calling convention and float ABI, and LLVM
         // doesn't support the "musleabihf" value.
         llvm_target: "armv5te-unknown-linux-gnueabi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs
index 6d20a9047de..e2ab803576a 100644
--- a/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv5te_unknown_linux_uclibceabi.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armv5te-unknown-linux-uclibcgnueabi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs
index 1aec8e6681c..04f35178828 100644
--- a/compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/armv6_unknown_freebsd.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armv6-unknown-freebsd-gnueabihf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv6_unknown_netbsd_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv6_unknown_netbsd_eabihf.rs
index 86c8ade8b51..ca4d42ebbe8 100644
--- a/compiler/rustc_target/src/spec/targets/armv6_unknown_netbsd_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv6_unknown_netbsd_eabihf.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armv6-unknown-netbsdelf-eabihf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs b/compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs
index 01a08283f82..9a88277b063 100644
--- a/compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs
+++ b/compiler/rustc_target/src/spec/targets/armv6k_nintendo_3ds.rs
@@ -12,7 +12,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "armv6k-none-eabihf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_linux_androideabi.rs b/compiler/rustc_target/src/spec/targets/armv7_linux_androideabi.rs
index bfeca4bbc9e..e798ef47354 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_linux_androideabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_linux_androideabi.rs
@@ -13,7 +13,12 @@ pub fn target() -> Target {
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-march=armv7-a"]);
     Target {
         llvm_target: "armv7-none-linux-android".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs
index 5f068edbaad..0730a423f72 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_sony_vita_newlibeabihf.rs
@@ -13,7 +13,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "thumbv7a-vita-eabihf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs
index 888eac89a98..017b126129c 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_freebsd.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armv7-unknown-freebsd-gnueabihf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabi.rs
index e04c9790164..2be263d6d9c 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabi.rs
@@ -6,7 +6,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armv7-unknown-linux-gnueabi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabihf.rs
index 401cef1f86c..8a80a623b1d 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_gnueabihf.rs
@@ -6,7 +6,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armv7-unknown-linux-gnueabihf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs
index 4792eb930d6..ad4ebed74e7 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabi.rs
@@ -11,7 +11,12 @@ pub fn target() -> Target {
         // to determine the calling convention and float ABI, and it doesn't
         // support the "musleabi" value.
         llvm_target: "armv7-unknown-linux-gnueabi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs
index 948746235a7..ba7b62bc5eb 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_musleabihf.rs
@@ -8,7 +8,12 @@ pub fn target() -> Target {
         // uses it to determine the calling convention and float ABI, and LLVM
         // doesn't support the "musleabihf" value.
         llvm_target: "armv7-unknown-linux-gnueabihf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_ohos.rs
index 62faf4b682a..489aad7845d 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_ohos.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_ohos.rs
@@ -9,7 +9,12 @@ pub fn target() -> Target {
     Target {
         // LLVM 15 doesn't support OpenHarmony yet, use a linux target instead.
         llvm_target: "armv7-unknown-linux-gnueabi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabi.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabi.rs
index b33a6ec19ee..fdf46101d25 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabi.rs
@@ -7,7 +7,12 @@ pub fn target() -> Target {
     let base = base::linux_uclibc::opts();
     Target {
         llvm_target: "armv7-unknown-linux-gnueabi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabihf.rs
index b64e325d760..36bc9548209 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_linux_uclibceabihf.rs
@@ -7,7 +7,12 @@ pub fn target() -> Target {
     let base = base::linux_uclibc::opts();
     Target {
         llvm_target: "armv7-unknown-linux-gnueabihf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_unknown_netbsd_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_unknown_netbsd_eabihf.rs
index 08efed615aa..2dc4d9b835b 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_unknown_netbsd_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_unknown_netbsd_eabihf.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armv7-unknown-netbsdelf-eabihf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7_wrs_vxworks_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7_wrs_vxworks_eabihf.rs
index 48721437c51..89469f01c3a 100644
--- a/compiler/rustc_target/src/spec/targets/armv7_wrs_vxworks_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7_wrs_vxworks_eabihf.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armv7-unknown-linux-gnueabihf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabi.rs b/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabi.rs
index 0c466f5a6c1..ffdeba50df2 100644
--- a/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabi.rs
@@ -4,7 +4,12 @@ pub fn target() -> Target {
     let base = base::solid::opts("asp3");
     Target {
         llvm_target: "armv7a-none-eabi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabihf.rs
index a109423f6d5..cbcf223daf6 100644
--- a/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7a_kmc_solid_asp3_eabihf.rs
@@ -4,7 +4,12 @@ pub fn target() -> Target {
     let base = base::solid::opts("asp3");
     Target {
         llvm_target: "armv7a-none-eabihf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs
index 2680dda0305..3373e677c4a 100644
--- a/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7a_none_eabi.rs
@@ -32,7 +32,12 @@ pub fn target() -> Target {
     };
     Target {
         llvm_target: "armv7a-none-eabi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs
index b26b560a5ee..12844a8e582 100644
--- a/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7a_none_eabihf.rs
@@ -24,7 +24,12 @@ pub fn target() -> Target {
     };
     Target {
         llvm_target: "armv7a-none-eabihf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs
index 030f0ce4594..42ad9e0a35e 100644
--- a/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs
@@ -5,7 +5,12 @@ pub fn target() -> Target {
     let arch = Arch::Armv7k;
     Target {
         llvm_target: "armv7k-apple-watchos".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:o-p:32:32-Fi8-i64:64-a:0:32-n32-S128".into(),
         arch: arch.target_arch(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs b/compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs
index b71de060ca6..d5213234339 100644
--- a/compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7r_none_eabi.rs
@@ -5,7 +5,12 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ
 pub fn target() -> Target {
     Target {
         llvm_target: "armv7r-none-eabi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs
index a03179a770f..a8c622ccce2 100644
--- a/compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7r_none_eabihf.rs
@@ -5,7 +5,12 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ
 pub fn target() -> Target {
     Target {
         llvm_target: "armv7r-none-eabihf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
index c8ce77b58be..40e5fc3f20d 100644
--- a/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
@@ -5,7 +5,12 @@ pub fn target() -> Target {
     let arch = Arch::Armv7s;
     Target {
         llvm_target: ios_llvm_target(arch).into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32".into(),
         arch: arch.target_arch(),
diff --git a/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs
index f88b7e56c67..17fdd496302 100644
--- a/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/armv8r_none_eabihf.rs
@@ -5,7 +5,12 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ
 pub fn target() -> Target {
     Target {
         llvm_target: "armv8r-none-eabihf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs b/compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs
index a6ac0f93c44..470674372fd 100644
--- a/compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/bpfeb_unknown_none.rs
@@ -4,7 +4,12 @@ use crate::{abi::Endian, spec::base};
 pub fn target() -> Target {
     Target {
         llvm_target: "bpfeb".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         data_layout: "E-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         pointer_width: 64,
         arch: "bpf".into(),
diff --git a/compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs b/compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs
index cee4d687daf..3e3202df17e 100644
--- a/compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/bpfel_unknown_none.rs
@@ -4,7 +4,12 @@ use crate::{abi::Endian, spec::base};
 pub fn target() -> Target {
     Target {
         llvm_target: "bpfel".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         pointer_width: 64,
         arch: "bpf".into(),
diff --git a/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2.rs b/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2.rs
index 4f0bd6c9ed4..120c75f528a 100644
--- a/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2.rs
+++ b/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2.rs
@@ -6,7 +6,7 @@ pub fn target() -> Target {
     Target {
         //https://github.com/llvm/llvm-project/blob/8b76aea8d8b1b71f6220bc2845abc749f18a19b7/clang/lib/Basic/Targets/CSKY.h
         llvm_target: "csky-unknown-linux-gnuabiv2".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata { description:None, tier: None, host_tools: None, std: None },
         pointer_width: 32,
         data_layout: "e-m:e-S32-p:32:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:32-v128:32:32-a:0:32-Fi32-n32".into(),
         arch: "csky".into(),
diff --git a/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2hf.rs b/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2hf.rs
index d57c1d0c17f..2856e94ea4a 100644
--- a/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2hf.rs
+++ b/compiler/rustc_target/src/spec/targets/csky_unknown_linux_gnuabiv2hf.rs
@@ -6,7 +6,7 @@ pub fn target() -> Target {
     Target {
         //https://github.com/llvm/llvm-project/blob/8b76aea8d8b1b71f6220bc2845abc749f18a19b7/clang/lib/Basic/Targets/CSKY.h
         llvm_target: "csky-unknown-linux-gnuabiv2".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata { description:None, tier: None, host_tools: None, std: None },
         pointer_width: 32,
         data_layout: "e-m:e-S32-p:32:32-i32:32:32-i64:32:32-f32:32:32-f64:32:32-v64:32:32-v128:32:32-a:0:32-Fi32-n32".into(),
         arch: "csky".into(),
diff --git a/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs
index bae88e8546d..003d35ebeb4 100644
--- a/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/hexagon_unknown_linux_musl.rs
@@ -15,7 +15,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "hexagon-unknown-linux-musl".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: concat!(
             "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32",
diff --git a/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs
index 907ff078257..8750e0ee85f 100644
--- a/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/hexagon_unknown_none_elf.rs
@@ -3,7 +3,12 @@ use crate::spec::{PanicStrategy, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "hexagon-unknown-none-elf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: concat!(
             "e-m:e-p:32:32:32-a:0-n16:32-i64:64:64-i32:32",
diff --git a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
index cdd436ce34a..afa92ba99c6 100644
--- a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
@@ -11,7 +11,12 @@ pub fn target() -> Target {
         // This is required for the target to pick the right
         // MACH-O commands, so we do too.
         llvm_target: ios_sim_llvm_target(arch).into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:128-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs b/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs
index e37cf4e5214..290ed81ad45 100644
--- a/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs
+++ b/compiler/rustc_target/src/spec/targets/i586_pc_nto_qnx700.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOpt
 pub fn target() -> Target {
     Target {
         llvm_target: "i586-pc-unknown".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:32-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs
index f72a4276d76..73949c7bdc4 100644
--- a/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/i586_unknown_netbsd.rs
@@ -8,7 +8,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i586-unknown-netbsdelf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:32-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
index f4561d7ed58..34a447a97ef 100644
--- a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
@@ -16,7 +16,12 @@ pub fn target() -> Target {
         //
         // While ld64 doesn't understand i686, LLVM does.
         llvm_target: macos_llvm_target(Arch::I686).into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:o-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:128-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/i686_linux_android.rs b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs
index d16dfedd38f..585aad10c57 100644
--- a/compiler/rustc_target/src/spec/targets/i686_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_linux_android.rs
@@ -15,7 +15,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-linux-android".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:32-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs
index 1b092045e4b..66e09416dde 100644
--- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnu.rs
@@ -17,7 +17,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-pc-windows-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"
diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs
index 1a69e109fca..7a2d28aec9c 100644
--- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_gnullvm.rs
@@ -16,7 +16,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-pc-windows-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"
diff --git a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs
index 0ba486417ff..eb44520ad9b 100644
--- a/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_pc_windows_msvc.rs
@@ -23,7 +23,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-pc-windows-msvc".into(),
-        description: Some("32-bit MSVC (Windows 7+)".into()),
+        metadata: crate::spec::TargetMetadata {
+            description: Some("32-bit MSVC (Windows 7+)".into()),
+            tier: Some(1),
+            host_tools: Some(true),
+            std: Some(true),
+        },
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32"
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs
index f84886807c3..5826906e9d8 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_freebsd.rs
@@ -9,7 +9,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-unknown-freebsd".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:32-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs
index af74539b4a1..5f66911b39a 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_haiku.rs
@@ -9,7 +9,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-unknown-haiku".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:32-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs
index 096337d0906..a67105f24ca 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_hurd_gnu.rs
@@ -9,7 +9,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-unknown-hurd-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:32-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs
index 709265bde67..1d4916cabfd 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_gnu.rs
@@ -10,7 +10,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-unknown-linux-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:32-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs
index d86d0259cd9..c3b9b71802b 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_linux_musl.rs
@@ -23,7 +23,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-unknown-linux-musl".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:32-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs
index 86d3404c219..87eba1fb856 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_netbsd.rs
@@ -9,7 +9,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-unknown-netbsdelf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:32-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs
index 4e3829f05f5..0436f39f5b1 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_openbsd.rs
@@ -9,7 +9,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-unknown-openbsd".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:32-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs
index 296acf35fdb..8665a7ca61a 100644
--- a/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_unknown_uefi.rs
@@ -78,7 +78,12 @@ pub fn target() -> Target {
     // remove -gnu and use the default one.
     Target {
         llvm_target: "i686-unknown-windows-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"
diff --git a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs
index 12c7c4c5a2d..77dcd645728 100644
--- a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_gnu.rs
@@ -16,7 +16,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-pc-windows-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i64:64-i128:128-f80:32-n8:16:32-a:0:32-S32"
diff --git a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs
index d04ec0012f2..b3830226267 100644
--- a/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_uwp_windows_msvc.rs
@@ -7,7 +7,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-pc-windows-msvc".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32"
diff --git a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs
index 081b4c5364c..b68316f2830 100644
--- a/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_win7_windows_msvc.rs
@@ -23,7 +23,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-pc-windows-msvc".into(),
-        description: Some("32-bit Windows 7 support".into()),
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:x-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i64:64-i128:128-f80:128-n8:16:32-a:0:32-S32"
diff --git a/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs
index d554f717f25..e4d0b674cc4 100644
--- a/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_wrs_vxworks.rs
@@ -9,7 +9,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "i686-unknown-linux-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i128:128-f64:32:64-f80:32-n8:16:32-S128"
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs
index f69412bd509..f15a8798940 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_gnu.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "loongarch64-unknown-linux-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
         arch: "loongarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs
index 9f653174cf0..032a29708d1 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_linux_musl.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "loongarch64-unknown-linux-musl".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
         arch: "loongarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs
index 370c7b39950..b2bfc8e4272 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none.rs
@@ -4,7 +4,12 @@ use crate::spec::{Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "loongarch64-unknown-none".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
         arch: "loongarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs
index 8e50a1c3009..02e44c187ab 100644
--- a/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs
+++ b/compiler/rustc_target/src/spec/targets/loongarch64_unknown_none_softfloat.rs
@@ -4,7 +4,12 @@ use crate::spec::{Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "loongarch64-unknown-none".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n64-S128".into(),
         arch: "loongarch64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/m68k_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/m68k_unknown_linux_gnu.rs
index 9fe6760d9f3..abd07ef9bdc 100644
--- a/compiler/rustc_target/src/spec/targets/m68k_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/m68k_unknown_linux_gnu.rs
@@ -8,7 +8,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "m68k-unknown-linux-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "E-m:e-p:32:16:32-i8:8:8-i16:16:16-i32:16:32-n8:16:32-a:0:16-S16".into(),
         arch: "m68k".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs
index 96472c41da6..b8bdfc943de 100644
--- a/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/mips64_openwrt_linux_musl.rs
@@ -13,7 +13,12 @@ pub fn target() -> Target {
     Target {
         // LLVM doesn't recognize "muslabi64" yet.
         llvm_target: "mips64-unknown-linux-musl".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
         arch: "mips64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs
index 6c767c57ffa..e9de4a5c260 100644
--- a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_gnuabi64.rs
@@ -4,7 +4,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "mips64-unknown-linux-gnuabi64".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
         arch: "mips64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs
index d2b6b4e4898..48443717b19 100644
--- a/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mips64_unknown_linux_muslabi64.rs
@@ -9,7 +9,12 @@ pub fn target() -> Target {
     Target {
         // LLVM doesn't recognize "muslabi64" yet.
         llvm_target: "mips64-unknown-linux-musl".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
         arch: "mips64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs
index ef2458a563a..515473fbabc 100644
--- a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_gnuabi64.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "mips64el-unknown-linux-gnuabi64".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
         arch: "mips64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs
index 2983e957d4d..e6b998746e6 100644
--- a/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mips64el_unknown_linux_muslabi64.rs
@@ -8,7 +8,12 @@ pub fn target() -> Target {
     Target {
         // LLVM doesn't recognize "muslabi64" yet.
         llvm_target: "mips64el-unknown-linux-musl".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
         arch: "mips64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs
index d5a5540b326..3616ea60304 100644
--- a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_gnu.rs
@@ -4,7 +4,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "mips-unknown-linux-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         arch: "mips".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs
index 6a13fb7b6bc..b47bc0d3005 100644
--- a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_musl.rs
@@ -9,7 +9,12 @@ pub fn target() -> Target {
     base.crt_static_default = false;
     Target {
         llvm_target: "mips-unknown-linux-musl".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         arch: "mips".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs
index 1137a65c366..117d74f2d25 100644
--- a/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs
+++ b/compiler/rustc_target/src/spec/targets/mips_unknown_linux_uclibc.rs
@@ -4,7 +4,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "mips-unknown-linux-uclibc".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         arch: "mips".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_sony_psp.rs b/compiler/rustc_target/src/spec/targets/mipsel_sony_psp.rs
index 88a6d08286e..fafe1493538 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_sony_psp.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_sony_psp.rs
@@ -11,7 +11,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "mipsel-sony-psp".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         arch: "mips".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs b/compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs
index 3c97c279f1a..9f37b0edc17 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_sony_psx.rs
@@ -3,7 +3,12 @@ use crate::spec::{cvs, Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target,
 pub fn target() -> Target {
     Target {
         llvm_target: "mipsel-sony-psx".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         arch: "mips".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs
index cceeea43e17..e65480e355b 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_gnu.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "mipsel-unknown-linux-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         arch: "mips".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs
index 3da9b70ba7f..ed98f53a2b2 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_musl.rs
@@ -8,7 +8,12 @@ pub fn target() -> Target {
     base.crt_static_default = false;
     Target {
         llvm_target: "mipsel-unknown-linux-musl".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         arch: "mips".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs
index 14a8900c171..dc6807509cb 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_linux_uclibc.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "mipsel-unknown-linux-uclibc".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         arch: "mips".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs
index f89ac1f08e1..8e5cd30a54f 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_netbsd.rs
@@ -8,7 +8,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "mipsel-unknown-netbsd".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         arch: "mips".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs b/compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs
index 9c6bef4d771..b5948b4d35c 100644
--- a/compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsel_unknown_none.rs
@@ -7,7 +7,12 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, Targ
 pub fn target() -> Target {
     Target {
         llvm_target: "mipsel-unknown-none".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         arch: "mips".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs
index 0bda8634d8a..dbb143b7319 100644
--- a/compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsisa32r6_unknown_linux_gnu.rs
@@ -4,7 +4,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "mipsisa32r6-unknown-linux-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "E-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         arch: "mips32r6".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs
index 10b7b93d4ef..f5fff6bec1c 100644
--- a/compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsisa32r6el_unknown_linux_gnu.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "mipsisa32r6el-unknown-linux-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".into(),
         arch: "mips32r6".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs
index 945c237ef38..ed236cca1bb 100644
--- a/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsisa64r6_unknown_linux_gnuabi64.rs
@@ -4,7 +4,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "mipsisa64r6-unknown-linux-gnuabi64".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "E-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
         arch: "mips64r6".into(),
diff --git a/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs b/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs
index 407431f685c..bbdc5b95ad1 100644
--- a/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs
+++ b/compiler/rustc_target/src/spec/targets/mipsisa64r6el_unknown_linux_gnuabi64.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "mipsisa64r6el-unknown-linux-gnuabi64".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128".into(),
         arch: "mips64r6".into(),
diff --git a/compiler/rustc_target/src/spec/targets/msp430_none_elf.rs b/compiler/rustc_target/src/spec/targets/msp430_none_elf.rs
index 6f6503ea111..2b022a4a558 100644
--- a/compiler/rustc_target/src/spec/targets/msp430_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/msp430_none_elf.rs
@@ -3,7 +3,12 @@ use crate::spec::{cvs, Cc, LinkerFlavor, PanicStrategy, RelocModel, Target, Targ
 pub fn target() -> Target {
     Target {
         llvm_target: "msp430-none-elf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 16,
         data_layout: "e-m:e-p:16:16-i32:16-i64:16-f32:16-f64:16-a:8-n8:16-S16".into(),
         arch: "msp430".into(),
diff --git a/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs b/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs
index 33b79a13359..0b0b31b503b 100644
--- a/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs
+++ b/compiler/rustc_target/src/spec/targets/nvptx64_nvidia_cuda.rs
@@ -1,3 +1,4 @@
+use crate::spec::LinkSelfContainedDefault;
 use crate::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, Target, TargetOptions};
 
 pub fn target() -> Target {
@@ -5,7 +6,12 @@ pub fn target() -> Target {
         arch: "nvptx64".into(),
         data_layout: "e-i64:64-i128:128-v16:16-v32:32-n16:32:64".into(),
         llvm_target: "nvptx64-nvidia-cuda".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
 
         options: TargetOptions {
@@ -47,6 +53,9 @@ pub fn target() -> Target {
             // The LLVM backend does not support stack canaries for this target
             supports_stack_protector: false,
 
+            // Support using `self-contained` linkers like the llvm-bitcode-linker
+            link_self_contained: LinkSelfContainedDefault::True,
+
             ..Default::default()
         },
     }
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs b/compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs
index 6e156115f74..481df71c1a6 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64_ibm_aix.rs
@@ -10,7 +10,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64-ibm-aix".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "E-m:a-Fi64-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
         arch: "powerpc64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs
index 27fbb6e3d81..b1b981823b8 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_freebsd.rs
@@ -10,7 +10,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64-unknown-freebsd".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "E-m:e-Fn32-i64:64-n32:64".into(),
         arch: "powerpc64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs
index 11bbfe4baa2..ac10630d944 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_gnu.rs
@@ -10,7 +10,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64-unknown-linux-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "E-m:e-Fi64-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
         arch: "powerpc64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs
index 5036df13694..663f06cf0c6 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_linux_musl.rs
@@ -10,7 +10,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64-unknown-linux-musl".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "E-m:e-Fn32-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
         arch: "powerpc64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs
index f0813e50e03..5611352c951 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64_unknown_openbsd.rs
@@ -10,7 +10,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64-unknown-openbsd".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "E-m:e-Fn32-i64:64-n32:64".into(),
         arch: "powerpc64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs
index 2365b687f6d..22b45042aa6 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64_wrs_vxworks.rs
@@ -10,7 +10,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64-unknown-linux-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "E-m:e-Fi64-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
         arch: "powerpc64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs
index 83c0a9a7f69..812b5928966 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_freebsd.rs
@@ -9,7 +9,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64le-unknown-freebsd".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-Fn32-i64:64-n32:64".into(),
         arch: "powerpc64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs
index 6041836f8fa..e3c4b3b585c 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_gnu.rs
@@ -9,7 +9,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64le-unknown-linux-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-Fn32-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
         arch: "powerpc64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs
index a27a184aa88..497a40ade81 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc64le_unknown_linux_musl.rs
@@ -9,7 +9,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc64le-unknown-linux-musl".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-Fn32-i64:64-n32:64-S128-v256:256:256-v512:512:512".into(),
         arch: "powerpc64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_freebsd.rs
index 31220adc0db..194bb0566f1 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_freebsd.rs
@@ -13,7 +13,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc-unknown-freebsd13.0".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fn32-i64:64-n32".into(),
         arch: "powerpc".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs
index 780824bed2a..b88b2fbf809 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnu.rs
@@ -9,7 +9,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc-unknown-linux-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fn32-i64:64-n32".into(),
         arch: "powerpc".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs
index 302b06b3e93..b09c4cd21e0 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_gnuspe.rs
@@ -9,7 +9,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc-unknown-linux-gnuspe".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fn32-i64:64-n32".into(),
         arch: "powerpc".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs
index 7f512824980..67b19e90489 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_linux_musl.rs
@@ -9,7 +9,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc-unknown-linux-musl".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fn32-i64:64-n32".into(),
         arch: "powerpc".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_netbsd.rs
index 41ea47fbb63..c592cd3f6fd 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_netbsd.rs
@@ -9,7 +9,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc-unknown-netbsd".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fn32-i64:64-n32".into(),
         arch: "powerpc".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/powerpc_unknown_openbsd.rs
index b57c980096a..a17f437e064 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_unknown_openbsd.rs
@@ -9,7 +9,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc-unknown-openbsd".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fn32-i64:64-n32".into(),
         arch: "powerpc".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks.rs
index 7226d618465..91925ce151d 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks.rs
@@ -9,7 +9,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc-unknown-linux-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fn32-i64:64-n32".into(),
         arch: "powerpc".into(),
diff --git a/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs
index 847ff3799b0..7640feb28e3 100644
--- a/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs
+++ b/compiler/rustc_target/src/spec/targets/powerpc_wrs_vxworks_spe.rs
@@ -9,7 +9,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "powerpc-unknown-linux-gnuspe".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-Fn32-i64:64-n32".into(),
         arch: "powerpc".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs
index 95d3aa29fac..7e607574241 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_gnu.rs
@@ -5,7 +5,12 @@ use crate::spec::{base, CodeModel, SplitDebuginfo, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "riscv32-unknown-linux-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         arch: "riscv32".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs
index 1c81da11de1..a46b1bb6588 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32gc_unknown_linux_musl.rs
@@ -5,7 +5,12 @@ use crate::spec::{base, CodeModel, SplitDebuginfo, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "riscv32-unknown-linux-musl".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         arch: "riscv32".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv32i_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32i_unknown_none_elf.rs
index ad85186d216..87eebbe8708 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32i_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32i_unknown_none_elf.rs
@@ -4,7 +4,12 @@ pub fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         arch: "riscv32".into(),
 
diff --git a/compiler/rustc_target/src/spec/targets/riscv32im_risc0_zkvm_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32im_risc0_zkvm_elf.rs
index 43958df7ceb..186f8105df5 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32im_risc0_zkvm_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32im_risc0_zkvm_elf.rs
@@ -5,7 +5,12 @@ pub fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         arch: "riscv32".into(),
 
diff --git a/compiler/rustc_target/src/spec/targets/riscv32im_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32im_unknown_none_elf.rs
index 60433837cf1..962fcd0eb99 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32im_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32im_unknown_none_elf.rs
@@ -4,7 +4,12 @@ pub fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         arch: "riscv32".into(),
 
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imac_esp_espidf.rs b/compiler/rustc_target/src/spec/targets/riscv32imac_esp_espidf.rs
index 6741d5224c9..1e1356910d9 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imac_esp_espidf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imac_esp_espidf.rs
@@ -4,7 +4,12 @@ pub fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         arch: "riscv32".into(),
 
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_none_elf.rs
index 4b49df632a1..705bc17892a 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_none_elf.rs
@@ -4,7 +4,12 @@ pub fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         arch: "riscv32".into(),
 
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs
index a295e060909..80b6e6077b2 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imac_unknown_xous_elf.rs
@@ -4,7 +4,12 @@ pub fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         arch: "riscv32".into(),
 
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imafc_esp_espidf.rs b/compiler/rustc_target/src/spec/targets/riscv32imafc_esp_espidf.rs
index 15aa60f95a2..6c660793777 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imafc_esp_espidf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imafc_esp_espidf.rs
@@ -4,7 +4,12 @@ pub fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         arch: "riscv32".into(),
 
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_none_elf.rs
index 896ad1c04f8..f4a0cd1c51e 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imafc_unknown_none_elf.rs
@@ -4,7 +4,12 @@ pub fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         arch: "riscv32".into(),
 
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imc_esp_espidf.rs b/compiler/rustc_target/src/spec/targets/riscv32imc_esp_espidf.rs
index 1707e067a48..cee6fd32dd6 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imc_esp_espidf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imc_esp_espidf.rs
@@ -4,7 +4,12 @@ pub fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         arch: "riscv32".into(),
 
diff --git a/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_none_elf.rs
index e23273f8c9f..5378c132df1 100644
--- a/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv32imc_unknown_none_elf.rs
@@ -4,7 +4,12 @@ pub fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:32:32-i64:64-n32-S128".into(),
         llvm_target: "riscv32".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         arch: "riscv32".into(),
 
diff --git a/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs b/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs
index 879deff2563..27629199ea5 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64_linux_android.rs
@@ -5,7 +5,12 @@ use crate::spec::{base, CodeModel, SanitizerSet, SplitDebuginfo, Target, TargetO
 pub fn target() -> Target {
     Target {
         llvm_target: "riscv64-linux-android".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         arch: "riscv64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs
index ed0290d63a7..37c360e6761 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_freebsd.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, CodeModel, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "riscv64-unknown-freebsd".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         arch: "riscv64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs
index 97873e93f68..a600ee76566 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_fuchsia.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, CodeModel, SanitizerSet, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "riscv64-unknown-fuchsia".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         arch: "riscv64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs
index 40b3f196198..63c06a97223 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_hermit.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, CodeModel, RelocModel, Target, TargetOptions, TlsModel};
 pub fn target() -> Target {
     Target {
         llvm_target: "riscv64-unknown-hermit".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         arch: "riscv64".into(),
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs
index fc7c8024ffb..199ffc1c139 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_gnu.rs
@@ -5,7 +5,12 @@ use crate::spec::{base, CodeModel, SplitDebuginfo, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "riscv64-unknown-linux-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         arch: "riscv64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs
index aa32149986f..f8b5ceee8b4 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_linux_musl.rs
@@ -5,7 +5,12 @@ use crate::spec::{base, CodeModel, SplitDebuginfo, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "riscv64-unknown-linux-musl".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         arch: "riscv64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs
index 42d58535735..9dbe01f4598 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_netbsd.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, CodeModel, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "riscv64-unknown-netbsd".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         arch: "riscv64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs
index 89b0793375d..9f128d07a99 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_none_elf.rs
@@ -5,7 +5,12 @@ use crate::spec::{RelocModel, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         llvm_target: "riscv64".into(),
         pointer_width: 64,
         arch: "riscv64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs
index 8f42bb5c1d2..29919a16078 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64gc_unknown_openbsd.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, CodeModel, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "riscv64-unknown-openbsd".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         arch: "riscv64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs
index 78bfbe68565..1ab6aebcea9 100644
--- a/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/riscv64imac_unknown_none_elf.rs
@@ -5,7 +5,12 @@ pub fn target() -> Target {
     Target {
         data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
         llvm_target: "riscv64".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         arch: "riscv64".into(),
 
diff --git a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs
index a982e145a8e..be68c5b1c88 100644
--- a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs
@@ -18,7 +18,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "s390x-unknown-linux-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64".into(),
         arch: "s390x".into(),
diff --git a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs
index 015abf2521b..619e83ce620 100644
--- a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs
@@ -19,7 +19,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "s390x-unknown-linux-musl".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-v128:64-a:8:16-n32:64".into(),
         arch: "s390x".into(),
diff --git a/compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs
index 9df3c2167d7..77c9b4f996a 100644
--- a/compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/sparc64_unknown_linux_gnu.rs
@@ -9,7 +9,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "sparc64-unknown-linux-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "E-m:e-i64:64-n32:64-S128".into(),
         arch: "sparc64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs
index 305783883e2..42944367cf6 100644
--- a/compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/sparc64_unknown_netbsd.rs
@@ -9,7 +9,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "sparc64-unknown-netbsd".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "E-m:e-i64:64-n32:64-S128".into(),
         arch: "sparc64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs
index 2878d27f5d4..f0bf55d33e6 100644
--- a/compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/sparc64_unknown_openbsd.rs
@@ -10,7 +10,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "sparc64-unknown-openbsd".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "E-m:e-i64:64-n32:64-S128".into(),
         arch: "sparc64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs
index a2760ae93f2..c10f9d82d46 100644
--- a/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/sparc_unknown_linux_gnu.rs
@@ -10,7 +10,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "sparc-unknown-linux-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "E-m:e-p:32:32-i64:64-f128:64-n32-S64".into(),
         arch: "sparc".into(),
diff --git a/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs
index c32e637a4a4..cfe8f65d794 100644
--- a/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs
+++ b/compiler/rustc_target/src/spec/targets/sparc_unknown_none_elf.rs
@@ -20,7 +20,12 @@ pub fn target() -> Target {
     Target {
         data_layout: "E-m:e-p:32:32-i64:64-f128:64-n32-S64".into(),
         llvm_target: "sparc-unknown-none-elf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         arch: "sparc".into(),
         options,
diff --git a/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs b/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs
index 2b6d2a4e49a..a42243f59dc 100644
--- a/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs
+++ b/compiler/rustc_target/src/spec/targets/sparcv9_sun_solaris.rs
@@ -12,7 +12,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "sparcv9-sun-solaris".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "E-m:e-i64:64-n32:64-S128".into(),
         // Use "sparc64" instead of "sparcv9" here, since the former is already
diff --git a/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs
index 321b46d1d73..9f222522505 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv4t_none_eabi.rs
@@ -15,7 +15,12 @@ use crate::spec::{cvs, FramePointer};
 pub fn target() -> Target {
     Target {
         llvm_target: "thumbv4t-none-eabi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         arch: "arm".into(),
         /* Data layout args are '-' separated:
diff --git a/compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs
index d9901c647ab..67e57c5fc35 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv5te_none_eabi.rs
@@ -5,7 +5,12 @@ use crate::spec::{base, cvs, FramePointer, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "thumbv5te-none-eabi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         arch: "arm".into(),
         /* Data layout args are '-' separated:
diff --git a/compiler/rustc_target/src/spec/targets/thumbv6m_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv6m_none_eabi.rs
index c9878f172ae..cac415128b6 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv6m_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv6m_none_eabi.rs
@@ -5,7 +5,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "thumbv6m-none-eabi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs
index bb2555bb1a5..13e1e349b04 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7a_pc_windows_msvc.rs
@@ -13,7 +13,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "thumbv7a-pc-windows-msvc".into(),
-        description: Some("ARM32 Windows MSVC".into()),
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7a_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_uwp_windows_msvc.rs
index ce07626be3b..e3e2ea63594 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7a_uwp_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7a_uwp_windows_msvc.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, PanicStrategy, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "thumbv7a-pc-windows-msvc".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:w-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabi.rs
index f09ba2461a3..ec73cf40a71 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabi.rs
@@ -14,7 +14,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "thumbv7em-none-eabi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabihf.rs
index 5aebfea45f0..8c6bc6d7267 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7em_none_eabihf.rs
@@ -13,7 +13,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "thumbv7em-none-eabihf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7m_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7m_none_eabi.rs
index 4e91765654c..0104cdcc9a2 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7m_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7m_none_eabi.rs
@@ -5,7 +5,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "thumbv7m-none-eabi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7neon_linux_androideabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7neon_linux_androideabi.rs
index 8638f36a0fc..d50e63b9217 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7neon_linux_androideabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7neon_linux_androideabi.rs
@@ -13,7 +13,12 @@ pub fn target() -> Target {
     base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-march=armv7-a"]);
     Target {
         llvm_target: "armv7-none-linux-android".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_gnueabihf.rs
index 20e1967c449..d630ca214e5 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_gnueabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_gnueabihf.rs
@@ -9,7 +9,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "armv7-unknown-linux-gnueabihf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs
index 6be7c9f6a64..74d5450c787 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv7neon_unknown_linux_musleabihf.rs
@@ -12,7 +12,12 @@ pub fn target() -> Target {
         // uses it to determine the calling convention and float ABI, and LLVM
         // doesn't support the "musleabihf" value.
         llvm_target: "armv7-unknown-linux-gnueabihf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_base_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_base_none_eabi.rs
index 3a3cccd65a6..2f385208f36 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv8m_base_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv8m_base_none_eabi.rs
@@ -5,7 +5,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "thumbv8m.base-none-eabi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabi.rs
index 21c74af74d5..29a0803ba07 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabi.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabi.rs
@@ -6,7 +6,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "thumbv8m.main-none-eabi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabihf.rs
index 1baab520fd4..2fef08261e1 100644
--- a/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabihf.rs
+++ b/compiler/rustc_target/src/spec/targets/thumbv8m_main_none_eabihf.rs
@@ -6,7 +6,12 @@ use crate::spec::{base, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "thumbv8m.main-none-eabihf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64".into(),
         arch: "arm".into(),
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs
index b6d5dae4f64..195ff46cf9d 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs
@@ -24,7 +24,12 @@ pub fn target() -> Target {
     };
     Target {
         llvm_target: "wasm32-unknown-emscripten".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-f128:64-n32:64-S128-ni:1:10:20".into(),
         arch: "wasm32".into(),
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs b/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs
index 94ded57d2f0..e743a18ce80 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_unknown_unknown.rs
@@ -47,7 +47,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "wasm32-unknown-unknown".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
         arch: "wasm32".into(),
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs
index c04df5e6448..26bdb1cbebe 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_wasi_preview1_threads.rs
@@ -125,7 +125,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "wasm32-wasi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
         arch: "wasm32".into(),
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs
index 85c99c77e23..7cbe9f09e6c 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip1.rs
@@ -49,7 +49,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "wasm32-wasi".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
         arch: "wasm32".into(),
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
index cd1b1c33ae4..5ff3f07daae 100644
--- a/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm32_wasip2.rs
@@ -56,7 +56,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "wasm32-unknown-unknown".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
         arch: "wasm32".into(),
diff --git a/compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs b/compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs
index 866e80782e2..8edde36dac6 100644
--- a/compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs
+++ b/compiler/rustc_target/src/spec/targets/wasm64_unknown_unknown.rs
@@ -39,7 +39,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "wasm64-unknown-unknown".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout: "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-n32:64-S128-ni:1:10:20".into(),
         arch: "wasm64".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
index 78907a12550..1716c590aa5 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
@@ -16,7 +16,12 @@ pub fn target() -> Target {
         // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
         // correctly, we do too.
         llvm_target: macos_llvm_target(arch).into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
index e40c7cf8ac1..fa22c2907d2 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
@@ -10,7 +10,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: ios_sim_llvm_target(arch).into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
index af375c58979..9b479de8165 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
@@ -8,7 +8,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: mac_catalyst_llvm_target(arch).into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
index fe603d667b2..f62d31c5166 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
@@ -7,7 +7,12 @@ pub fn target() -> Target {
     let arch = Arch::X86_64_sim;
     Target {
         llvm_target: tvos_sim_llvm_target(arch).into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
index 8032764f93d..371aab8b508 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
@@ -5,7 +5,12 @@ pub fn target() -> Target {
     let arch = Arch::X86_64_sim;
     Target {
         llvm_target: watchos_sim_llvm_target(arch).into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs b/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs
index be40a7995bd..012450e307e 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_fortanix_unknown_sgx.rs
@@ -74,7 +74,12 @@ pub fn target() -> Target {
     };
     Target {
         llvm_target: "x86_64-elf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs b/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs
index eb30838693e..92711bbe246 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_linux_android.rs
@@ -15,7 +15,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-linux-android".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs
index 2253506df20..c7169c3d62d 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_nto_qnx710.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-pc-unknown".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs
index df2fe6c2ace..4dbe049a4b7 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_solaris.rs
@@ -12,7 +12,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-pc-solaris".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs
index ca65d3acb0f..de0f17246c3 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnu.rs
@@ -16,7 +16,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-pc-windows-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs
index 57519ccf0c1..b485970bb41 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_gnullvm.rs
@@ -11,7 +11,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-pc-windows-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs
index c066c453feb..da4dc9bf949 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_pc_windows_msvc.rs
@@ -10,7 +10,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-pc-windows-msvc".into(),
-        description: Some("64-bit MSVC (Windows 7+)".into()),
+        metadata: crate::spec::TargetMetadata {
+            description: Some("64-bit MSVC (Windows 7+)".into()),
+            tier: Some(1),
+            host_tools: Some(true),
+            std: Some(true),
+        },
         pointer_width: 64,
         data_layout:
             "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs b/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs
index bb4744f2c57..8752ba81066 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unikraft_linux_musl.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOpt
 pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-unknown-linux-musl".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         arch: "x86_64".into(),
         data_layout:
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs
index d5b148a8e74..aef95e373cb 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_dragonfly.rs
@@ -10,7 +10,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-dragonfly".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs
index a99b908454b..15146a5ef72 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_freebsd.rs
@@ -13,7 +13,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-freebsd".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs
index 8ced5051418..80cdeab0a67 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_fuchsia.rs
@@ -11,7 +11,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-fuchsia".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs
index dc7c56d866e..9f62eb1fa27 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_haiku.rs
@@ -12,7 +12,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-haiku".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs
index 37ee1f7af1d..745a658ed00 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hermit.rs
@@ -3,7 +3,12 @@ use crate::spec::{base, StackProbeType, Target, TargetOptions};
 pub fn target() -> Target {
     Target {
         llvm_target: "x86_64-unknown-hermit".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         arch: "x86_64".into(),
         data_layout:
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs
index 664312e0713..c52cdf466ab 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_illumos.rs
@@ -12,7 +12,12 @@ pub fn target() -> Target {
         // LLVM does not currently have a separate illumos target,
         // so we still pass Solaris to it
         llvm_target: "x86_64-pc-solaris".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs
index c4b0b18ab23..6b170c22c9e 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_l4re_uclibc.rs
@@ -9,7 +9,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-l4re-uclibc".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs
index 644c324050d..98374023dc5 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnu.rs
@@ -19,7 +19,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-linux-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs
index 4de9e9d3158..f6e0b051e8f 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_gnux32.rs
@@ -14,7 +14,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-linux-gnux32".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 32,
         data_layout: "e-m:e-p:32:32-p270:32:32-p271:32:32-p272:64:64-\
             i64:64-i128:128-f80:128-n8:16:32:64-S128"
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs
index 4cb50e837f6..66237f07102 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_musl.rs
@@ -17,7 +17,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-linux-musl".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs
index fed9cbcffd0..db8db1d2538 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_linux_ohos.rs
@@ -17,7 +17,12 @@ pub fn target() -> Target {
     Target {
         // LLVM 15 doesn't support OpenHarmony yet, use a linux target instead.
         llvm_target: "x86_64-unknown-linux-musl".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs
index 175543b02a6..38ae3a4fe42 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_netbsd.rs
@@ -18,7 +18,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-netbsd".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs
index 0bb5ea1594c..5846dc16d66 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_none.rs
@@ -29,7 +29,12 @@ pub fn target() -> Target {
     };
     Target {
         llvm_target: "x86_64-unknown-none-elf".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs
index d0d16b8c8ee..4d7eba24213 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_openbsd.rs
@@ -11,7 +11,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-openbsd".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs
index b1feb8c2b37..99f5d9dc41d 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_redox.rs
@@ -10,7 +10,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-redox".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs
index 9bdadd73bc0..0c6e4b2b1ff 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_uefi.rs
@@ -31,7 +31,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-windows".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs
index 7d3884e521d..aef6fd1a781 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_gnu.rs
@@ -15,7 +15,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-pc-windows-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs
index a685530332a..963ccdbfcd0 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_uwp_windows_msvc.rs
@@ -9,7 +9,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-pc-windows-msvc".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs
index 813802e2320..9b458614f2b 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_win7_windows_msvc.rs
@@ -9,7 +9,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-win7-windows-msvc".into(),
-        description: Some("64-bit Windows 7 support".into()),
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:w-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs b/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs
index e293d0eb3ce..b956d228c17 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_wrs_vxworks.rs
@@ -11,7 +11,12 @@ pub fn target() -> Target {
 
     Target {
         llvm_target: "x86_64-unknown-linux-gnu".into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
index 9aaaa894a93..b17e21e5d12 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
@@ -34,7 +34,12 @@ pub fn target() -> Target {
         // MACOSX_DEPLOYMENT_TARGET. To enable cross-language LTO to work
         // correctly, we do too.
         llvm_target: macos_llvm_target(arch).into(),
-        description: None,
+        metadata: crate::spec::TargetMetadata {
+            description: None,
+            tier: None,
+            host_tools: None,
+            std: None,
+        },
         pointer_width: 64,
         data_layout:
             "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
diff --git a/compiler/rustc_target/src/spec/tests/tests_impl.rs b/compiler/rustc_target/src/spec/tests/tests_impl.rs
index 3fefd60f7cd..3be18ef3127 100644
--- a/compiler/rustc_target/src/spec/tests/tests_impl.rs
+++ b/compiler/rustc_target/src/spec/tests/tests_impl.rs
@@ -56,7 +56,10 @@ impl Target {
                     LinkerFlavor::Msvc(..) => {
                         assert_matches!(flavor, LinkerFlavor::Msvc(..))
                     }
-                    LinkerFlavor::EmCc | LinkerFlavor::Bpf | LinkerFlavor::Ptx => {
+                    LinkerFlavor::EmCc
+                    | LinkerFlavor::Bpf
+                    | LinkerFlavor::Ptx
+                    | LinkerFlavor::Llbc => {
                         assert_eq!(flavor, self.linker_flavor)
                     }
                 }
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index e37640d0689..b126062102e 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -1,7 +1,7 @@
 use crate::fluent_generated as fluent;
 use rustc_errors::{
-    codes::*, AddToDiagnostic, Applicability, Diag, DiagCtxt, EmissionGuarantee, IntoDiagnostic,
-    Level, SubdiagMessageOp,
+    codes::*, Applicability, Diag, DiagCtxt, Diagnostic, EmissionGuarantee, Level,
+    SubdiagMessageOp, Subdiagnostic,
 };
 use rustc_macros::Diagnostic;
 use rustc_middle::ty::{self, ClosureKind, PolyTraitRef, Ty};
@@ -57,9 +57,9 @@ pub struct NegativePositiveConflict<'tcx> {
     pub positive_impl_span: Result<Span, Symbol>,
 }
 
-impl<G: EmissionGuarantee> IntoDiagnostic<'_, G> for NegativePositiveConflict<'_> {
+impl<G: EmissionGuarantee> Diagnostic<'_, G> for NegativePositiveConflict<'_> {
     #[track_caller]
-    fn into_diagnostic(self, dcx: &DiagCtxt, level: Level) -> Diag<'_, G> {
+    fn into_diag(self, dcx: &DiagCtxt, level: Level) -> Diag<'_, G> {
         let mut diag = Diag::new(dcx, level, fluent::trait_selection_negative_positive_conflict);
         diag.arg("trait_desc", self.trait_desc.print_only_trait_path().to_string());
         diag.arg("self_desc", self.self_ty.map_or_else(|| "none".to_string(), |ty| ty.to_string()));
@@ -100,8 +100,8 @@ pub enum AdjustSignatureBorrow {
     RemoveBorrow { remove_borrow: Vec<(Span, String)> },
 }
 
-impl AddToDiagnostic for AdjustSignatureBorrow {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for AdjustSignatureBorrow {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: F,
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
index 22f52c27362..3b858cb449f 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/mod.rs
@@ -16,7 +16,7 @@ use rustc_middle::traits::solve::{
     CanonicalInput, CanonicalResponse, Certainty, IsNormalizesToHack, PredefinedOpaques,
     PredefinedOpaquesData, QueryResult,
 };
-use rustc_middle::traits::{specialization_graph, DefiningAnchor};
+use rustc_middle::traits::specialization_graph;
 use rustc_middle::ty::{
     self, InferCtxtLike, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable,
     TypeVisitable, TypeVisitableExt, TypeVisitor,
@@ -258,10 +258,7 @@ impl<'a, 'tcx> EvalCtxt<'a, 'tcx> {
         // instead of taking them. This would cause an ICE here, since we have
         // assertions against dropping an `InferCtxt` without taking opaques.
         // FIXME: Once we remove support for the old impl we can remove this.
-        if input.anchor != DefiningAnchor::Error {
-            // This seems ok, but fragile.
-            let _ = infcx.take_opaque_types();
-        }
+        let _ = infcx.take_opaque_types();
 
         result
     }
diff --git a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
index ed839d14dc7..a45c1c34410 100644
--- a/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_trait_selection/src/solve/normalizes_to/mod.rs
@@ -542,13 +542,14 @@ impl<'tcx> assembly::GoalKind<'tcx> for NormalizesTo<'tcx> {
                 | ty::Coroutine(..)
                 | ty::CoroutineWitness(..)
                 | ty::Never
-                | ty::Foreign(..) => tcx.types.unit,
+                | ty::Foreign(..)
+                | ty::Dynamic(_, _, ty::DynStar) => tcx.types.unit,
 
                 ty::Error(e) => Ty::new_error(tcx, *e),
 
                 ty::Str | ty::Slice(_) => tcx.types.usize,
 
-                ty::Dynamic(_, _, _) => {
+                ty::Dynamic(_, _, ty::Dyn) => {
                     let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, None);
                     tcx.type_of(dyn_metadata)
                         .instantiate(tcx, &[ty::GenericArg::from(goal.predicate.self_ty())])
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
index 71fcc47dba3..ad5b7debad7 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs
@@ -32,7 +32,7 @@ use rustc_hir::{GenericParam, Item, Node};
 use rustc_infer::infer::error_reporting::TypeErrCtxt;
 use rustc_infer::infer::{InferOk, TypeTrace};
 use rustc_middle::traits::select::OverflowError;
-use rustc_middle::traits::{DefiningAnchor, SignatureMismatchData};
+use rustc_middle::traits::SignatureMismatchData;
 use rustc_middle::ty::abstract_const::NotConstEvaluatable;
 use rustc_middle::ty::error::{ExpectedFound, TypeError};
 use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder, TypeSuperFoldable};
@@ -3390,19 +3390,12 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
             obligation.cause.span,
             format!("cannot check whether the hidden type of {name} satisfies auto traits"),
         );
+
+        err.note(
+            "fetching the hidden types of an opaque inside of the defining scope is not supported. \
+            You can try moving the opaque type and the item that actually registers a hidden type into a new submodule",
+        );
         err.span_note(self.tcx.def_span(def_id), "opaque type is declared here");
-        match self.defining_use_anchor {
-            DefiningAnchor::Bubble | DefiningAnchor::Error => {}
-            DefiningAnchor::Bind(bind) => {
-                err.span_note(
-                    self.tcx.def_ident_span(bind).unwrap_or_else(|| self.tcx.def_span(bind)),
-                    "this item depends on auto traits of the hidden type, \
-                    but may also be registering the hidden type. \
-                    This is not supported right now. \
-                    You can try moving the opaque type and the item that actually registers a hidden type into a new submodule".to_string(),
-                );
-            }
-        };
 
         self.note_obligation_cause(&mut err, &obligation);
         self.point_at_returns_when_relevant(&mut err, &obligation);
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index 3dcc8382289..4a1064b29f6 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -54,7 +54,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
         self.span = old;
     }
 
-    fn parent_trait_ref(&self) -> Option<ty::TraitRef<'tcx>> {
+    fn parent_impl_trait_ref(&self) -> Option<ty::TraitRef<'tcx>> {
         let parent = self.parent()?;
         if matches!(self.tcx.def_kind(parent), DefKind::Impl { .. }) {
             Some(self.tcx.impl_trait_ref(parent)?.instantiate_identity())
@@ -210,6 +210,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
             ty::Alias(ty::Opaque, alias_ty) if alias_ty.def_id.is_local() => {
                 self.visit_opaque_ty(alias_ty);
             }
+            // Skips type aliases, as they are meant to be transparent.
             ty::Alias(ty::Weak, alias_ty) if alias_ty.def_id.is_local() => {
                 self.tcx
                     .type_of(alias_ty.def_id)
@@ -220,11 +221,11 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
                 // This avoids having to do normalization of `Self::AssocTy` by only
                 // supporting the case of a method defining opaque types from assoc types
                 // in the same impl block.
-                if let Some(parent_trait_ref) = self.parent_trait_ref() {
+                if let Some(impl_trait_ref) = self.parent_impl_trait_ref() {
                     // If the trait ref of the associated item and the impl differs,
                     // then we can't use the impl's identity args below, so
                     // just skip.
-                    if alias_ty.trait_ref(self.tcx) == parent_trait_ref {
+                    if alias_ty.trait_ref(self.tcx) == impl_trait_ref {
                         let parent = self.parent().expect("we should have a parent here");
 
                         for &assoc in self.tcx.associated_items(parent).in_definition_order() {
@@ -241,7 +242,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
 
                             let impl_args = alias_ty.args.rebase_onto(
                                 self.tcx,
-                                parent_trait_ref.def_id,
+                                impl_trait_ref.def_id,
                                 ty::GenericArgs::identity_for_item(self.tcx, parent),
                             );
 
@@ -259,6 +260,24 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
                             }
                         }
                     }
+                } else if let Some(ty::ImplTraitInTraitData::Trait { fn_def_id, .. }) =
+                    self.tcx.opt_rpitit_info(alias_ty.def_id)
+                    && fn_def_id == self.item.into()
+                {
+                    // RPITIT in trait definitions get desugared to an associated type. For
+                    // default methods we also create an opaque type this associated type
+                    // normalizes to. The associated type is only known to normalize to the
+                    // opaque if it is fully concrete. There could otherwise be an impl
+                    // overwriting the default method.
+                    //
+                    // However, we have to be able to normalize the associated type while inside
+                    // of the default method. This is normally handled by adding an unchecked
+                    // `Projection(<Self as Trait>::synthetic_assoc_ty, trait_def::opaque)`
+                    // assumption to the `param_env` of the default method. We also separately
+                    // rely on that assumption here.
+                    let ty = self.tcx.type_of(alias_ty.def_id).instantiate(self.tcx, alias_ty.args);
+                    let ty::Alias(ty::Opaque, alias_ty) = ty.kind() else { bug!("{ty:?}") };
+                    self.visit_opaque_ty(alias_ty);
                 }
             }
             ty::Adt(def, _) if def.did().is_local() => {
diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs
index 5527d853e30..72fcc95c3b3 100644
--- a/compiler/rustc_ty_utils/src/sig_types.rs
+++ b/compiler/rustc_ty_utils/src/sig_types.rs
@@ -23,8 +23,14 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>(
     match kind {
         // Walk over the signature of the function
         DefKind::AssocFn | DefKind::Fn => {
-            let ty_sig = tcx.fn_sig(item).instantiate_identity();
             let hir_sig = tcx.hir_node_by_def_id(item).fn_decl().unwrap();
+            // If the type of the item uses `_`, we're gonna error out anyway, but
+            // typeck (which type_of invokes below), will call back into opaque_types_defined_by
+            // causing a cycle. So we just bail out in this case.
+            if hir_sig.output.get_infer_ret_ty().is_some() {
+                return V::Result::output();
+            }
+            let ty_sig = tcx.fn_sig(item).instantiate_identity();
             // Walk over the inputs and outputs manually in order to get good spans for them.
             try_visit!(visitor.visit(hir_sig.output.span(), ty_sig.output()));
             for (hir, ty) in hir_sig.inputs.iter().zip(ty_sig.inputs().iter()) {
@@ -39,6 +45,12 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>(
         // Walk over the type of the item
         DefKind::Static(_) | DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => {
             if let Some(ty) = tcx.hir_node_by_def_id(item).ty() {
+                // If the type of the item uses `_`, we're gonna error out anyway, but
+                // typeck (which type_of invokes below), will call back into opaque_types_defined_by
+                // causing a cycle. So we just bail out in this case.
+                if ty.is_suggestable_infer_ty() {
+                    return V::Result::output();
+                }
                 // Associated types in traits don't necessarily have a type that we can visit
                 try_visit!(visitor.visit(ty.span, tcx.type_of(item).instantiate_identity()));
             }
diff --git a/config.example.toml b/config.example.toml
index c1939933850..ddcd0ec02e0 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -679,6 +679,10 @@
 # sysroot.
 #llvm-tools = true
 
+# Indicates whether the `self-contained` llvm-bitcode-linker, will be made available
+# in the sysroot
+#llvm-bitcode-linker = false
+
 # Whether to deny warnings in crates
 #deny-warnings = true
 
@@ -842,6 +846,17 @@
 # See that option for more info.
 #codegen-backends = rust.codegen-backends (array)
 
+# This is a "runner" to pass to `compiletest` when executing tests. Tests will
+# execute this tool where the binary-to-test is passed as an argument. Can
+# be useful for situations such as when WebAssembly is being tested and a
+# runtime needs to be configured. This value is similar to
+# Cargo's `CARGO_$target_RUNNER` configuration.
+#
+# This configuration is a space-separated list of arguments so `foo bar` would
+# execute the program `foo` with the first argument as `bar` and the second
+# argument as the test binary.
+#runner = <none> (string)
+
 # =============================================================================
 # Distribution options
 #
diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs
index 61ec04a4849..0c7f94ccceb 100644
--- a/library/alloc/src/ffi/c_str.rs
+++ b/library/alloc/src/ffi/c_str.rs
@@ -1,3 +1,5 @@
+//! [`CString`] and its related types.
+
 #[cfg(test)]
 mod tests;
 
diff --git a/library/alloc/src/ffi/mod.rs b/library/alloc/src/ffi/mod.rs
index e8530fbc1f0..9fc1acc231b 100644
--- a/library/alloc/src/ffi/mod.rs
+++ b/library/alloc/src/ffi/mod.rs
@@ -80,9 +80,13 @@
 
 #![stable(feature = "alloc_ffi", since = "1.64.0")]
 
+#[doc(no_inline)]
 #[stable(feature = "alloc_c_string", since = "1.64.0")]
-pub use self::c_str::FromVecWithNulError;
+pub use self::c_str::{FromVecWithNulError, IntoStringError, NulError};
+
+#[doc(inline)]
 #[stable(feature = "alloc_c_string", since = "1.64.0")]
-pub use self::c_str::{CString, IntoStringError, NulError};
+pub use self::c_str::CString;
 
-mod c_str;
+#[unstable(feature = "c_str_module", issue = "112134")]
+pub mod c_str;
diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs
index ace73c0fdaa..0ee293db73a 100644
--- a/library/alloc/src/raw_vec.rs
+++ b/library/alloc/src/raw_vec.rs
@@ -5,7 +5,6 @@ use core::cmp;
 use core::hint;
 use core::mem::{self, ManuallyDrop, MaybeUninit, SizedTypeProperties};
 use core::ptr::{self, NonNull, Unique};
-use core::slice;
 
 #[cfg(not(no_global_oom_handling))]
 use crate::alloc::handle_alloc_error;
@@ -192,7 +191,7 @@ impl<T, A: Allocator> RawVec<T, A> {
 
         let me = ManuallyDrop::new(self);
         unsafe {
-            let slice = slice::from_raw_parts_mut(me.ptr() as *mut MaybeUninit<T>, len);
+            let slice = ptr::slice_from_raw_parts_mut(me.ptr() as *mut MaybeUninit<T>, len);
             Box::from_raw_in(slice, ptr::read(&me.alloc))
         }
     }
diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs
index f4e392760c8..21d5dce04a0 100644
--- a/library/alloc/src/slice.rs
+++ b/library/alloc/src/slice.rs
@@ -33,8 +33,6 @@ use crate::vec::Vec;
 #[cfg(test)]
 mod tests;
 
-#[unstable(feature = "slice_range", issue = "76393")]
-pub use core::slice::range;
 #[unstable(feature = "array_chunks", issue = "74985")]
 pub use core::slice::ArrayChunks;
 #[unstable(feature = "array_chunks", issue = "74985")]
@@ -51,6 +49,8 @@ pub use core::slice::{from_mut, from_ref};
 pub use core::slice::{from_mut_ptr_range, from_ptr_range};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::slice::{from_raw_parts, from_raw_parts_mut};
+#[unstable(feature = "slice_range", issue = "76393")]
+pub use core::slice::{range, try_range};
 #[stable(feature = "slice_group_by", since = "1.77.0")]
 pub use core::slice::{ChunkBy, ChunkByMut};
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/backtrace b/library/backtrace
-Subproject 6145fe6bac65c38375f1216a565a6cc7deb89a2
+Subproject ddf1b89b861d297c6ef3f09b70d853e81ccc85f
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index 0825281090c..111fb83088b 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -1,3 +1,5 @@
+//! [`CStr`] and its related types.
+
 use crate::cmp::Ordering;
 use crate::error::Error;
 use crate::ffi::c_char;
@@ -9,15 +11,20 @@ use crate::slice;
 use crate::slice::memchr;
 use crate::str;
 
+// FIXME: because this is doc(inline)d, we *have* to use intra-doc links because the actual link
+//   depends on where the item is being documented. however, since this is libcore, we can't
+//   actually reference libstd or liballoc in intra-doc links. so, the best we can do is remove the
+//   links to `CString` and `String` for now until a solution is developed
+
 /// Representation of a borrowed C string.
 ///
 /// This type represents a borrowed reference to a nul-terminated
 /// array of bytes. It can be constructed safely from a <code>&[[u8]]</code>
 /// slice, or unsafely from a raw `*const c_char`. It can then be
 /// converted to a Rust <code>&[str]</code> by performing UTF-8 validation, or
-/// into an owned [`CString`].
+/// into an owned `CString`.
 ///
-/// `&CStr` is to [`CString`] as <code>&[str]</code> is to [`String`]: the former
+/// `&CStr` is to `CString` as <code>&[str]</code> is to `String`: the former
 /// in each pair are borrowed references; the latter are owned
 /// strings.
 ///
@@ -26,9 +33,6 @@ use crate::str;
 /// Instead, safe wrappers of FFI functions may leverage the unsafe [`CStr::from_ptr`] constructor
 /// to provide a safe interface to other consumers.
 ///
-/// [`CString`]: ../../std/ffi/struct.CString.html
-/// [`String`]: ../../std/string/struct.String.html
-///
 /// # Examples
 ///
 /// Inspecting a foreign C string:
@@ -125,10 +129,13 @@ enum FromBytesWithNulErrorKind {
     NotNulTerminated,
 }
 
+// FIXME: const stability attributes should not be required here, I think
 impl FromBytesWithNulError {
+    #[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")]
     const fn interior_nul(pos: usize) -> FromBytesWithNulError {
         FromBytesWithNulError { kind: FromBytesWithNulErrorKind::InteriorNul(pos) }
     }
+    #[rustc_const_stable(feature = "const_cstr_methods", since = "1.72.0")]
     const fn not_nul_terminated() -> FromBytesWithNulError {
         FromBytesWithNulError { kind: FromBytesWithNulErrorKind::NotNulTerminated }
     }
diff --git a/library/core/src/ffi/mod.rs b/library/core/src/ffi/mod.rs
index 44200926a32..3627e844222 100644
--- a/library/core/src/ffi/mod.rs
+++ b/library/core/src/ffi/mod.rs
@@ -13,10 +13,20 @@ use crate::fmt;
 use crate::marker::PhantomData;
 use crate::ops::{Deref, DerefMut};
 
+#[doc(no_inline)]
 #[stable(feature = "core_c_str", since = "1.64.0")]
-pub use self::c_str::{CStr, FromBytesUntilNulError, FromBytesWithNulError};
+pub use self::c_str::FromBytesWithNulError;
 
-mod c_str;
+#[doc(no_inline)]
+#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
+pub use self::c_str::FromBytesUntilNulError;
+
+#[doc(inline)]
+#[stable(feature = "core_c_str", since = "1.64.0")]
+pub use self::c_str::CStr;
+
+#[unstable(feature = "c_str_module", issue = "112134")]
+pub mod c_str;
 
 macro_rules! type_alias {
     {
diff --git a/library/core/src/io/borrowed_buf.rs b/library/core/src/io/borrowed_buf.rs
index ed06ce6927e..778d38b1537 100644
--- a/library/core/src/io/borrowed_buf.rs
+++ b/library/core/src/io/borrowed_buf.rs
@@ -139,9 +139,11 @@ impl<'data> BorrowedBuf<'data> {
     }
 }
 
-/// A writeable view of the unfilled portion of a [`BorrowedBuf`](BorrowedBuf).
+/// A writeable view of the unfilled portion of a [`BorrowedBuf`].
+///
+/// The unfilled portion consists of an initialized and an uninitialized part; see [`BorrowedBuf`]
+/// for details.
 ///
-/// Provides access to the initialized and uninitialized parts of the underlying `BorrowedBuf`.
 /// Data can be written directly to the cursor by using [`append`](BorrowedCursor::append) or
 /// indirectly by getting a slice of part or all of the cursor and writing into the slice. In the
 /// indirect case, the caller must call [`advance`](BorrowedCursor::advance) after writing to inform
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 0f7885769c2..6bcf7c13e64 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -204,6 +204,7 @@
 // tidy-alphabetical-start
 #![cfg_attr(bootstrap, feature(diagnostic_namespace))]
 #![cfg_attr(bootstrap, feature(platform_intrinsics))]
+#![cfg_attr(not(bootstrap), feature(freeze_impls))]
 #![feature(abi_unadjusted)]
 #![feature(adt_const_params)]
 #![feature(allow_internal_unsafe)]
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 2e22129d7b6..a56a2578c22 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -810,15 +810,21 @@ pub trait DiscriminantKind {
     type Discriminant: Clone + Copy + Debug + Eq + PartialEq + Hash + Send + Sync + Unpin;
 }
 
-/// Compiler-internal trait used to determine whether a type contains
+/// Used to determine whether a type contains
 /// any `UnsafeCell` internally, but not through an indirection.
 /// This affects, for example, whether a `static` of that type is
 /// placed in read-only static memory or writable static memory.
+/// This can be used to declare that a constant with a generic type
+/// will not contain interior mutability, and subsequently allow
+/// placing the constant behind references.
 #[lang = "freeze"]
-pub(crate) unsafe auto trait Freeze {}
+#[unstable(feature = "freeze", issue = "121675")]
+pub unsafe auto trait Freeze {}
 
+#[unstable(feature = "freeze", issue = "121675")]
 impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
 marker_impls! {
+    #[unstable(feature = "freeze", issue = "121675")]
     unsafe Freeze for
         {T: ?Sized} PhantomData<T>,
         {T: ?Sized} *const T,
diff --git a/library/core/src/slice/index.rs b/library/core/src/slice/index.rs
index 312dccbf109..64f1f360821 100644
--- a/library/core/src/slice/index.rs
+++ b/library/core/src/slice/index.rs
@@ -180,19 +180,19 @@ pub unsafe trait SliceIndex<T: ?Sized>: private_slice_index::Sealed {
     #[unstable(feature = "slice_index_methods", issue = "none")]
     fn get_mut(self, slice: &mut T) -> Option<&mut Self::Output>;
 
-    /// Returns a shared reference to the output at this location, without
+    /// Returns a pointer to the output at this location, without
     /// performing any bounds checking.
     /// Calling this method with an out-of-bounds index or a dangling `slice` pointer
-    /// is *[undefined behavior]* even if the resulting reference is not used.
+    /// is *[undefined behavior]* even if the resulting pointer is not used.
     ///
     /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
     #[unstable(feature = "slice_index_methods", issue = "none")]
     unsafe fn get_unchecked(self, slice: *const T) -> *const Self::Output;
 
-    /// Returns a mutable reference to the output at this location, without
+    /// Returns a mutable pointer to the output at this location, without
     /// performing any bounds checking.
     /// Calling this method with an out-of-bounds index or a dangling `slice` pointer
-    /// is *[undefined behavior]* even if the resulting reference is not used.
+    /// is *[undefined behavior]* even if the resulting pointer is not used.
     ///
     /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html
     #[unstable(feature = "slice_index_methods", issue = "none")]
@@ -704,8 +704,7 @@ where
 {
     let len = bounds.end;
 
-    let start: ops::Bound<&usize> = range.start_bound();
-    let start = match start {
+    let start = match range.start_bound() {
         ops::Bound::Included(&start) => start,
         ops::Bound::Excluded(start) => {
             start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
@@ -713,8 +712,7 @@ where
         ops::Bound::Unbounded => 0,
     };
 
-    let end: ops::Bound<&usize> = range.end_bound();
-    let end = match end {
+    let end = match range.end_bound() {
         ops::Bound::Included(end) => {
             end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
         }
@@ -732,6 +730,59 @@ where
     ops::Range { start, end }
 }
 
+/// Performs bounds-checking of a range without panicking.
+///
+/// This is a version of [`range`] that returns [`None`] instead of panicking.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(slice_range)]
+///
+/// use std::slice;
+///
+/// let v = [10, 40, 30];
+/// assert_eq!(Some(1..2), slice::try_range(1..2, ..v.len()));
+/// assert_eq!(Some(0..2), slice::try_range(..2, ..v.len()));
+/// assert_eq!(Some(1..3), slice::try_range(1.., ..v.len()));
+/// ```
+///
+/// Returns [`None`] when [`Index::index`] would panic:
+///
+/// ```
+/// #![feature(slice_range)]
+///
+/// use std::slice;
+///
+/// assert_eq!(None, slice::try_range(2..1, ..3));
+/// assert_eq!(None, slice::try_range(1..4, ..3));
+/// assert_eq!(None, slice::try_range(1..=usize::MAX, ..3));
+/// ```
+///
+/// [`Index::index`]: ops::Index::index
+#[unstable(feature = "slice_range", issue = "76393")]
+#[must_use]
+pub fn try_range<R>(range: R, bounds: ops::RangeTo<usize>) -> Option<ops::Range<usize>>
+where
+    R: ops::RangeBounds<usize>,
+{
+    let len = bounds.end;
+
+    let start = match range.start_bound() {
+        ops::Bound::Included(&start) => start,
+        ops::Bound::Excluded(start) => start.checked_add(1)?,
+        ops::Bound::Unbounded => 0,
+    };
+
+    let end = match range.end_bound() {
+        ops::Bound::Included(end) => end.checked_add(1)?,
+        ops::Bound::Excluded(&end) => end,
+        ops::Bound::Unbounded => len,
+    };
+
+    if start > end || end > len { None } else { Some(ops::Range { start, end }) }
+}
+
 /// Convert pair of `ops::Bound`s into `ops::Range` without performing any bounds checking and (in debug) overflow checking
 pub(crate) fn into_range_unchecked(
     len: usize,
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index 2dd01ba33af..4a574bf0347 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -91,7 +91,7 @@ pub use sort::heapsort;
 pub use index::SliceIndex;
 
 #[unstable(feature = "slice_range", issue = "76393")]
-pub use index::range;
+pub use index::{range, try_range};
 
 #[stable(feature = "inherent_ascii_escape", since = "1.60.0")]
 pub use ascii::EscapeAscii;
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index 8fc942dedc9..1b43c46bda5 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -622,7 +622,7 @@ impl LocalWaker {
     ///
     /// [`poll()`]: crate::future::Future::poll
     #[inline]
-    #[stable(feature = "futures_api", since = "1.36.0")]
+    #[unstable(feature = "local_waker", issue = "118959")]
     pub fn wake(self) {
         // The actual wakeup call is delegated through a virtual function call
         // to the implementation which is defined by the executor.
@@ -644,7 +644,7 @@ impl LocalWaker {
     /// the case where an owned `Waker` is available. This method should be preferred to
     /// calling `waker.clone().wake()`.
     #[inline]
-    #[stable(feature = "futures_api", since = "1.36.0")]
+    #[unstable(feature = "local_waker", issue = "118959")]
     pub fn wake_by_ref(&self) {
         // The actual wakeup call is delegated through a virtual function call
         // to the implementation which is defined by the executor.
@@ -664,7 +664,7 @@ impl LocalWaker {
     /// avoid cloning the waker when they would wake the same task anyway.
     #[inline]
     #[must_use]
-    #[stable(feature = "futures_api", since = "1.36.0")]
+    #[unstable(feature = "local_waker", issue = "118959")]
     pub fn will_wake(&self, other: &LocalWaker) -> bool {
         self.waker == other.waker
     }
@@ -676,7 +676,7 @@ impl LocalWaker {
     /// Therefore this method is unsafe.
     #[inline]
     #[must_use]
-    #[stable(feature = "futures_api", since = "1.36.0")]
+    #[unstable(feature = "local_waker", issue = "118959")]
     #[rustc_const_unstable(feature = "const_waker", issue = "102012")]
     pub const unsafe fn from_raw(waker: RawWaker) -> LocalWaker {
         Self { waker }
@@ -748,7 +748,18 @@ impl AsRef<LocalWaker> for Waker {
     }
 }
 
-#[stable(feature = "futures_api", since = "1.36.0")]
+#[unstable(feature = "local_waker", issue = "118959")]
+impl Drop for LocalWaker {
+    #[inline]
+    fn drop(&mut self) {
+        // SAFETY: This is safe because `LocalWaker::from_raw` is the only way
+        // to initialize `drop` and `data` requiring the user to acknowledge
+        // that the contract of `RawWaker` is upheld.
+        unsafe { (self.waker.vtable.drop)(self.waker.data) }
+    }
+}
+
+#[unstable(feature = "local_waker", issue = "118959")]
 impl fmt::Debug for LocalWaker {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let vtable_ptr = self.waker.vtable as *const RawWakerVTable;
diff --git a/library/panic_unwind/src/gcc.rs b/library/panic_unwind/src/gcc.rs
index 54eb6627c01..589d3c1b4d2 100644
--- a/library/panic_unwind/src/gcc.rs
+++ b/library/panic_unwind/src/gcc.rs
@@ -62,7 +62,7 @@ pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
     let exception = Box::new(Exception {
         _uwe: uw::_Unwind_Exception {
             exception_class: rust_exception_class(),
-            exception_cleanup,
+            exception_cleanup: Some(exception_cleanup),
             private: [core::ptr::null(); uw::unwinder_private_data_size],
         },
         canary: &CANARY,
diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs
index 7a0bae34642..dde1c64c6f1 100644
--- a/library/panic_unwind/src/lib.rs
+++ b/library/panic_unwind/src/lib.rs
@@ -53,12 +53,12 @@ cfg_if::cfg_if! {
         target_os = "solid_asp3",
         all(target_family = "unix", not(target_os = "espidf")),
         all(target_vendor = "fortanix", target_env = "sgx"),
+        target_family = "wasm",
     ))] {
         #[path = "gcc.rs"]
         mod real_imp;
     } else {
         // Targets that don't support unwinding.
-        // - family=wasm
         // - os=none ("bare metal" targets)
         // - os=uefi
         // - os=espidf
diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs
new file mode 100644
index 00000000000..b59b0c5bba6
--- /dev/null
+++ b/library/std/src/ffi/c_str.rs
@@ -0,0 +1,19 @@
+//! [`CStr`], [`CString`], and related types.
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use core::ffi::c_str::CStr;
+
+#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
+pub use core::ffi::c_str::FromBytesWithNulError;
+
+#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
+pub use core::ffi::c_str::FromBytesUntilNulError;
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use alloc::ffi::c_str::{CString, NulError};
+
+#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")]
+pub use alloc::ffi::c_str::FromVecWithNulError;
+
+#[stable(feature = "cstring_into", since = "1.7.0")]
+pub use alloc::ffi::c_str::IntoStringError;
diff --git a/library/std/src/ffi/mod.rs b/library/std/src/ffi/mod.rs
index f810611a02e..f45fd77e8b1 100644
--- a/library/std/src/ffi/mod.rs
+++ b/library/std/src/ffi/mod.rs
@@ -161,12 +161,32 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
-#[stable(feature = "alloc_c_string", since = "1.64.0")]
-pub use alloc::ffi::{CString, FromVecWithNulError, IntoStringError, NulError};
-#[stable(feature = "cstr_from_bytes_until_nul", since = "1.73.0")]
-pub use core::ffi::FromBytesUntilNulError;
-#[stable(feature = "core_c_str", since = "1.64.0")]
-pub use core::ffi::{CStr, FromBytesWithNulError};
+#[unstable(feature = "c_str_module", issue = "112134")]
+pub mod c_str;
+
+#[doc(inline)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::c_str::{CStr, CString};
+
+#[doc(no_inline)]
+#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
+pub use self::c_str::FromBytesWithNulError;
+
+#[doc(no_inline)]
+#[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")]
+pub use self::c_str::FromBytesUntilNulError;
+
+#[doc(no_inline)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use self::c_str::NulError;
+
+#[doc(no_inline)]
+#[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")]
+pub use self::c_str::FromVecWithNulError;
+
+#[doc(no_inline)]
+#[stable(feature = "cstring_into", since = "1.7.0")]
+pub use self::c_str::IntoStringError;
 
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(inline)]
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 9a4a2301b6f..10bf9c51d16 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -692,10 +692,9 @@ pub trait Read {
     /// Callers have to ensure that no unchecked out-of-bounds accesses are possible even if
     /// `n > buf.len()`.
     ///
-    /// No guarantees are provided about the contents of `buf` when this
-    /// 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.
+    /// *Implementations* of this method can make no assumptions about the contents of `buf` when
+    /// this function is called. It is recommended that implementations only write data to `buf`
+    /// instead of reading its contents.
     ///
     /// Correspondingly, however, *callers* of this method in unsafe code must not assume
     /// any guarantees about how the implementation uses `buf`. The trait is safe to implement,
@@ -901,12 +900,10 @@ pub trait Read {
     /// This function reads as many bytes as necessary to completely fill the
     /// specified buffer `buf`.
     ///
-    /// No guarantees are provided about the contents of `buf` when this
-    /// 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
-    /// subject.
+    /// *Implementations* of this method can make no assumptions about the contents of `buf` when
+    /// this function is called. It is recommended that implementations only write data to `buf`
+    /// instead of reading its contents. The documentation on [`read`] has a more detailed
+    /// explanation of this subject.
     ///
     /// # Errors
     ///
diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs
index c306de3039f..eb5d5988768 100644
--- a/library/std/src/io/tests.rs
+++ b/library/std/src/io/tests.rs
@@ -694,6 +694,8 @@ fn read_buf_full_read() {
 }
 
 #[test]
+// Miri does not support signalling OOM
+#[cfg_attr(miri, ignore)]
 // 64-bit only to be sure the allocator will fail fast on an impossible to satsify size
 #[cfg(target_pointer_width = "64")]
 fn try_oom_error() {
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 55a5292a4a4..8cf44f4760d 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -314,6 +314,7 @@
 //
 // Library features (core):
 // tidy-alphabetical-start
+#![feature(c_str_module)]
 #![feature(char_internals)]
 #![feature(core_intrinsics)]
 #![feature(core_io_borrowed_buf)]
diff --git a/library/std/src/os/android/net.rs b/library/std/src/os/android/net.rs
index fe40d6319c2..349e73eaabd 100644
--- a/library/std/src/os/android/net.rs
+++ b/library/std/src/os/android/net.rs
@@ -5,5 +5,8 @@
 #[stable(feature = "unix_socket_abstract", since = "1.70.0")]
 pub use crate::os::net::linux_ext::addr::SocketAddrExt;
 
+#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+pub use crate::os::net::linux_ext::socket::UnixSocketExt;
+
 #[unstable(feature = "tcp_quickack", issue = "96256")]
 pub use crate::os::net::linux_ext::tcp::TcpStreamExt;
diff --git a/library/std/src/os/freebsd/mod.rs b/library/std/src/os/freebsd/mod.rs
index c072fae557f..39912e6970d 100644
--- a/library/std/src/os/freebsd/mod.rs
+++ b/library/std/src/os/freebsd/mod.rs
@@ -3,4 +3,5 @@
 #![stable(feature = "raw_ext", since = "1.1.0")]
 
 pub mod fs;
+pub mod net;
 pub mod raw;
diff --git a/library/std/src/os/freebsd/net.rs b/library/std/src/os/freebsd/net.rs
new file mode 100644
index 00000000000..33990d54caa
--- /dev/null
+++ b/library/std/src/os/freebsd/net.rs
@@ -0,0 +1,65 @@
+//! FreeBSD-specific networking functionality.
+
+#![unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+
+use crate::io;
+use crate::os::unix::net;
+use crate::sealed::Sealed;
+use crate::sys_common::AsInner;
+
+/// FreeBSD-specific functionality for `AF_UNIX` sockets [`UnixDatagram`]
+/// and [`UnixStream`].
+///
+/// [`UnixDatagram`]: net::UnixDatagram
+/// [`UnixStream`]: net::UnixStream
+#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+pub trait UnixSocketExt: Sealed {
+    /// Query the current setting of socket option `LOCAL_CREDS_PERSISTENT`.
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    fn local_creds_persistent(&self) -> io::Result<bool>;
+
+    /// Enable or disable socket option `LOCAL_CREDS_PERSISTENT`.
+    ///
+    /// This option enables the credentials of the sending process to be
+    /// received as a control message in [`AncillaryData`].
+    ///
+    /// [`AncillaryData`]: net::AncillaryData
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(unix_socket_ancillary_data)]
+    /// use std::os::freebsd::net::UnixSocketExt;
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixDatagram::unbound()?;
+    ///     sock.set_local_creds_persistent(true).expect("set_local_creds_persistent failed");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    fn set_local_creds_persistent(&self, local_creds_persistent: bool) -> io::Result<()>;
+}
+
+#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+impl UnixSocketExt for net::UnixDatagram {
+    fn local_creds_persistent(&self) -> io::Result<bool> {
+        self.as_inner().local_creds_persistent()
+    }
+
+    fn set_local_creds_persistent(&self, local_creds_persistent: bool) -> io::Result<()> {
+        self.as_inner().set_local_creds_persistent(local_creds_persistent)
+    }
+}
+
+#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+impl UnixSocketExt for net::UnixStream {
+    fn local_creds_persistent(&self) -> io::Result<bool> {
+        self.as_inner().local_creds_persistent()
+    }
+
+    fn set_local_creds_persistent(&self, local_creds_persistent: bool) -> io::Result<()> {
+        self.as_inner().set_local_creds_persistent(local_creds_persistent)
+    }
+}
diff --git a/library/std/src/os/linux/net.rs b/library/std/src/os/linux/net.rs
index c8e734d740b..f898e705487 100644
--- a/library/std/src/os/linux/net.rs
+++ b/library/std/src/os/linux/net.rs
@@ -5,5 +5,8 @@
 #[stable(feature = "unix_socket_abstract", since = "1.70.0")]
 pub use crate::os::net::linux_ext::addr::SocketAddrExt;
 
+#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+pub use crate::os::net::linux_ext::socket::UnixSocketExt;
+
 #[unstable(feature = "tcp_quickack", issue = "96256")]
 pub use crate::os::net::linux_ext::tcp::TcpStreamExt;
diff --git a/library/std/src/os/net/linux_ext/mod.rs b/library/std/src/os/net/linux_ext/mod.rs
index 62e78cc50d4..d0979640c32 100644
--- a/library/std/src/os/net/linux_ext/mod.rs
+++ b/library/std/src/os/net/linux_ext/mod.rs
@@ -5,6 +5,9 @@
 #[stable(feature = "unix_socket_abstract", since = "1.70.0")]
 pub(crate) mod addr;
 
+#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+pub(crate) mod socket;
+
 #[unstable(feature = "tcp_quickack", issue = "96256")]
 pub(crate) mod tcp;
 
diff --git a/library/std/src/os/net/linux_ext/socket.rs b/library/std/src/os/net/linux_ext/socket.rs
new file mode 100644
index 00000000000..4e4168f693c
--- /dev/null
+++ b/library/std/src/os/net/linux_ext/socket.rs
@@ -0,0 +1,63 @@
+//! Linux and Android-specific socket functionality.
+
+use crate::io;
+use crate::os::unix::net;
+use crate::sealed::Sealed;
+use crate::sys_common::AsInner;
+
+/// Linux-specific functionality for `AF_UNIX` sockets [`UnixDatagram`]
+/// and [`UnixStream`].
+///
+/// [`UnixDatagram`]: net::UnixDatagram
+/// [`UnixStream`]: net::UnixStream
+#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+pub trait UnixSocketExt: Sealed {
+    /// Query the current setting of socket option `SO_PASSCRED`.
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    fn passcred(&self) -> io::Result<bool>;
+
+    /// Enable or disable socket option `SO_PASSCRED`.
+    ///
+    /// This option enables the credentials of the sending process to be
+    /// received as a control message in [`AncillaryData`].
+    ///
+    /// [`AncillaryData`]: net::AncillaryData
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(unix_socket_ancillary_data)]
+    /// use std::os::linux::net::UnixSocketExt;
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixDatagram::unbound()?;
+    ///     sock.set_passcred(true).expect("set_passcred failed");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    fn set_passcred(&self, passcred: bool) -> io::Result<()>;
+}
+
+#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+impl UnixSocketExt for net::UnixDatagram {
+    fn passcred(&self) -> io::Result<bool> {
+        self.as_inner().passcred()
+    }
+
+    fn set_passcred(&self, passcred: bool) -> io::Result<()> {
+        self.as_inner().set_passcred(passcred)
+    }
+}
+
+#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+impl UnixSocketExt for net::UnixStream {
+    fn passcred(&self) -> io::Result<bool> {
+        self.as_inner().passcred()
+    }
+
+    fn set_passcred(&self, passcred: bool) -> io::Result<()> {
+        self.as_inner().set_passcred(passcred)
+    }
+}
diff --git a/library/std/src/os/netbsd/mod.rs b/library/std/src/os/netbsd/mod.rs
index 497a51a1df6..2f21e98a6f4 100644
--- a/library/std/src/os/netbsd/mod.rs
+++ b/library/std/src/os/netbsd/mod.rs
@@ -3,4 +3,5 @@
 #![stable(feature = "raw_ext", since = "1.1.0")]
 
 pub mod fs;
+pub mod net;
 pub mod raw;
diff --git a/library/std/src/os/netbsd/net.rs b/library/std/src/os/netbsd/net.rs
new file mode 100644
index 00000000000..5c82f43077d
--- /dev/null
+++ b/library/std/src/os/netbsd/net.rs
@@ -0,0 +1,65 @@
+//! NetBSD-specific networking functionality.
+
+#![unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+
+use crate::io;
+use crate::os::unix::net;
+use crate::sealed::Sealed;
+use crate::sys_common::AsInner;
+
+/// NetBSD-specific functionality for `AF_UNIX` sockets [`UnixDatagram`]
+/// and [`UnixStream`].
+///
+/// [`UnixDatagram`]: net::UnixDatagram
+/// [`UnixStream`]: net::UnixStream
+#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+pub trait UnixSocketExt: Sealed {
+    /// Query the current setting of socket option `LOCAL_CREDS`.
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    fn local_creds(&self) -> io::Result<bool>;
+
+    /// Enable or disable socket option `LOCAL_CREDS`.
+    ///
+    /// This option enables the credentials of the sending process to be
+    /// received as a control message in [`AncillaryData`].
+    ///
+    /// [`AncillaryData`]: net::AncillaryData
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// #![feature(unix_socket_ancillary_data)]
+    /// use std::os::netbsd::net::UnixSocketExt;
+    /// use std::os::unix::net::UnixDatagram;
+    ///
+    /// fn main() -> std::io::Result<()> {
+    ///     let sock = UnixDatagram::unbound()?;
+    ///     sock.set_local_creds(true).expect("set_local_creds failed");
+    ///     Ok(())
+    /// }
+    /// ```
+    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+    fn set_local_creds(&self, local_creds: bool) -> io::Result<()>;
+}
+
+#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+impl UnixSocketExt for net::UnixDatagram {
+    fn local_creds(&self) -> io::Result<bool> {
+        self.as_inner().local_creds()
+    }
+
+    fn set_local_creds(&self, local_creds: bool) -> io::Result<()> {
+        self.as_inner().set_local_creds(local_creds)
+    }
+}
+
+#[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
+impl UnixSocketExt for net::UnixStream {
+    fn local_creds(&self) -> io::Result<bool> {
+        self.as_inner().local_creds()
+    }
+
+    fn set_local_creds(&self, local_creds: bool) -> io::Result<()> {
+        self.as_inner().set_local_creds(local_creds)
+    }
+}
diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs
index 0b4d955294c..df698c17f6c 100644
--- a/library/std/src/os/unix/net/datagram.rs
+++ b/library/std/src/os/unix/net/datagram.rs
@@ -6,6 +6,7 @@ use crate::io::{IoSlice, IoSliceMut};
 use crate::net::Shutdown;
 use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
 use crate::path::Path;
+use crate::sealed::Sealed;
 use crate::sys::cvt;
 use crate::sys::net::Socket;
 use crate::sys_common::{AsInner, FromInner, IntoInner};
@@ -54,6 +55,10 @@ const MSG_NOSIGNAL: libc::c_int = 0x0;
 #[stable(feature = "unix_socket", since = "1.10.0")]
 pub struct UnixDatagram(Socket);
 
+/// Allows extension traits within `std`.
+#[unstable(feature = "sealed", issue = "none")]
+impl Sealed for UnixDatagram {}
+
 #[stable(feature = "unix_socket", since = "1.10.0")]
 impl fmt::Debug for UnixDatagram {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -802,69 +807,6 @@ impl UnixDatagram {
         self.0.set_nonblocking(nonblocking)
     }
 
-    /// Moves the socket to pass unix credentials as control message in [`SocketAncillary`].
-    ///
-    /// Set the socket option `SO_PASSCRED`.
-    ///
-    /// # Examples
-    ///
-    #[cfg_attr(
-        any(
-            target_os = "android",
-            target_os = "linux",
-            target_os = "netbsd",
-            target_os = "freebsd",
-        ),
-        doc = "```no_run"
-    )]
-    #[cfg_attr(
-        not(any(
-            target_os = "android",
-            target_os = "linux",
-            target_os = "netbsd",
-            target_os = "freebsd"
-        )),
-        doc = "```ignore"
-    )]
-    /// #![feature(unix_socket_ancillary_data)]
-    /// use std::os::unix::net::UnixDatagram;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let sock = UnixDatagram::unbound()?;
-    ///     sock.set_passcred(true).expect("set_passcred function failed");
-    ///     Ok(())
-    /// }
-    /// ```
-    #[cfg(any(
-        doc,
-        target_os = "android",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "freebsd"
-    ))]
-    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
-    pub fn set_passcred(&self, passcred: bool) -> io::Result<()> {
-        self.0.set_passcred(passcred)
-    }
-
-    /// Get the current value of the socket for passing unix credentials in [`SocketAncillary`].
-    /// This value can be change by [`set_passcred`].
-    ///
-    /// Get the socket option `SO_PASSCRED`.
-    ///
-    /// [`set_passcred`]: UnixDatagram::set_passcred
-    #[cfg(any(
-        doc,
-        target_os = "android",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "freebsd"
-    ))]
-    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
-    pub fn passcred(&self) -> io::Result<bool> {
-        self.0.passcred()
-    }
-
     /// Set the id of the socket for network filtering purpose
     ///
     #[cfg_attr(
@@ -1038,3 +980,10 @@ impl From<OwnedFd> for UnixDatagram {
         unsafe { Self::from_raw_fd(owned.into_raw_fd()) }
     }
 }
+
+impl AsInner<Socket> for UnixDatagram {
+    #[inline]
+    fn as_inner(&self) -> &Socket {
+        &self.0
+    }
+}
diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs
index 069cb299e28..d2e23bdee6c 100644
--- a/library/std/src/os/unix/net/stream.rs
+++ b/library/std/src/os/unix/net/stream.rs
@@ -19,6 +19,7 @@ use crate::io::{self, IoSlice, IoSliceMut};
 use crate::net::Shutdown;
 use crate::os::unix::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
 use crate::path::Path;
+use crate::sealed::Sealed;
 use crate::sys::cvt;
 use crate::sys::net::Socket;
 use crate::sys_common::{AsInner, FromInner};
@@ -44,6 +45,10 @@ use crate::time::Duration;
 #[stable(feature = "unix_socket", since = "1.10.0")]
 pub struct UnixStream(pub(super) Socket);
 
+/// Allows extension traits within `std`.
+#[unstable(feature = "sealed", issue = "none")]
+impl Sealed for UnixStream {}
+
 #[stable(feature = "unix_socket", since = "1.10.0")]
 impl fmt::Debug for UnixStream {
     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -379,69 +384,6 @@ impl UnixStream {
         self.0.set_nonblocking(nonblocking)
     }
 
-    /// Moves the socket to pass unix credentials as control message in [`SocketAncillary`].
-    ///
-    /// Set the socket option `SO_PASSCRED`.
-    ///
-    /// # Examples
-    ///
-    #[cfg_attr(
-        any(
-            target_os = "android",
-            target_os = "linux",
-            target_os = "netbsd",
-            target_os = "freebsd"
-        ),
-        doc = "```no_run"
-    )]
-    #[cfg_attr(
-        not(any(
-            target_os = "android",
-            target_os = "linux",
-            target_os = "netbsd",
-            target_os = "freebsd"
-        )),
-        doc = "```ignore"
-    )]
-    /// #![feature(unix_socket_ancillary_data)]
-    /// use std::os::unix::net::UnixStream;
-    ///
-    /// fn main() -> std::io::Result<()> {
-    ///     let socket = UnixStream::connect("/tmp/sock")?;
-    ///     socket.set_passcred(true).expect("Couldn't set passcred");
-    ///     Ok(())
-    /// }
-    /// ```
-    #[cfg(any(
-        doc,
-        target_os = "android",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "freebsd"
-    ))]
-    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
-    pub fn set_passcred(&self, passcred: bool) -> io::Result<()> {
-        self.0.set_passcred(passcred)
-    }
-
-    /// Get the current value of the socket for passing unix credentials in [`SocketAncillary`].
-    /// This value can be change by [`set_passcred`].
-    ///
-    /// Get the socket option `SO_PASSCRED`.
-    ///
-    /// [`set_passcred`]: UnixStream::set_passcred
-    #[cfg(any(
-        doc,
-        target_os = "android",
-        target_os = "linux",
-        target_os = "netbsd",
-        target_os = "freebsd"
-    ))]
-    #[unstable(feature = "unix_socket_ancillary_data", issue = "76915")]
-    pub fn passcred(&self) -> io::Result<bool> {
-        self.0.passcred()
-    }
-
     /// Set the id of the socket for network filtering purpose
     ///
     #[cfg_attr(
@@ -751,3 +693,10 @@ impl From<OwnedFd> for UnixStream {
         unsafe { Self::from_raw_fd(owned.into_raw_fd()) }
     }
 }
+
+impl AsInner<Socket> for UnixStream {
+    #[inline]
+    fn as_inner(&self) -> &Socket {
+        &self.0
+    }
+}
diff --git a/library/std/src/os/unix/net/tests.rs b/library/std/src/os/unix/net/tests.rs
index 6a6af9efd78..e456e41b21c 100644
--- a/library/std/src/os/unix/net/tests.rs
+++ b/library/std/src/os/unix/net/tests.rs
@@ -8,10 +8,10 @@ use crate::thread;
 use crate::time::Duration;
 
 #[cfg(target_os = "android")]
-use crate::os::android::net::SocketAddrExt;
+use crate::os::android::net::{SocketAddrExt, UnixSocketExt};
 
 #[cfg(target_os = "linux")]
-use crate::os::linux::net::SocketAddrExt;
+use crate::os::linux::net::{SocketAddrExt, UnixSocketExt};
 
 macro_rules! or_panic {
     ($e:expr) => {
diff --git a/library/std/src/sys/pal/unix/net.rs b/library/std/src/sys/pal/unix/net.rs
index 60546a3de45..09750b6ffc8 100644
--- a/library/std/src/sys/pal/unix/net.rs
+++ b/library/std/src/sys/pal/unix/net.rs
@@ -465,25 +465,31 @@ impl Socket {
     }
 
     #[cfg(target_os = "netbsd")]
-    pub fn set_passcred(&self, passcred: bool) -> io::Result<()> {
-        setsockopt(self, 0 as libc::c_int, libc::LOCAL_CREDS, passcred as libc::c_int)
+    pub fn set_local_creds(&self, local_creds: bool) -> io::Result<()> {
+        setsockopt(self, 0 as libc::c_int, libc::LOCAL_CREDS, local_creds as libc::c_int)
     }
 
     #[cfg(target_os = "netbsd")]
-    pub fn passcred(&self) -> io::Result<bool> {
-        let passcred: libc::c_int = getsockopt(self, 0 as libc::c_int, libc::LOCAL_CREDS)?;
-        Ok(passcred != 0)
+    pub fn local_creds(&self) -> io::Result<bool> {
+        let local_creds: libc::c_int = getsockopt(self, 0 as libc::c_int, libc::LOCAL_CREDS)?;
+        Ok(local_creds != 0)
     }
 
     #[cfg(target_os = "freebsd")]
-    pub fn set_passcred(&self, passcred: bool) -> io::Result<()> {
-        setsockopt(self, libc::AF_LOCAL, libc::LOCAL_CREDS_PERSISTENT, passcred as libc::c_int)
+    pub fn set_local_creds_persistent(&self, local_creds_persistent: bool) -> io::Result<()> {
+        setsockopt(
+            self,
+            libc::AF_LOCAL,
+            libc::LOCAL_CREDS_PERSISTENT,
+            local_creds_persistent as libc::c_int,
+        )
     }
 
     #[cfg(target_os = "freebsd")]
-    pub fn passcred(&self) -> io::Result<bool> {
-        let passcred: libc::c_int = getsockopt(self, libc::AF_LOCAL, libc::LOCAL_CREDS_PERSISTENT)?;
-        Ok(passcred != 0)
+    pub fn local_creds_persistent(&self) -> io::Result<bool> {
+        let local_creds_persistent: libc::c_int =
+            getsockopt(self, libc::AF_LOCAL, libc::LOCAL_CREDS_PERSISTENT)?;
+        Ok(local_creds_persistent != 0)
     }
 
     #[cfg(not(any(target_os = "solaris", target_os = "illumos", target_os = "vita")))]
diff --git a/library/std/src/sys/pal/unix/rand.rs b/library/std/src/sys/pal/unix/rand.rs
index 5c32957bc51..c9ed6825f6c 100644
--- a/library/std/src/sys/pal/unix/rand.rs
+++ b/library/std/src/sys/pal/unix/rand.rs
@@ -62,7 +62,13 @@ mod imp {
         unsafe { getrandom(buf.as_mut_ptr().cast(), buf.len(), libc::GRND_NONBLOCK) }
     }
 
-    #[cfg(any(target_os = "espidf", target_os = "horizon", target_os = "freebsd", netbsd10))]
+    #[cfg(any(
+        target_os = "espidf",
+        target_os = "horizon",
+        target_os = "freebsd",
+        target_os = "dragonfly",
+        netbsd10
+    ))]
     fn getrandom(buf: &mut [u8]) -> libc::ssize_t {
         unsafe { libc::getrandom(buf.as_mut_ptr().cast(), buf.len(), 0) }
     }
@@ -73,6 +79,7 @@ mod imp {
         target_os = "espidf",
         target_os = "horizon",
         target_os = "freebsd",
+        target_os = "dragonfly",
         netbsd10
     )))]
     fn getrandom_fill_bytes(_buf: &mut [u8]) -> bool {
@@ -85,6 +92,7 @@ mod imp {
         target_os = "espidf",
         target_os = "horizon",
         target_os = "freebsd",
+        target_os = "dragonfly",
         netbsd10
     ))]
     fn getrandom_fill_bytes(v: &mut [u8]) -> bool {
diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs
index 923637cbaf2..78a599077c7 100644
--- a/library/std/src/sys/pal/unix/stack_overflow.rs
+++ b/library/std/src/sys/pal/unix/stack_overflow.rs
@@ -51,7 +51,7 @@ mod imp {
     #[cfg(all(target_os = "linux", target_env = "gnu"))]
     use libc::{mmap64, munmap};
     use libc::{sigaction, sighandler_t, SA_ONSTACK, SA_SIGINFO, SIGBUS, SIG_DFL};
-    use libc::{sigaltstack, SIGSTKSZ, SS_DISABLE};
+    use libc::{sigaltstack, SS_DISABLE};
     use libc::{MAP_ANON, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SIGSEGV};
 
     use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
@@ -130,7 +130,7 @@ mod imp {
         drop_handler(MAIN_ALTSTACK.load(Ordering::Relaxed));
     }
 
-    unsafe fn get_stackp() -> *mut libc::c_void {
+    unsafe fn get_stack() -> libc::stack_t {
         // OpenBSD requires this flag for stack mapping
         // otherwise the said mapping will fail as a no-op on most systems
         // and has a different meaning on FreeBSD
@@ -148,20 +148,28 @@ mod imp {
             target_os = "dragonfly",
         )))]
         let flags = MAP_PRIVATE | MAP_ANON;
-        let stackp =
-            mmap64(ptr::null_mut(), SIGSTKSZ + page_size(), PROT_READ | PROT_WRITE, flags, -1, 0);
+
+        let sigstack_size = sigstack_size();
+        let page_size = page_size();
+
+        let stackp = mmap64(
+            ptr::null_mut(),
+            sigstack_size + page_size,
+            PROT_READ | PROT_WRITE,
+            flags,
+            -1,
+            0,
+        );
         if stackp == MAP_FAILED {
             panic!("failed to allocate an alternative stack: {}", io::Error::last_os_error());
         }
-        let guard_result = libc::mprotect(stackp, page_size(), PROT_NONE);
+        let guard_result = libc::mprotect(stackp, page_size, PROT_NONE);
         if guard_result != 0 {
             panic!("failed to set up alternative stack guard page: {}", io::Error::last_os_error());
         }
-        stackp.add(page_size())
-    }
+        let stackp = stackp.add(page_size);
 
-    unsafe fn get_stack() -> libc::stack_t {
-        libc::stack_t { ss_sp: get_stackp(), ss_flags: 0, ss_size: SIGSTKSZ }
+        libc::stack_t { ss_sp: stackp, ss_flags: 0, ss_size: sigstack_size }
     }
 
     pub unsafe fn make_handler() -> Handler {
@@ -182,6 +190,8 @@ mod imp {
 
     pub unsafe fn drop_handler(data: *mut libc::c_void) {
         if !data.is_null() {
+            let sigstack_size = sigstack_size();
+            let page_size = page_size();
             let stack = libc::stack_t {
                 ss_sp: ptr::null_mut(),
                 ss_flags: SS_DISABLE,
@@ -189,14 +199,32 @@ mod imp {
                 // UNIX2003 which returns ENOMEM when disabling a stack while
                 // passing ss_size smaller than MINSIGSTKSZ. According to POSIX
                 // both ss_sp and ss_size should be ignored in this case.
-                ss_size: SIGSTKSZ,
+                ss_size: sigstack_size,
             };
             sigaltstack(&stack, ptr::null_mut());
             // We know from `get_stackp` that the alternate stack we installed is part of a mapping
             // that started one page earlier, so walk back a page and unmap from there.
-            munmap(data.sub(page_size()), SIGSTKSZ + page_size());
+            munmap(data.sub(page_size), sigstack_size + page_size);
         }
     }
+
+    /// Modern kernels on modern hardware can have dynamic signal stack sizes.
+    #[cfg(any(target_os = "linux", target_os = "android"))]
+    fn sigstack_size() -> usize {
+        // FIXME: reuse const from libc when available?
+        const AT_MINSIGSTKSZ: crate::ffi::c_ulong = 51;
+        let dynamic_sigstksz = unsafe { libc::getauxval(AT_MINSIGSTKSZ) };
+        // If getauxval couldn't find the entry, it returns 0,
+        // so take the higher of the "constant" and auxval.
+        // This transparently supports older kernels which don't provide AT_MINSIGSTKSZ
+        libc::SIGSTKSZ.max(dynamic_sigstksz as _)
+    }
+
+    /// Not all OS support hardware where this is needed.
+    #[cfg(not(any(target_os = "linux", target_os = "android")))]
+    fn sigstack_size() -> usize {
+        libc::SIGSTKSZ
+    }
 }
 
 #[cfg(not(any(
diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs
index 2af6382f3da..6520ca9fc48 100644
--- a/library/std/src/sys/pal/unix/thread.rs
+++ b/library/std/src/sys/pal/unix/thread.rs
@@ -806,9 +806,9 @@ pub mod guard {
     #[cfg(any(
         target_os = "android",
         target_os = "freebsd",
+        target_os = "netbsd",
         target_os = "hurd",
         target_os = "linux",
-        target_os = "netbsd",
         target_os = "l4re"
     ))]
     unsafe fn get_stack_start() -> Option<*mut libc::c_void> {
@@ -911,9 +911,10 @@ pub mod guard {
                         }
                     }) * page_size;
             Some(guard)
-        } else if cfg!(target_os = "openbsd") {
+        } else if cfg!(any(target_os = "openbsd", target_os = "netbsd")) {
             // OpenBSD stack already includes a guard page, and stack is
             // immutable.
+            // NetBSD stack includes the guard page.
             //
             // We'll just note where we expect rlimit to start
             // faulting, so our handler can report "stack overflow", and
diff --git a/library/std/src/sys/pal/windows/alloc.rs b/library/std/src/sys/pal/windows/alloc.rs
index 270eca37b14..681d1a5efe9 100644
--- a/library/std/src/sys/pal/windows/alloc.rs
+++ b/library/std/src/sys/pal/windows/alloc.rs
@@ -6,6 +6,7 @@ use crate::ptr;
 use crate::sync::atomic::{AtomicPtr, Ordering};
 use crate::sys::c;
 use crate::sys::common::alloc::{realloc_fallback, MIN_ALIGN};
+use core::mem::MaybeUninit;
 
 #[cfg(test)]
 mod tests;
@@ -94,29 +95,30 @@ static HEAP: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut());
 // a non-null handle returned by `GetProcessHeap`.
 #[inline]
 fn init_or_get_process_heap() -> c::HANDLE {
-    let heap = HEAP.load(Ordering::Relaxed);
-    if core::intrinsics::unlikely(heap.is_null()) {
-        // `HEAP` has not yet been successfully initialized
-        let heap = unsafe { GetProcessHeap() };
-        if !heap.is_null() {
-            // SAFETY: No locking is needed because within the same process,
-            // successful calls to `GetProcessHeap` will always return the same value, even on different threads.
-            HEAP.store(heap, Ordering::Release);
-
-            // SAFETY: `HEAP` contains a non-null handle returned by `GetProcessHeap`
-            heap
-        } else {
-            // Could not get the current process heap.
-            ptr::null_mut()
-        }
-    } else {
+    // `HEAP` has not yet been successfully initialized
+    let heap = unsafe { GetProcessHeap() };
+    if !heap.is_null() {
+        // SAFETY: No locking is needed because within the same process,
+        // successful calls to `GetProcessHeap` will always return the same value, even on different threads.
+        HEAP.store(heap, Ordering::Release);
+
         // SAFETY: `HEAP` contains a non-null handle returned by `GetProcessHeap`
         heap
+    } else {
+        // Could not get the current process heap.
+        ptr::null_mut()
     }
 }
 
+/// This is outlined from `process_heap_alloc` so that `process_heap_alloc`
+/// does not need any stack allocations.
 #[inline(never)]
-fn process_heap_alloc(flags: c::DWORD, dwBytes: c::SIZE_T) -> c::LPVOID {
+#[cold]
+extern "C" fn process_heap_init_and_alloc(
+    _heap: MaybeUninit<c::HANDLE>, // We pass this argument to match the ABI of `HeapAlloc`
+    flags: c::DWORD,
+    dwBytes: c::SIZE_T,
+) -> c::LPVOID {
     let heap = init_or_get_process_heap();
     if core::intrinsics::unlikely(heap.is_null()) {
         return ptr::null_mut();
@@ -125,6 +127,21 @@ fn process_heap_alloc(flags: c::DWORD, dwBytes: c::SIZE_T) -> c::LPVOID {
     unsafe { HeapAlloc(heap, flags, dwBytes) }
 }
 
+#[inline(never)]
+fn process_heap_alloc(
+    _heap: MaybeUninit<c::HANDLE>, // We pass this argument to match the ABI of `HeapAlloc`,
+    flags: c::DWORD,
+    dwBytes: c::SIZE_T,
+) -> c::LPVOID {
+    let heap = HEAP.load(Ordering::Relaxed);
+    if core::intrinsics::likely(!heap.is_null()) {
+        // SAFETY: `heap` is a non-null handle returned by `GetProcessHeap`.
+        unsafe { HeapAlloc(heap, flags, dwBytes) }
+    } else {
+        process_heap_init_and_alloc(MaybeUninit::uninit(), flags, dwBytes)
+    }
+}
+
 // Get a non-null handle to the default heap of the current process.
 // SAFETY: `HEAP` must have been successfully initialized.
 #[inline]
@@ -148,12 +165,12 @@ unsafe fn allocate(layout: Layout, zeroed: bool) -> *mut u8 {
 
     if layout.align() <= MIN_ALIGN {
         // The returned pointer points to the start of an allocated block.
-        process_heap_alloc(flags, layout.size()) as *mut u8
+        process_heap_alloc(MaybeUninit::uninit(), flags, layout.size()) as *mut u8
     } else {
         // Allocate extra padding in order to be able to satisfy the alignment.
         let total = layout.align() + layout.size();
 
-        let ptr = process_heap_alloc(flags, total) as *mut u8;
+        let ptr = process_heap_alloc(MaybeUninit::uninit(), flags, total) as *mut u8;
         if ptr.is_null() {
             // Allocation has failed.
             return ptr::null_mut();
diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs
index 2fc6598d876..1c828bac4b6 100644
--- a/library/std/src/sys/pal/windows/c.rs
+++ b/library/std/src/sys/pal/windows/c.rs
@@ -344,6 +344,7 @@ compat_fn_with_fallback! {
 
     // >= Win8 / Server 2012
     // https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimepreciseasfiletime
+    #[cfg(target_vendor = "win7")]
     pub fn GetSystemTimePreciseAsFileTime(lpsystemtimeasfiletime: *mut FILETIME) -> () {
         GetSystemTimeAsFileTime(lpsystemtimeasfiletime)
     }
diff --git a/library/std/src/sys/pal/windows/c/bindings.txt b/library/std/src/sys/pal/windows/c/bindings.txt
index 7667f761106..849e64ac591 100644
--- a/library/std/src/sys/pal/windows/c/bindings.txt
+++ b/library/std/src/sys/pal/windows/c/bindings.txt
@@ -2476,6 +2476,7 @@ Windows.Win32.System.Pipes.PIPE_WAIT
 Windows.Win32.System.SystemInformation.GetSystemDirectoryW
 Windows.Win32.System.SystemInformation.GetSystemInfo
 Windows.Win32.System.SystemInformation.GetSystemTimeAsFileTime
+Windows.Win32.System.SystemInformation.GetSystemTimePreciseAsFileTime
 Windows.Win32.System.SystemInformation.GetWindowsDirectoryW
 Windows.Win32.System.SystemInformation.PROCESSOR_ARCHITECTURE
 Windows.Win32.System.SystemInformation.SYSTEM_INFO
diff --git a/library/std/src/sys/pal/windows/c/windows_sys.rs b/library/std/src/sys/pal/windows/c/windows_sys.rs
index 7b751079afb..baaa8257d84 100644
--- a/library/std/src/sys/pal/windows/c/windows_sys.rs
+++ b/library/std/src/sys/pal/windows/c/windows_sys.rs
@@ -346,6 +346,10 @@ extern "system" {
 }
 #[link(name = "kernel32")]
 extern "system" {
+    pub fn GetSystemTimePreciseAsFileTime(lpsystemtimeasfiletime: *mut FILETIME) -> ();
+}
+#[link(name = "kernel32")]
+extern "system" {
     pub fn GetTempPathW(nbufferlength: u32, lpbuffer: PWSTR) -> u32;
 }
 #[link(name = "kernel32")]
diff --git a/library/std/src/sys/personality/mod.rs b/library/std/src/sys/personality/mod.rs
index d37b8ce6346..1a6ea1dafcb 100644
--- a/library/std/src/sys/personality/mod.rs
+++ b/library/std/src/sys/personality/mod.rs
@@ -16,11 +16,12 @@ mod dwarf;
 cfg_if::cfg_if! {
     if #[cfg(target_os = "emscripten")] {
         mod emcc;
-    } else if #[cfg(target_env = "msvc")] {
+    } else if #[cfg(any(target_env = "msvc", target_family = "wasm"))] {
         // This is required by the compiler to exist (e.g., it's a lang item),
         // but it's never actually called by the compiler because
-        // _CxxFrameHandler3 is the personality function that is always used.
-        // Hence this is just an aborting stub.
+        // __CxxFrameHandler3 (msvc) / __gxx_wasm_personality_v0 (wasm) is the
+        // personality function that is always used.  Hence this is just an
+        // aborting stub.
         #[lang = "eh_personality"]
         fn rust_eh_personality() {
             core::intrinsics::abort()
@@ -36,7 +37,6 @@ cfg_if::cfg_if! {
         mod gcc;
     } else {
         // Targets that don't support unwinding.
-        // - family=wasm
         // - os=none ("bare metal" targets)
         // - os=uefi
         // - os=espidf
diff --git a/library/test/src/console.rs b/library/test/src/console.rs
index 09aa3bfb6aa..8096e498263 100644
--- a/library/test/src/console.rs
+++ b/library/test/src/console.rs
@@ -323,10 +323,11 @@ pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> io::Resu
     // Prevent the usage of `Instant` in some cases:
     // - It's currently not supported for wasm targets.
     // - We disable it for miri because it's not available when isolation is enabled.
-    let is_instant_supported =
-        !cfg!(target_family = "wasm") && !cfg!(target_os = "zkvm") && !cfg!(miri);
+    let is_instant_unsupported = (cfg!(target_family = "wasm") && !cfg!(target_os = "wasi"))
+        || cfg!(target_os = "zkvm")
+        || cfg!(miri);
 
-    let start_time = is_instant_supported.then(Instant::now);
+    let start_time = (!is_instant_unsupported).then(Instant::now);
     run_tests(opts, tests, |x| on_test_event(&x, &mut st, &mut *out))?;
     st.exec_time = start_time.map(|t| TestSuiteExecTime(t.elapsed()));
 
diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs
index a64f2904633..45aa0ea4fbb 100644
--- a/library/unwind/src/lib.rs
+++ b/library/unwind/src/lib.rs
@@ -6,6 +6,10 @@
 #![cfg_attr(bootstrap, feature(cfg_target_abi))]
 #![feature(strict_provenance)]
 #![cfg_attr(not(target_env = "msvc"), feature(libc))]
+#![cfg_attr(
+    all(target_family = "wasm", not(target_os = "emscripten")),
+    feature(link_llvm_intrinsics)
+)]
 #![allow(internal_features)]
 
 cfg_if::cfg_if! {
@@ -29,9 +33,11 @@ cfg_if::cfg_if! {
     } else if #[cfg(target_os = "xous")] {
         mod unwinding;
         pub use unwinding::*;
+    } else if #[cfg(target_family = "wasm")] {
+        mod wasm;
+        pub use wasm::*;
     } else {
         // no unwinder on the system!
-        // - wasm32 (not emscripten, which is "unix" family)
         // - os=none ("bare metal" targets)
         // - os=hermit
         // - os=uefi
diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs
index 527c408c89e..0a0dc9438b3 100644
--- a/library/unwind/src/libunwind.rs
+++ b/library/unwind/src/libunwind.rs
@@ -91,7 +91,7 @@ pub struct _Unwind_Exception {
 pub enum _Unwind_Context {}
 
 pub type _Unwind_Exception_Cleanup_Fn =
-    extern "C" fn(unwind_code: _Unwind_Reason_Code, exception: *mut _Unwind_Exception);
+    Option<extern "C" fn(unwind_code: _Unwind_Reason_Code, exception: *mut _Unwind_Exception)>;
 
 // FIXME: The `#[link]` attributes on `extern "C"` block marks those symbols declared in
 // the block are reexported in dylib build of std. This is needed when build rustc with
diff --git a/library/unwind/src/unwinding.rs b/library/unwind/src/unwinding.rs
index 1a4187b2220..95e2eb000cc 100644
--- a/library/unwind/src/unwinding.rs
+++ b/library/unwind/src/unwinding.rs
@@ -46,7 +46,7 @@ pub const unwinder_private_data_size: usize = core::mem::size_of::<UnwindExcepti
     - core::mem::size_of::<_Unwind_Exception_Cleanup_Fn>();
 
 pub type _Unwind_Exception_Cleanup_Fn =
-    extern "C" fn(unwind_code: _Unwind_Reason_Code, exception: *mut _Unwind_Exception);
+    Option<extern "C" fn(unwind_code: _Unwind_Reason_Code, exception: *mut _Unwind_Exception)>;
 
 #[repr(C)]
 pub struct _Unwind_Exception {
diff --git a/library/unwind/src/wasm.rs b/library/unwind/src/wasm.rs
new file mode 100644
index 00000000000..b06671bcb83
--- /dev/null
+++ b/library/unwind/src/wasm.rs
@@ -0,0 +1,65 @@
+//! A shim for libunwind implemented in terms of the native wasm `throw` instruction.
+
+#![allow(nonstandard_style)]
+
+#[repr(C)]
+#[derive(Debug, Copy, Clone, PartialEq)]
+pub enum _Unwind_Reason_Code {
+    _URC_NO_REASON = 0,
+    _URC_FOREIGN_EXCEPTION_CAUGHT = 1,
+    _URC_FATAL_PHASE2_ERROR = 2,
+    _URC_FATAL_PHASE1_ERROR = 3,
+    _URC_NORMAL_STOP = 4,
+    _URC_END_OF_STACK = 5,
+    _URC_HANDLER_FOUND = 6,
+    _URC_INSTALL_CONTEXT = 7,
+    _URC_CONTINUE_UNWIND = 8,
+    _URC_FAILURE = 9, // used only by ARM EHABI
+}
+pub use _Unwind_Reason_Code::*;
+
+pub type _Unwind_Exception_Class = u64;
+pub type _Unwind_Word = *const u8;
+
+pub const unwinder_private_data_size: usize = 2;
+
+#[repr(C)]
+pub struct _Unwind_Exception {
+    pub exception_class: _Unwind_Exception_Class,
+    pub exception_cleanup: _Unwind_Exception_Cleanup_Fn,
+    pub private: [_Unwind_Word; unwinder_private_data_size],
+}
+
+pub type _Unwind_Exception_Cleanup_Fn =
+    Option<extern "C" fn(unwind_code: _Unwind_Reason_Code, exception: *mut _Unwind_Exception)>;
+
+pub unsafe fn _Unwind_DeleteException(exception: *mut _Unwind_Exception) {
+    if let Some(exception_cleanup) = unsafe { (*exception).exception_cleanup } {
+        exception_cleanup(_URC_FOREIGN_EXCEPTION_CAUGHT, exception);
+    }
+}
+
+pub unsafe fn _Unwind_RaiseException(exception: *mut _Unwind_Exception) -> _Unwind_Reason_Code {
+    #[cfg(panic = "unwind")]
+    extern "C" {
+        /// LLVM lowers this intrinsic to the `throw` instruction.
+        // FIXME(coolreader18): move to stdarch
+        #[link_name = "llvm.wasm.throw"]
+        fn wasm_throw(tag: i32, ptr: *mut u8) -> !;
+    }
+
+    // The wasm `throw` instruction takes a "tag", which differentiates certain
+    // types of exceptions from others. LLVM currently just identifies these
+    // via integers, with 0 corresponding to C++ exceptions and 1 to C setjmp()/longjmp().
+    // Ideally, we'd be able to choose something unique for Rust, but for now,
+    // we pretend to be C++ and implement the Itanium exception-handling ABI.
+    cfg_if::cfg_if! {
+        // for now, unless we're -Zbuild-std with panic=unwind, never codegen a throw.
+        if #[cfg(panic = "unwind")] {
+            wasm_throw(0, exception.cast())
+        } else {
+            let _ = exception;
+            core::arch::wasm32::unreachable()
+        }
+    }
+}
diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md
index d0a069f45e1..077db44ae54 100644
--- a/src/bootstrap/README.md
+++ b/src/bootstrap/README.md
@@ -1,7 +1,7 @@
 # rustbuild - Bootstrapping Rust
 
-This README is aimed at helping to explain how Rust is bootstrapped and in general,
-some of the technical details of the build system.
+This README is aimed at helping to explain how Rust is bootstrapped,
+and some of the technical details of the build system.
 
 Note that this README only covers internal information, not how to use the tool.
 Please check [bootstrapping dev guide][bootstrapping-dev-guide] for further information.
@@ -10,12 +10,12 @@ Please check [bootstrapping dev guide][bootstrapping-dev-guide] for further info
 
 ## Introduction
 
-The build system defers most of the complicated logic managing invocations
+The build system defers most of the complicated logic of managing invocations
 of rustc and rustdoc to Cargo itself. However, moving through various stages
 and copying artifacts is still necessary for it to do. Each time rustbuild
 is invoked, it will iterate through the list of predefined steps and execute
 each serially in turn if it matches the paths passed or is a default rule.
-For each step rustbuild relies on the step internally being incremental and
+For each step, rustbuild relies on the step internally being incremental and
 parallel. Note, though, that the `-j` parameter to rustbuild gets forwarded
 to appropriate test harnesses and such.
 
@@ -24,7 +24,7 @@ to appropriate test harnesses and such.
 The rustbuild build system goes through a few phases to actually build the
 compiler. What actually happens when you invoke rustbuild is:
 
-1. The entry point script(`x` for unix like systems, `x.ps1` for windows systems,
+1. The entry point script (`x` for unix like systems, `x.ps1` for windows systems,
    `x.py` cross-platform) is run. This script is responsible for downloading the stage0
    compiler/Cargo binaries, and it then compiles the build system itself (this folder).
    Finally, it then invokes the actual `bootstrap` binary build system.
@@ -107,12 +107,13 @@ build/
 
     # Location where the stage0 Cargo and Rust compiler are unpacked. This
     # directory is purely an extracted and overlaid tarball of these two (done
-    # by the bootstrap python script). In theory, the build system does not
+    # by the bootstrap Python script). In theory, the build system does not
     # modify anything under this directory afterwards.
     stage0/
 
     # These to-build directories are the cargo output directories for builds of
-    # the standard library and compiler, respectively. Internally, these may also
+    # the standard library, the test system, the compiler, and various tools,
+    # respectively. Internally, these may also
     # have other target directories, which represent artifacts being compiled
     # from the host to the specified target.
     #
@@ -169,17 +170,17 @@ read by the other.
 
 Some general areas that you may be interested in modifying are:
 
-* Adding a new build tool? Take a look at `bootstrap/tool.rs` for examples of
-  other tools.
+* Adding a new build tool? Take a look at `bootstrap/src/core/build_steps/tool.rs`
+  for examples of other tools.
 * Adding a new compiler crate? Look no further! Adding crates can be done by
-  adding a new directory with `Cargo.toml` followed by configuring all
+  adding a new directory with `Cargo.toml`, followed by configuring all
   `Cargo.toml` files accordingly.
 * Adding a new dependency from crates.io? This should just work inside the
   compiler artifacts stage (everything other than libtest and libstd).
-* Adding a new configuration option? You'll want to modify `bootstrap/flags.rs`
-  for command line flags and then `bootstrap/config.rs` to copy the flags to the
+* Adding a new configuration option? You'll want to modify `bootstrap/src/core/config/flags.rs`
+  for command line flags and then `bootstrap/src/core/config/config.rs` to copy the flags to the
   `Config` struct.
-* Adding a sanity check? Take a look at `bootstrap/sanity.rs`.
+* Adding a sanity check? Take a look at `bootstrap/src/core/sanity.rs`.
 
 If you make a major change on bootstrap configuration, please remember to:
 
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index 4257c0f7991..9c43160d455 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -54,6 +54,7 @@ o("cargo-native-static", "build.cargo-native-static", "static native libraries i
 o("profiler", "build.profiler", "build the profiler runtime")
 o("full-tools", None, "enable all tools")
 o("lld", "rust.lld", "build lld")
+o("llvm-bitcode-linker", "rust.llvm-bitcode-linker", "build llvm bitcode linker")
 o("clang", "llvm.clang", "build clang")
 o("use-libcxx", "llvm.use-libcxx", "build LLVM with libc++")
 o("control-flow-guard", "rust.control-flow-guard", "Enable Control Flow Guard")
@@ -366,6 +367,7 @@ def apply_args(known_args, option_checking, config):
             set('rust.codegen-backends', ['llvm'], config)
             set('rust.lld', True, config)
             set('rust.llvm-tools', True, config)
+            set('rust.llvm-bitcode-linker', True, config)
             set('build.extended', True, config)
         elif option.name in ['option-checking', 'verbose-configure']:
             # this was handled above
diff --git a/src/bootstrap/defaults/config.compiler.toml b/src/bootstrap/defaults/config.compiler.toml
index e276f126211..d93c5fd25a1 100644
--- a/src/bootstrap/defaults/config.compiler.toml
+++ b/src/bootstrap/defaults/config.compiler.toml
@@ -17,6 +17,8 @@ lto = "off"
 # Forces frame pointers to be used with `-Cforce-frame-pointers`.
 # This can be helpful for profiling at a small performance cost.
 frame-pointers = true
+# Build the llvm-bitcode-linker as it is required for running nvptx tests
+llvm-bitcode-linker = true
 
 [llvm]
 # Having this set to true disrupts compiler development workflows for people who use `llvm.download-ci-llvm = true`
diff --git a/src/bootstrap/defaults/config.dist.toml b/src/bootstrap/defaults/config.dist.toml
index 44efdf50b96..f3c6ffc9bd5 100644
--- a/src/bootstrap/defaults/config.dist.toml
+++ b/src/bootstrap/defaults/config.dist.toml
@@ -16,6 +16,8 @@ download-ci-llvm = false
 # Make sure they don't get set when installing from source.
 channel = "nightly"
 download-rustc = false
+# Build the llvm-bitcode-linker as it is required for running nvptx tests
+llvm-bitcode-linker = true
 
 [dist]
 # Use better compression when preparing tarballs.
diff --git a/src/bootstrap/defaults/config.library.toml b/src/bootstrap/defaults/config.library.toml
index 087544397f5..4a1a49b7275 100644
--- a/src/bootstrap/defaults/config.library.toml
+++ b/src/bootstrap/defaults/config.library.toml
@@ -10,6 +10,8 @@ bench-stage = 0
 incremental = true
 # Make the compiler and standard library faster to build, at the expense of a ~20% runtime slowdown.
 lto = "off"
+# Build the llvm-bitcode-linker as it is required for running nvptx tests
+llvm-bitcode-linker = true
 
 [llvm]
 # Will download LLVM from CI if available on your platform.
diff --git a/src/bootstrap/defaults/config.tools.toml b/src/bootstrap/defaults/config.tools.toml
index 6e6c3660027..94c8b724cbf 100644
--- a/src/bootstrap/defaults/config.tools.toml
+++ b/src/bootstrap/defaults/config.tools.toml
@@ -12,6 +12,8 @@ incremental = true
 # Using these defaults will download the stage2 compiler (see `download-rustc`
 # setting) and the stage2 toolchain should therefore be used for these defaults.
 download-rustc = "if-unchanged"
+# Build the llvm-bitcode-linker as it is required for running nvptx tests
+llvm-bitcode-linker = true
 
 [build]
 # Document with the in-tree rustdoc by default, since `download-rustc` makes it quick to compile.
diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs
index f6f4253a364..a90139a070a 100644
--- a/src/bootstrap/src/core/build_steps/check.rs
+++ b/src/bootstrap/src/core/build_steps/check.rs
@@ -8,12 +8,10 @@ use crate::core::builder::{
     self, crate_description, Alias, Builder, Kind, RunConfig, ShouldRun, Step,
 };
 use crate::core::config::TargetSelection;
-use crate::utils::cache::Interned;
-use crate::INTERNER;
 use crate::{Compiler, Mode, Subcommand};
 use std::path::{Path, PathBuf};
 
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Std {
     pub target: TargetSelection,
     /// Whether to build only a subset of crates.
@@ -21,7 +19,7 @@ pub struct Std {
     /// This shouldn't be used from other steps; see the comment on [`compile::Rustc`].
     ///
     /// [`compile::Rustc`]: crate::core::build_steps::compile::Rustc
-    crates: Interned<Vec<String>>,
+    crates: Vec<String>,
 }
 
 /// Returns args for the subcommand itself (not for cargo)
@@ -89,7 +87,7 @@ fn cargo_subcommand(kind: Kind) -> &'static str {
 
 impl Std {
     pub fn new(target: TargetSelection) -> Self {
-        Self { target, crates: INTERNER.intern_list(vec![]) }
+        Self { target, crates: vec![] }
     }
 }
 
@@ -204,7 +202,7 @@ impl Step for Std {
     }
 }
 
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Rustc {
     pub target: TargetSelection,
     /// Whether to build only a subset of crates.
@@ -212,7 +210,7 @@ pub struct Rustc {
     /// This shouldn't be used from other steps; see the comment on [`compile::Rustc`].
     ///
     /// [`compile::Rustc`]: crate::core::build_steps::compile::Rustc
-    crates: Interned<Vec<String>>,
+    crates: Vec<String>,
 }
 
 impl Rustc {
@@ -222,7 +220,7 @@ impl Rustc {
             .into_iter()
             .map(|krate| krate.name.to_string())
             .collect();
-        Self { target, crates: INTERNER.intern_list(crates) }
+        Self { target, crates }
     }
 }
 
@@ -305,10 +303,10 @@ impl Step for Rustc {
     }
 }
 
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct CodegenBackend {
     pub target: TargetSelection,
-    pub backend: Interned<String>,
+    pub backend: &'static str,
 }
 
 impl Step for CodegenBackend {
@@ -321,14 +319,14 @@ impl Step for CodegenBackend {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        for &backend in &[INTERNER.intern_str("cranelift"), INTERNER.intern_str("gcc")] {
+        for &backend in &["cranelift", "gcc"] {
             run.builder.ensure(CodegenBackend { target: run.target, backend });
         }
     }
 
     fn run(self, builder: &Builder<'_>) {
         // FIXME: remove once https://github.com/rust-lang/rust/issues/112393 is resolved
-        if builder.build.config.vendor && &self.backend == "gcc" {
+        if builder.build.config.vendor && self.backend == "gcc" {
             println!("Skipping checking of `rustc_codegen_gcc` with vendoring enabled.");
             return;
         }
@@ -552,7 +550,7 @@ fn codegen_backend_stamp(
     builder: &Builder<'_>,
     compiler: Compiler,
     target: TargetSelection,
-    backend: Interned<String>,
+    backend: &str,
 ) -> PathBuf {
     builder
         .cargo_out(compiler, Mode::Codegen, target)
diff --git a/src/bootstrap/src/core/build_steps/clean.rs b/src/bootstrap/src/core/build_steps/clean.rs
index 17ca92f25a9..9e103a350e6 100644
--- a/src/bootstrap/src/core/build_steps/clean.rs
+++ b/src/bootstrap/src/core/build_steps/clean.rs
@@ -10,7 +10,6 @@ use std::io::{self, ErrorKind};
 use std::path::Path;
 
 use crate::core::builder::{crate_description, Builder, RunConfig, ShouldRun, Step};
-use crate::utils::cache::Interned;
 use crate::utils::helpers::t;
 use crate::{Build, Compiler, Mode, Subcommand};
 
@@ -44,10 +43,10 @@ impl Step for CleanAll {
 
 macro_rules! clean_crate_tree {
     ( $( $name:ident, $mode:path, $root_crate:literal);+ $(;)? ) => { $(
-        #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+        #[derive(Debug, Clone, PartialEq, Eq, Hash)]
         pub struct $name {
             compiler: Compiler,
-            crates: Interned<Vec<String>>,
+            crates: Vec<String>,
         }
 
         impl Step for $name {
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 4bf50e19c3f..242fe3c12b9 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -27,7 +27,6 @@ use crate::core::builder::crate_description;
 use crate::core::builder::Cargo;
 use crate::core::builder::{Builder, Kind, PathSet, RunConfig, ShouldRun, Step, TaskPath};
 use crate::core::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection};
-use crate::utils::cache::{Interned, INTERNER};
 use crate::utils::helpers::{
     exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, output, symlink_dir, t, up_to_date,
 };
@@ -35,14 +34,14 @@ use crate::LLVM_TOOLS;
 use crate::{CLang, Compiler, DependencyType, GitRepo, Mode};
 use filetime::FileTime;
 
-#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
 pub struct Std {
     pub target: TargetSelection,
     pub compiler: Compiler,
     /// Whether to build only a subset of crates in the standard library.
     ///
     /// This shouldn't be used from other steps; see the comment on [`Rustc`].
-    crates: Interned<Vec<String>>,
+    crates: Vec<String>,
     /// When using download-rustc, we need to use a new build of `std` for running unit tests of Std itself,
     /// but we need to use the downloaded copy of std for linking to rustdoc. Allow this to be overriden by `builder.ensure` from other steps.
     force_recompile: bool,
@@ -559,13 +558,13 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
     cargo.rustdocflag("-Zcrate-attr=warn(rust_2018_idioms)");
 }
 
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 struct StdLink {
     pub compiler: Compiler,
     pub target_compiler: Compiler,
     pub target: TargetSelection,
     /// Not actually used; only present to make sure the cache invalidation is correct.
-    crates: Interned<Vec<String>>,
+    crates: Vec<String>,
     /// See [`Std::force_recompile`].
     force_recompile: bool,
 }
@@ -612,7 +611,7 @@ impl Step for StdLink {
             });
             let libdir = sysroot.join(lib).join("rustlib").join(target.triple).join("lib");
             let hostdir = sysroot.join(lib).join("rustlib").join(compiler.host.triple).join("lib");
-            (INTERNER.intern_path(libdir), INTERNER.intern_path(hostdir))
+            (libdir, hostdir)
         } else {
             let libdir = builder.sysroot_libdir(target_compiler, target);
             let hostdir = builder.sysroot_libdir(target_compiler, compiler.host);
@@ -818,7 +817,7 @@ fn cp_rustc_component_to_ci_sysroot(
     }
 }
 
-#[derive(Debug, PartialOrd, Ord, Copy, Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, PartialOrd, Ord, Clone, PartialEq, Eq, Hash)]
 pub struct Rustc {
     pub target: TargetSelection,
     pub compiler: Compiler,
@@ -827,7 +826,7 @@ pub struct Rustc {
     /// This should only be requested by the user, not used within rustbuild itself.
     /// Using it within rustbuild can lead to confusing situation where lints are replayed
     /// in two different steps.
-    crates: Interned<Vec<String>>,
+    crates: Vec<String>,
 }
 
 impl Rustc {
@@ -1220,13 +1219,13 @@ fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelect
     }
 }
 
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 struct RustcLink {
     pub compiler: Compiler,
     pub target_compiler: Compiler,
     pub target: TargetSelection,
     /// Not actually used; only present to make sure the cache invalidation is correct.
-    crates: Interned<Vec<String>>,
+    crates: Vec<String>,
 }
 
 impl RustcLink {
@@ -1261,11 +1260,11 @@ impl Step for RustcLink {
     }
 }
 
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct CodegenBackend {
     pub target: TargetSelection,
     pub compiler: Compiler,
-    pub backend: Interned<String>,
+    pub backend: String,
 }
 
 fn needs_codegen_config(run: &RunConfig<'_>) -> bool {
@@ -1284,7 +1283,7 @@ pub(crate) const CODEGEN_BACKEND_PREFIX: &str = "rustc_codegen_";
 fn is_codegen_cfg_needed(path: &TaskPath, run: &RunConfig<'_>) -> bool {
     if path.path.to_str().unwrap().contains(CODEGEN_BACKEND_PREFIX) {
         let mut needs_codegen_backend_config = true;
-        for &backend in run.builder.config.codegen_backends(run.target) {
+        for backend in run.builder.config.codegen_backends(run.target) {
             if path
                 .path
                 .to_str()
@@ -1321,7 +1320,7 @@ impl Step for CodegenBackend {
             return;
         }
 
-        for &backend in run.builder.config.codegen_backends(run.target) {
+        for backend in run.builder.config.codegen_backends(run.target) {
             if backend == "llvm" {
                 continue; // Already built as part of rustc
             }
@@ -1329,7 +1328,7 @@ impl Step for CodegenBackend {
             run.builder.ensure(CodegenBackend {
                 target: run.target,
                 compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()),
-                backend,
+                backend: backend.clone(),
             });
         }
     }
@@ -1394,7 +1393,7 @@ impl Step for CodegenBackend {
                 f.display()
             );
         }
-        let stamp = codegen_backend_stamp(builder, compiler, target, backend);
+        let stamp = codegen_backend_stamp(builder, compiler, target, &backend);
         let codegen_backend = codegen_backend.to_str().unwrap();
         t!(fs::write(stamp, codegen_backend));
     }
@@ -1433,7 +1432,7 @@ fn copy_codegen_backends_to_sysroot(
             continue; // Already built as part of rustc
         }
 
-        let stamp = codegen_backend_stamp(builder, compiler, target, *backend);
+        let stamp = codegen_backend_stamp(builder, compiler, target, backend);
         let dylib = t!(fs::read_to_string(&stamp));
         let file = Path::new(&dylib);
         let filename = file.file_name().unwrap().to_str().unwrap();
@@ -1470,7 +1469,7 @@ fn codegen_backend_stamp(
     builder: &Builder<'_>,
     compiler: Compiler,
     target: TargetSelection,
-    backend: Interned<String>,
+    backend: &str,
 ) -> PathBuf {
     builder
         .cargo_out(compiler, Mode::Codegen, target)
@@ -1508,7 +1507,7 @@ impl Sysroot {
 }
 
 impl Step for Sysroot {
-    type Output = Interned<PathBuf>;
+    type Output = PathBuf;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
         run.never()
@@ -1520,7 +1519,7 @@ impl Step for Sysroot {
     /// That is, the sysroot for the stage0 compiler is not what the compiler
     /// thinks it is by default, but it's the same as the default for stages
     /// 1-3.
-    fn run(self, builder: &Builder<'_>) -> Interned<PathBuf> {
+    fn run(self, builder: &Builder<'_>) -> PathBuf {
         let compiler = self.compiler;
         let host_dir = builder.out.join(compiler.host.triple);
 
@@ -1652,7 +1651,7 @@ impl Step for Sysroot {
             );
         }
 
-        INTERNER.intern_path(sysroot)
+        sysroot
     }
 }
 
@@ -1735,7 +1734,7 @@ impl Step for Assemble {
         // to not fail while linking the artifacts.
         build_compiler.stage = actual_stage;
 
-        for &backend in builder.config.codegen_backends(target_compiler.host) {
+        for backend in builder.config.codegen_backends(target_compiler.host) {
             if backend == "llvm" {
                 continue; // Already built as part of rustc
             }
@@ -1743,7 +1742,7 @@ impl Step for Assemble {
             builder.ensure(CodegenBackend {
                 compiler: build_compiler,
                 target: target_compiler.host,
-                backend,
+                backend: backend.clone(),
             });
         }
 
@@ -1844,6 +1843,16 @@ impl Step for Assemble {
             }
         }
 
+        if builder.config.llvm_bitcode_linker_enabled {
+            let src_path = builder.ensure(crate::core::build_steps::tool::LlvmBitcodeLinker {
+                compiler: build_compiler,
+                target: target_compiler.host,
+                extra_features: vec![],
+            });
+            let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
+            builder.copy(&src_path, &libdir_bin.join(&tool_exe));
+        }
+
         // Ensure that `libLLVM.so` ends up in the newly build compiler directory,
         // so that it can be found when the newly built `rustc` is run.
         dist::maybe_install_llvm_runtime(builder, target_compiler.host, &sysroot);
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 1090edc9c92..613c58252d3 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -25,7 +25,6 @@ use crate::core::build_steps::llvm;
 use crate::core::build_steps::tool::{self, Tool};
 use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
 use crate::core::config::TargetSelection;
-use crate::utils::cache::{Interned, INTERNER};
 use crate::utils::channel;
 use crate::utils::helpers::{exe, is_dylib, output, t, target_supports_cranelift_backend, timeit};
 use crate::utils::tarball::{GeneratedTarball, OverlayKind, Tarball};
@@ -489,8 +488,7 @@ impl Step for Rustc {
             }
 
             // Debugger scripts
-            builder
-                .ensure(DebuggerScripts { sysroot: INTERNER.intern_path(image.to_owned()), host });
+            builder.ensure(DebuggerScripts { sysroot: image.to_owned(), host });
 
             // Misc license info
             let cp = |file: &str| {
@@ -504,9 +502,9 @@ impl Step for Rustc {
     }
 }
 
-#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct DebuggerScripts {
-    pub sysroot: Interned<PathBuf>,
+    pub sysroot: PathBuf,
     pub host: TargetSelection,
 }
 
@@ -1264,10 +1262,10 @@ impl Step for Miri {
     }
 }
 
-#[derive(Debug, PartialOrd, Ord, Copy, Clone, Hash, PartialEq, Eq)]
+#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
 pub struct CodegenBackend {
     pub compiler: Compiler,
-    pub backend: Interned<String>,
+    pub backend: String,
 }
 
 impl Step for CodegenBackend {
@@ -1280,14 +1278,14 @@ impl Step for CodegenBackend {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        for &backend in run.builder.config.codegen_backends(run.target) {
+        for backend in run.builder.config.codegen_backends(run.target) {
             if backend == "llvm" {
                 continue; // Already built as part of rustc
             }
 
             run.builder.ensure(CodegenBackend {
                 compiler: run.builder.compiler(run.builder.top_stage, run.target),
-                backend,
+                backend: backend.clone(),
             });
         }
     }
@@ -1304,7 +1302,8 @@ impl Step for CodegenBackend {
             return None;
         }
 
-        if !builder.config.codegen_backends(self.compiler.host).contains(&self.backend) {
+        if !builder.config.codegen_backends(self.compiler.host).contains(&self.backend.to_string())
+        {
             return None;
         }
 
@@ -1529,7 +1528,7 @@ impl Step for Extended {
         add_component!("analysis" => Analysis { compiler, target });
         add_component!("rustc-codegen-cranelift" => CodegenBackend {
             compiler: builder.compiler(stage, target),
-            backend: INTERNER.intern_str("cranelift"),
+            backend: "cranelift".to_string(),
         });
 
         let etc = builder.src.join("src/etc/installer");
diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs
index c4235755ba8..c23cd9374a6 100644
--- a/src/bootstrap/src/core/build_steps/doc.rs
+++ b/src/bootstrap/src/core/build_steps/doc.rs
@@ -16,7 +16,6 @@ use crate::core::build_steps::tool::{self, prepare_tool_cargo, SourceType, Tool}
 use crate::core::builder::{self, crate_description};
 use crate::core::builder::{Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
 use crate::core::config::{Config, TargetSelection};
-use crate::utils::cache::{Interned, INTERNER};
 use crate::utils::helpers::{dir_is_empty, symlink_dir, t, up_to_date};
 use crate::Mode;
 
@@ -59,8 +58,8 @@ macro_rules! book {
                 )?
                 builder.ensure(RustbookSrc {
                     target: self.target,
-                    name: INTERNER.intern_str($book_name),
-                    src: INTERNER.intern_path(builder.src.join($path)),
+                    name: $book_name.to_owned(),
+                    src: builder.src.join($path),
                     parent: Some(self),
                 })
             }
@@ -108,18 +107,18 @@ impl Step for UnstableBook {
         builder.ensure(UnstableBookGen { target: self.target });
         builder.ensure(RustbookSrc {
             target: self.target,
-            name: INTERNER.intern_str("unstable-book"),
-            src: INTERNER.intern_path(builder.md_doc_out(self.target).join("unstable-book")),
+            name: "unstable-book".to_owned(),
+            src: builder.md_doc_out(self.target).join("unstable-book"),
             parent: Some(self),
         })
     }
 }
 
-#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
 struct RustbookSrc<P: Step> {
     target: TargetSelection,
-    name: Interned<String>,
-    src: Interned<PathBuf>,
+    name: String,
+    src: PathBuf,
     parent: Option<P>,
 }
 
@@ -141,7 +140,7 @@ impl<P: Step> Step for RustbookSrc<P> {
         let out = builder.doc_out(target);
         t!(fs::create_dir_all(&out));
 
-        let out = out.join(name);
+        let out = out.join(&name);
         let index = out.join("index.html");
         let rustbook = builder.tool_exe(Tool::Rustbook);
         let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook);
@@ -211,8 +210,8 @@ impl Step for TheBook {
         // build book
         builder.ensure(RustbookSrc {
             target,
-            name: INTERNER.intern_str("book"),
-            src: INTERNER.intern_path(absolute_path.clone()),
+            name: "book".to_owned(),
+            src: absolute_path.clone(),
             parent: Some(self),
         });
 
@@ -220,8 +219,8 @@ impl Step for TheBook {
         for edition in &["first-edition", "second-edition", "2018-edition"] {
             builder.ensure(RustbookSrc {
                 target,
-                name: INTERNER.intern_string(format!("book/{edition}")),
-                src: INTERNER.intern_path(absolute_path.join(edition)),
+                name: format!("book/{edition}"),
+                src: absolute_path.join(edition),
                 // There should only be one book that is marked as the parent for each target, so
                 // treat the other editions as not having a parent.
                 parent: Option::<Self>::None,
@@ -526,12 +525,12 @@ impl Step for SharedAssets {
     }
 }
 
-#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
+#[derive(Debug, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
 pub struct Std {
     pub stage: u32,
     pub target: TargetSelection,
     pub format: DocumentationFormat,
-    crates: Interned<Vec<String>>,
+    crates: Vec<String>,
 }
 
 impl Std {
@@ -546,7 +545,7 @@ impl Std {
             .into_iter()
             .map(|krate| krate.name.to_string())
             .collect();
-        Std { stage, target, format, crates: INTERNER.intern_list(crates) }
+        Std { stage, target, format, crates }
     }
 }
 
@@ -721,11 +720,11 @@ fn doc_std(
     builder.cp_r(&out_dir, out);
 }
 
-#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct Rustc {
     pub stage: u32,
     pub target: TargetSelection,
-    crates: Interned<Vec<String>>,
+    crates: Vec<String>,
 }
 
 impl Rustc {
@@ -735,7 +734,7 @@ impl Rustc {
             .into_iter()
             .map(|krate| krate.name.to_string())
             .collect();
-        Self { stage, target, crates: INTERNER.intern_list(crates) }
+        Self { stage, target, crates }
     }
 }
 
@@ -1194,8 +1193,8 @@ impl Step for RustcBook {
         // Run rustbook/mdbook to generate the HTML pages.
         builder.ensure(RustbookSrc {
             target: self.target,
-            name: INTERNER.intern_str("rustc"),
-            src: INTERNER.intern_path(out_base),
+            name: "rustc".to_owned(),
+            src: out_base,
             parent: Some(self),
         });
     }
diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs
index 6726671ddd9..41920fabaa9 100644
--- a/src/bootstrap/src/core/build_steps/install.rs
+++ b/src/bootstrap/src/core/build_steps/install.rs
@@ -13,7 +13,6 @@ use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
 use crate::core::config::{Config, TargetSelection};
 use crate::utils::helpers::t;
 use crate::utils::tarball::GeneratedTarball;
-use crate::INTERNER;
 use crate::{Compiler, Kind};
 
 #[cfg(target_os = "illumos")]
@@ -291,7 +290,7 @@ install!((self, builder, _config),
     RustcCodegenCranelift, alias = "rustc-codegen-cranelift", Self::should_build(_config), only_hosts: true, {
         if let Some(tarball) = builder.ensure(dist::CodegenBackend {
             compiler: self.compiler,
-            backend: INTERNER.intern_str("cranelift"),
+            backend: "cranelift".to_string(),
         }) {
             install_sh(builder, "rustc-codegen-cranelift", self.compiler.stage, Some(self.target), &tarball);
         } else {
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 4a4497e57db..47b0637538b 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -26,7 +26,6 @@ use crate::core::builder::{Builder, Compiler, Kind, RunConfig, ShouldRun, Step};
 use crate::core::config::flags::get_completion;
 use crate::core::config::flags::Subcommand;
 use crate::core::config::TargetSelection;
-use crate::utils::cache::{Interned, INTERNER};
 use crate::utils::exec::BootstrapCommand;
 use crate::utils::helpers::{
     self, add_link_lib_path, add_rustdoc_cargo_linker_args, dylib_path, dylib_path_var,
@@ -38,9 +37,9 @@ use crate::{envify, CLang, DocTests, GitRepo, Mode};
 
 const ADB_TEST_DIR: &str = "/data/local/tmp/work";
 
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct CrateBootstrap {
-    path: Interned<PathBuf>,
+    path: PathBuf,
     host: TargetSelection,
 }
 
@@ -58,7 +57,7 @@ impl Step for CrateBootstrap {
 
     fn make_run(run: RunConfig<'_>) {
         for path in run.paths {
-            let path = INTERNER.intern_path(path.assert_single_path().path.clone());
+            let path = path.assert_single_path().path.clone();
             run.builder.ensure(CrateBootstrap { host: run.target, path });
         }
     }
@@ -623,7 +622,7 @@ impl Step for Miri {
 
         // miri tests need to know about the stage sysroot
         cargo.env("MIRI_SYSROOT", &miri_sysroot);
-        cargo.env("MIRI_HOST_SYSROOT", sysroot);
+        cargo.env("MIRI_HOST_SYSROOT", &sysroot);
         cargo.env("MIRI", &miri);
         if builder.config.locked_deps {
             // enforce lockfiles
@@ -1646,8 +1645,10 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
         }
 
         if suite == "debuginfo" {
-            builder
-                .ensure(dist::DebuggerScripts { sysroot: builder.sysroot(compiler), host: target });
+            builder.ensure(dist::DebuggerScripts {
+                sysroot: builder.sysroot(compiler).to_path_buf(),
+                host: target,
+            });
         }
 
         // Also provide `rust_test_helpers` for the host.
@@ -1656,8 +1657,8 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
         // ensure that `libproc_macro` is available on the host.
         builder.ensure(compile::Std::new(compiler, compiler.host));
 
-        // As well as the target, except for plain wasm32, which can't build it
-        if suite != "mir-opt" && !target.contains("wasm") && !target.contains("emscripten") {
+        // As well as the target
+        if suite != "mir-opt" {
             builder.ensure(TestHelpers { target });
         }
 
@@ -1970,6 +1971,8 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
 
         if builder.remote_tested(target) {
             cmd.arg("--remote-test-client").arg(builder.tool_exe(Tool::RemoteTestClient));
+        } else if let Some(tool) = builder.runner(target) {
+            cmd.arg("--runner").arg(tool);
         }
 
         if suite != "mir-opt" {
@@ -2378,7 +2381,7 @@ impl Step for RustcGuide {
 pub struct CrateLibrustc {
     compiler: Compiler,
     target: TargetSelection,
-    crates: Vec<Interned<String>>,
+    crates: Vec<String>,
 }
 
 impl Step for CrateLibrustc {
@@ -2394,8 +2397,11 @@ impl Step for CrateLibrustc {
         let builder = run.builder;
         let host = run.build_triple();
         let compiler = builder.compiler_for(builder.top_stage, host, host);
-        let crates =
-            run.paths.iter().map(|p| builder.crate_paths[&p.assert_single_path().path]).collect();
+        let crates = run
+            .paths
+            .iter()
+            .map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
+            .collect();
 
         builder.ensure(CrateLibrustc { compiler, target: run.target, crates });
     }
@@ -2418,7 +2424,7 @@ impl Step for CrateLibrustc {
 fn run_cargo_test<'a>(
     cargo: impl Into<Command>,
     libtest_args: &[&str],
-    crates: &[Interned<String>],
+    crates: &[String],
     primary_crate: &str,
     description: impl Into<Option<&'a str>>,
     compiler: Compiler,
@@ -2449,7 +2455,7 @@ fn run_cargo_test<'a>(
 fn prepare_cargo_test(
     cargo: impl Into<Command>,
     libtest_args: &[&str],
-    crates: &[Interned<String>],
+    crates: &[String],
     primary_crate: &str,
     compiler: Compiler,
     target: TargetSelection,
@@ -2477,7 +2483,7 @@ fn prepare_cargo_test(
         DocTests::No => {
             let krate = &builder
                 .crates
-                .get(&INTERNER.intern_str(primary_crate))
+                .get(primary_crate)
                 .unwrap_or_else(|| panic!("missing crate {primary_crate}"));
             if krate.has_lib {
                 cargo.arg("--lib");
@@ -2487,7 +2493,7 @@ fn prepare_cargo_test(
         DocTests::Yes => {}
     }
 
-    for &krate in crates {
+    for krate in crates {
         cargo.arg("-p").arg(krate);
     }
 
@@ -2505,20 +2511,13 @@ fn prepare_cargo_test(
     dylib_path.insert(0, PathBuf::from(&*builder.sysroot_libdir(compiler, target)));
     cargo.env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
 
-    if target.contains("emscripten") {
-        cargo.env(
-            format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
-            builder.config.nodejs.as_ref().expect("nodejs not configured"),
-        );
-    } else if target.starts_with("wasm32") {
-        let node = builder.config.nodejs.as_ref().expect("nodejs not configured");
-        let runner = format!("{} {}/src/etc/wasm32-shim.js", node.display(), builder.src.display());
-        cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), &runner);
-    } else if builder.remote_tested(target) {
+    if builder.remote_tested(target) {
         cargo.env(
             format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)),
             format!("{} run 0", builder.tool_exe(Tool::RemoteTestClient).display()),
         );
+    } else if let Some(tool) = builder.runner(target) {
+        cargo.env(format!("CARGO_TARGET_{}_RUNNER", envify(&target.triple)), tool);
     }
 
     cargo
@@ -2529,7 +2528,7 @@ pub struct Crate {
     pub compiler: Compiler,
     pub target: TargetSelection,
     pub mode: Mode,
-    pub crates: Vec<Interned<String>>,
+    pub crates: Vec<String>,
 }
 
 impl Step for Crate {
@@ -2544,8 +2543,11 @@ impl Step for Crate {
         let builder = run.builder;
         let host = run.build_triple();
         let compiler = builder.compiler_for(builder.top_stage, host, host);
-        let crates =
-            run.paths.iter().map(|p| builder.crate_paths[&p.assert_single_path().path]).collect();
+        let crates = run
+            .paths
+            .iter()
+            .map(|p| builder.crate_paths[&p.assert_single_path().path].clone())
+            .collect();
 
         builder.ensure(Crate { compiler, target: run.target, mode: Mode::Std, crates });
     }
@@ -2707,7 +2709,7 @@ impl Step for CrateRustdoc {
         run_cargo_test(
             cargo,
             &[],
-            &[INTERNER.intern_str("rustdoc:0.0.0")],
+            &["rustdoc:0.0.0".to_string()],
             "rustdoc",
             "rustdoc",
             compiler,
@@ -2768,7 +2770,7 @@ impl Step for CrateRustdocJsonTypes {
         run_cargo_test(
             cargo,
             libtest_args,
-            &[INTERNER.intern_str("rustdoc-json-types")],
+            &["rustdoc-json-types".to_string()],
             "rustdoc-json-types",
             "rustdoc-json-types",
             compiler,
@@ -3194,8 +3196,7 @@ impl Step for CodegenCranelift {
             return;
         }
 
-        if !builder.config.codegen_backends(run.target).contains(&INTERNER.intern_str("cranelift"))
-        {
+        if !builder.config.codegen_backends(run.target).contains(&"cranelift".to_owned()) {
             builder.info("cranelift not in rust.codegen-backends. skipping");
             return;
         }
@@ -3319,7 +3320,7 @@ impl Step for CodegenGCC {
             return;
         }
 
-        if !builder.config.codegen_backends(run.target).contains(&INTERNER.intern_str("gcc")) {
+        if !builder.config.codegen_backends(run.target).contains(&"gcc".to_owned()) {
             builder.info("gcc not in rust.codegen-backends. skipping");
             return;
         }
@@ -3394,7 +3395,6 @@ impl Step for CodegenGCC {
             .arg("--out-dir")
             .arg(builder.stage_out(compiler, Mode::ToolRustc).join("cg_gcc"))
             .arg("--release")
-            .arg("--no-default-features")
             .arg("--mini-tests")
             .arg("--std-tests");
         cargo.args(builder.config.test_args());
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 889876f461d..53dc1cff0ae 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -795,6 +795,7 @@ tool_extended!((self, builder),
     Rls, "src/tools/rls", "rls", stable=true, tool_std=true;
     RustDemangler, "src/tools/rust-demangler", "rust-demangler", stable=false, tool_std=true;
     Rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, add_bins_to_sysroot = ["rustfmt", "cargo-fmt"];
+    LlvmBitcodeLinker, "src/tools/llvm-bitcode-linker", "llvm-bitcode-linker", stable=false, add_bins_to_sysroot = ["llvm-bitcode-linker"];
 );
 
 impl<'a> Builder<'a> {
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index 8223a80c931..5e5d6d024ee 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -19,7 +19,7 @@ use crate::core::build_steps::{check, clean, compile, dist, doc, install, run, s
 use crate::core::config::flags::{Color, Subcommand};
 use crate::core::config::{DryRun, SplitDebuginfo, TargetSelection};
 use crate::prepare_behaviour_dump_dir;
-use crate::utils::cache::{Cache, Interned, INTERNER};
+use crate::utils::cache::Cache;
 use crate::utils::helpers::{self, add_dylib_path, add_link_lib_path, exe, linker_args};
 use crate::utils::helpers::{check_cfg_arg, libdir, linker_flags, output, t, LldThreads};
 use crate::EXTRA_CHECK_CFGS;
@@ -102,7 +102,7 @@ impl RunConfig<'_> {
 
     /// Return a list of crate names selected by `run.paths`.
     #[track_caller]
-    pub fn cargo_crates_in_set(&self) -> Interned<Vec<String>> {
+    pub fn cargo_crates_in_set(&self) -> Vec<String> {
         let mut crates = Vec::new();
         for krate in &self.paths {
             let path = krate.assert_single_path();
@@ -111,7 +111,7 @@ impl RunConfig<'_> {
             };
             crates.push(crate_name.to_string());
         }
-        INTERNER.intern_list(crates)
+        crates
     }
 
     /// Given an `alias` selected by the `Step` and the paths passed on the command line,
@@ -120,7 +120,7 @@ impl RunConfig<'_> {
     /// Normally, people will pass *just* `library` if they pass it.
     /// But it's possible (although strange) to pass something like `library std core`.
     /// Build all crates anyway, as if they hadn't passed the other args.
-    pub fn make_run_crates(&self, alias: Alias) -> Interned<Vec<String>> {
+    pub fn make_run_crates(&self, alias: Alias) -> Vec<String> {
         let has_alias =
             self.paths.iter().any(|set| set.assert_single_path().path.ends_with(alias.as_str()));
         if !has_alias {
@@ -133,7 +133,7 @@ impl RunConfig<'_> {
         };
 
         let crate_names = crates.into_iter().map(|krate| krate.name.to_string()).collect();
-        INTERNER.intern_list(crate_names)
+        crate_names
     }
 }
 
@@ -763,6 +763,7 @@ impl<'a> Builder<'a> {
                 tool::RustdocGUITest,
                 tool::OptimizedDist,
                 tool::CoverageDump,
+                tool::LlvmBitcodeLinker
             ),
             Kind::Check | Kind::Clippy | Kind::Fix => describe!(
                 check::Std,
@@ -1062,26 +1063,26 @@ impl<'a> Builder<'a> {
         }
     }
 
-    pub fn sysroot(&self, compiler: Compiler) -> Interned<PathBuf> {
+    pub fn sysroot(&self, compiler: Compiler) -> PathBuf {
         self.ensure(compile::Sysroot::new(compiler))
     }
 
     /// Returns the libdir where the standard library and other artifacts are
     /// found for a compiler's sysroot.
-    pub fn sysroot_libdir(&self, compiler: Compiler, target: TargetSelection) -> Interned<PathBuf> {
+    pub fn sysroot_libdir(&self, compiler: Compiler, target: TargetSelection) -> PathBuf {
         #[derive(Debug, Clone, Hash, PartialEq, Eq)]
         struct Libdir {
             compiler: Compiler,
             target: TargetSelection,
         }
         impl Step for Libdir {
-            type Output = Interned<PathBuf>;
+            type Output = PathBuf;
 
             fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
                 run.never()
             }
 
-            fn run(self, builder: &Builder<'_>) -> Interned<PathBuf> {
+            fn run(self, builder: &Builder<'_>) -> PathBuf {
                 let lib = builder.sysroot_libdir_relative(self.compiler);
                 let sysroot = builder
                     .sysroot(self.compiler)
@@ -1110,7 +1111,7 @@ impl<'a> Builder<'a> {
                     );
                 }
 
-                INTERNER.intern_path(sysroot)
+                sysroot
             }
         }
         self.ensure(Libdir { compiler, target })
diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index 2cbebbcf4e2..6a1dde51603 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -608,7 +608,7 @@ mod dist {
                 compiler: Compiler { host, stage: 0 },
                 target: host,
                 mode: Mode::Std,
-                crates: vec![INTERNER.intern_str("std")],
+                crates: vec!["std".to_owned()],
             },]
         );
     }
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 47b13c26711..ae5169e9383 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -236,6 +236,7 @@ pub struct Config {
     pub lld_mode: LldMode,
     pub lld_enabled: bool,
     pub llvm_tools_enabled: bool,
+    pub llvm_bitcode_linker_enabled: bool,
 
     pub llvm_cflags: Option<String>,
     pub llvm_cxxflags: Option<String>,
@@ -264,7 +265,7 @@ pub struct Config {
     pub rustc_default_linker: Option<String>,
     pub rust_optimize_tests: bool,
     pub rust_dist_src: bool,
-    pub rust_codegen_backends: Vec<Interned<String>>,
+    pub rust_codegen_backends: Vec<String>,
     pub rust_verify_llvm_ir: bool,
     pub rust_thin_lto_import_instr_limit: Option<u32>,
     pub rust_remap_debuginfo: bool,
@@ -458,6 +459,8 @@ impl std::str::FromStr for RustcLto {
 }
 
 #[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
+// N.B.: This type is used everywhere, and the entire codebase relies on it being Copy.
+// Making !Copy is highly nontrivial!
 pub struct TargetSelection {
     pub triple: Interned<String>,
     file: Option<Interned<String>>,
@@ -579,8 +582,9 @@ pub struct Target {
     pub musl_libdir: Option<PathBuf>,
     pub wasi_root: Option<PathBuf>,
     pub qemu_rootfs: Option<PathBuf>,
+    pub runner: Option<String>,
     pub no_std: bool,
-    pub codegen_backends: Option<Vec<Interned<String>>>,
+    pub codegen_backends: Option<Vec<String>>,
 }
 
 impl Target {
@@ -1096,6 +1100,7 @@ define_config! {
         dist_src: Option<bool> = "dist-src",
         save_toolstates: Option<String> = "save-toolstates",
         codegen_backends: Option<Vec<String>> = "codegen-backends",
+        llvm_bitcode_linker: Option<bool> = "llvm-bitcode-linker",
         lld: Option<bool> = "lld",
         lld_mode: Option<LldMode> = "use-lld",
         llvm_tools: Option<bool> = "llvm-tools",
@@ -1142,6 +1147,7 @@ define_config! {
         qemu_rootfs: Option<String> = "qemu-rootfs",
         no_std: Option<bool> = "no-std",
         codegen_backends: Option<Vec<String>> = "codegen-backends",
+        runner: Option<String> = "runner",
     }
 }
 
@@ -1163,7 +1169,7 @@ impl Config {
             channel: "dev".to_string(),
             codegen_tests: true,
             rust_dist_src: true,
-            rust_codegen_backends: vec![INTERNER.intern_str("llvm")],
+            rust_codegen_backends: vec!["llvm".to_owned()],
             deny_warnings: true,
             bindir: "bin".into(),
             dist_include_mingw_linker: true,
@@ -1567,6 +1573,7 @@ impl Config {
                 codegen_backends,
                 lld,
                 llvm_tools,
+                llvm_bitcode_linker,
                 deny_warnings,
                 backtrace_on_ice,
                 verify_llvm_ir,
@@ -1646,6 +1653,7 @@ impl Config {
             }
             set(&mut config.lld_mode, lld_mode);
             set(&mut config.lld_enabled, lld);
+            set(&mut config.llvm_bitcode_linker_enabled, llvm_bitcode_linker);
 
             if matches!(config.lld_mode, LldMode::SelfContained)
                 && !config.lld_enabled
@@ -1693,7 +1701,7 @@ impl Config {
                         }
                     }
 
-                    INTERNER.intern_str(s)
+                    s.clone()
                 }).collect();
             }
 
@@ -1862,6 +1870,7 @@ impl Config {
                 target.musl_libdir = cfg.musl_libdir.map(PathBuf::from);
                 target.wasi_root = cfg.wasi_root.map(PathBuf::from);
                 target.qemu_rootfs = cfg.qemu_rootfs.map(PathBuf::from);
+                target.runner = cfg.runner;
                 target.sanitizers = cfg.sanitizers;
                 target.profiler = cfg.profiler;
                 target.rpath = cfg.rpath;
@@ -1880,7 +1889,7 @@ impl Config {
                             }
                         }
 
-                        INTERNER.intern_str(s)
+                        s.clone()
                     }).collect());
                 }
 
@@ -2267,7 +2276,7 @@ impl Config {
     }
 
     pub fn llvm_enabled(&self, target: TargetSelection) -> bool {
-        self.codegen_backends(target).contains(&INTERNER.intern_str("llvm"))
+        self.codegen_backends(target).contains(&"llvm".to_owned())
     }
 
     pub fn llvm_libunwind(&self, target: TargetSelection) -> LlvmLibunwind {
@@ -2286,14 +2295,14 @@ impl Config {
         self.submodules.unwrap_or(rust_info.is_managed_git_subrepository())
     }
 
-    pub fn codegen_backends(&self, target: TargetSelection) -> &[Interned<String>] {
+    pub fn codegen_backends(&self, target: TargetSelection) -> &[String] {
         self.target_config
             .get(&target)
             .and_then(|cfg| cfg.codegen_backends.as_deref())
             .unwrap_or(&self.rust_codegen_backends)
     }
 
-    pub fn default_codegen_backend(&self, target: TargetSelection) -> Option<Interned<String>> {
+    pub fn default_codegen_backend(&self, target: TargetSelection) -> Option<String> {
         self.codegen_backends(target).first().cloned()
     }
 
diff --git a/src/bootstrap/src/core/metadata.rs b/src/bootstrap/src/core/metadata.rs
index 5802082326a..08a96407a69 100644
--- a/src/bootstrap/src/core/metadata.rs
+++ b/src/bootstrap/src/core/metadata.rs
@@ -3,7 +3,6 @@ use std::process::Command;
 
 use serde_derive::Deserialize;
 
-use crate::utils::cache::INTERNER;
 use crate::utils::helpers::output;
 use crate::{t, Build, Crate};
 
@@ -43,19 +42,19 @@ struct Target {
 pub fn build(build: &mut Build) {
     for package in workspace_members(build) {
         if package.source.is_none() {
-            let name = INTERNER.intern_string(package.name);
+            let name = package.name;
             let mut path = PathBuf::from(package.manifest_path);
             path.pop();
             let deps = package
                 .dependencies
                 .into_iter()
                 .filter(|dep| dep.source.is_none())
-                .map(|dep| INTERNER.intern_string(dep.name))
+                .map(|dep| dep.name)
                 .collect();
             let has_lib = package.targets.iter().any(|t| t.kind.iter().any(|k| k == "lib"));
-            let krate = Crate { name, deps, path, has_lib };
+            let krate = Crate { name: name.clone(), deps, path, has_lib };
             let relative_path = krate.local_path(build);
-            build.crates.insert(name, krate);
+            build.crates.insert(name.clone(), krate);
             let existing_path = build.crate_paths.insert(relative_path, name);
             assert!(
                 existing_path.is_none(),
diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs
index 1dce8d8ac71..e03b1e17908 100644
--- a/src/bootstrap/src/core/sanity.rs
+++ b/src/bootstrap/src/core/sanity.rs
@@ -15,6 +15,7 @@ use std::fs;
 use std::path::PathBuf;
 use std::process::Command;
 
+use crate::builder::Kind;
 use crate::core::config::Target;
 use crate::utils::helpers::output;
 use crate::Build;
@@ -64,6 +65,8 @@ pub fn check(build: &mut Build) {
     let mut skip_target_sanity =
         env::var_os("BOOTSTRAP_SKIP_TARGET_SANITY").is_some_and(|s| s == "1" || s == "true");
 
+    skip_target_sanity |= build.config.cmd.kind() == Kind::Check;
+
     // Skip target sanity checks when we are doing anything with mir-opt tests or Miri
     let skipped_paths = [OsStr::new("mir-opt"), OsStr::new("miri")];
     skip_target_sanity |= build.config.paths.iter().any(|path| {
@@ -169,11 +172,8 @@ than building it.
             continue;
         }
 
-        // Some environments don't want or need these tools, such as when testing Miri.
-        // FIXME: it would be better to refactor this code to split necessary setup from pure sanity
-        // checks, and have a regular flag for skipping the latter. Also see
-        // <https://github.com/rust-lang/rust/pull/103569#discussion_r1008741742>.
-        if skip_target_sanity {
+        // skip check for cross-targets
+        if skip_target_sanity && target != &build.build {
             continue;
         }
 
@@ -215,11 +215,8 @@ than building it.
             panic!("All the *-none-* and nvptx* targets are no-std targets")
         }
 
-        // Some environments don't want or need these tools, such as when testing Miri.
-        // FIXME: it would be better to refactor this code to split necessary setup from pure sanity
-        // checks, and have a regular flag for skipping the latter. Also see
-        // <https://github.com/rust-lang/rust/pull/103569#discussion_r1008741742>.
-        if skip_target_sanity {
+        // skip check for cross-targets
+        if skip_target_sanity && target != &build.build {
             continue;
         }
 
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index ab8f3c0d9e4..9cbd4d367f0 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -41,7 +41,6 @@ use crate::core::builder::Kind;
 use crate::core::config::{flags, LldMode};
 use crate::core::config::{DryRun, Target};
 use crate::core::config::{LlvmLibunwind, TargetSelection};
-use crate::utils::cache::{Interned, INTERNER};
 use crate::utils::exec::{BehaviorOnFailure, BootstrapCommand, OutputMode};
 use crate::utils::helpers::{self, dir_is_empty, exe, libdir, mtime, output, symlink_dir};
 
@@ -65,6 +64,7 @@ const LLVM_TOOLS: &[&str] = &[
     "llvm-ar",       // used for creating and modifying archive files
     "llvm-as",       // used to convert LLVM assembly to LLVM bitcode
     "llvm-dis",      // used to disassemble LLVM bitcode
+    "llvm-link",     // Used to link LLVM bitcode
     "llc",           // used to compile LLVM bytecode
     "opt",           // used to optimize LLVM bytecode
 ];
@@ -172,9 +172,11 @@ pub struct Build {
     doc_tests: DocTests,
     verbosity: usize,
 
-    // Targets for which to build
+    /// Build triple for the pre-compiled snapshot compiler.
     build: TargetSelection,
+    /// Which triples to produce a compiler toolchain for.
     hosts: Vec<TargetSelection>,
+    /// Which triples to build libraries (core/alloc/std/test/proc_macro) for.
     targets: Vec<TargetSelection>,
 
     initial_rustc: PathBuf,
@@ -191,8 +193,8 @@ pub struct Build {
     ranlib: RefCell<HashMap<TargetSelection, PathBuf>>,
     // Miscellaneous
     // allow bidirectional lookups: both name -> path and path -> name
-    crates: HashMap<Interned<String>, Crate>,
-    crate_paths: HashMap<PathBuf, Interned<String>>,
+    crates: HashMap<String, Crate>,
+    crate_paths: HashMap<PathBuf, String>,
     is_sudo: bool,
     ci_env: CiEnv,
     delayed_failures: RefCell<Vec<String>>,
@@ -204,8 +206,8 @@ pub struct Build {
 
 #[derive(Debug, Clone)]
 struct Crate {
-    name: Interned<String>,
-    deps: HashSet<Interned<String>>,
+    name: String,
+    deps: HashSet<String>,
     path: PathBuf,
     has_lib: bool,
 }
@@ -829,8 +831,8 @@ impl Build {
     }
 
     /// Output directory for some generated md crate documentation for a target (temporary)
-    fn md_doc_out(&self, target: TargetSelection) -> Interned<PathBuf> {
-        INTERNER.intern_path(self.out.join(&*target.triple).join("md-doc"))
+    fn md_doc_out(&self, target: TargetSelection) -> PathBuf {
+        self.out.join(&*target.triple).join("md-doc")
     }
 
     /// Returns `true` if this is an external version of LLVM not managed by bootstrap.
@@ -1353,6 +1355,44 @@ impl Build {
             || env::var_os("TEST_DEVICE_ADDR").is_some()
     }
 
+    /// Returns an optional "runner" to pass to `compiletest` when executing
+    /// test binaries.
+    ///
+    /// An example of this would be a WebAssembly runtime when testing the wasm
+    /// targets.
+    fn runner(&self, target: TargetSelection) -> Option<String> {
+        let configured_runner =
+            self.config.target_config.get(&target).and_then(|t| t.runner.as_ref()).map(|p| &**p);
+        if let Some(runner) = configured_runner {
+            return Some(runner.to_owned());
+        }
+
+        if target.starts_with("wasm") && target.contains("wasi") {
+            self.default_wasi_runner()
+        } else {
+            None
+        }
+    }
+
+    /// When a `runner` configuration is not provided and a WASI-looking target
+    /// is being tested this is consulted to prove the environment to see if
+    /// there's a runtime already lying around that seems reasonable to use.
+    fn default_wasi_runner(&self) -> Option<String> {
+        let mut finder = crate::core::sanity::Finder::new();
+
+        // Look for Wasmtime, and for its default options be sure to disable
+        // its caching system since we're executing quite a lot of tests and
+        // ideally shouldn't pollute the cache too much.
+        if let Some(path) = finder.maybe_have("wasmtime") {
+            if let Ok(mut path) = path.into_os_string().into_string() {
+                path.push_str(" run -C cache=n --dir .");
+                return Some(path);
+            }
+        }
+
+        None
+    }
+
     /// Returns the root of the "rootfs" image that this target will be using,
     /// if one was configured.
     ///
@@ -1538,7 +1578,7 @@ impl Build {
     /// "local" crates (those in the local source tree, not from a registry).
     fn in_tree_crates(&self, root: &str, target: Option<TargetSelection>) -> Vec<&Crate> {
         let mut ret = Vec::new();
-        let mut list = vec![INTERNER.intern_str(root)];
+        let mut list = vec![root.to_owned()];
         let mut visited = HashSet::new();
         while let Some(krate) = list.pop() {
             let krate = self
@@ -1564,11 +1604,11 @@ impl Build {
                     && (dep != "rustc_codegen_llvm"
                         || self.config.hosts.iter().any(|host| self.config.llvm_enabled(*host)))
                 {
-                    list.push(*dep);
+                    list.push(dep.clone());
                 }
             }
         }
-        ret.sort_unstable_by_key(|krate| krate.name); // reproducible order needed for tests
+        ret.sort_unstable_by_key(|krate| krate.name.clone()); // reproducible order needed for tests
         ret
     }
 
diff --git a/src/bootstrap/src/utils/cache.rs b/src/bootstrap/src/utils/cache.rs
index 2b86585a9d3..e18dcbb47be 100644
--- a/src/bootstrap/src/utils/cache.rs
+++ b/src/bootstrap/src/utils/cache.rs
@@ -194,17 +194,6 @@ impl Interner {
     pub fn intern_str(&self, s: &str) -> Interned<String> {
         self.strs.lock().unwrap().intern_borrow(s)
     }
-    pub fn intern_string(&self, s: String) -> Interned<String> {
-        self.strs.lock().unwrap().intern(s)
-    }
-
-    pub fn intern_path(&self, s: PathBuf) -> Interned<PathBuf> {
-        self.paths.lock().unwrap().intern(s)
-    }
-
-    pub fn intern_list(&self, v: Vec<String>) -> Interned<Vec<String>> {
-        self.lists.lock().unwrap().intern(v)
-    }
 }
 
 pub static INTERNER: Lazy<Interner> = Lazy::new(Interner::default);
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index d166b84e51f..85dfe45111f 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -141,4 +141,14 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Info,
         summary: "A new `boostrap-cache-path` option has been introduced which can be utilized to modify the cache path for bootstrap.",
     },
+    ChangeInfo {
+        change_id: 122108,
+        severity: ChangeSeverity::Info,
+        summary: "a new `target.*.runner` option is available to specify a wrapper executable required to run tests for a target",
+    },
+    ChangeInfo {
+        change_id: 117458,
+        severity: ChangeSeverity::Info,
+        summary: "New option `rust.llvm-bitcode-linker` that will build the llvm-bitcode-linker.",
+    },
 ];
diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
index e90141bb9a9..abd109a6ea3 100644
--- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
@@ -135,7 +135,7 @@ ENV TARGETS=$TARGETS,x86_64-unknown-uefi
 # Luckily one of the folders is /usr/local/include so symlink /usr/include/x86_64-linux-gnu/asm there
 RUN ln -s /usr/include/x86_64-linux-gnu/asm /usr/local/include/asm
 
-ENV RUST_CONFIGURE_ARGS --enable-extended --enable-lld --disable-docs \
+ENV RUST_CONFIGURE_ARGS --enable-extended --enable-lld --enable-llvm-bitcode-linker --disable-docs \
   --set target.wasm32-wasi.wasi-root=/wasm32-wasip1 \
   --set target.wasm32-wasip1.wasi-root=/wasm32-wasip1 \
   --set target.wasm32-wasi-preview1-threads.wasi-root=/wasm32-wasi-preview1-threads \
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gccjit.sh b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gccjit.sh
new file mode 100644
index 00000000000..324dd5fac16
--- /dev/null
+++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/build-gccjit.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+set -ex
+
+cd $1
+
+# Setting up folders for GCC
+git clone https://github.com/antoyo/gcc gcc-src
+cd gcc-src
+# This commit hash needs to be updated to use a more recent gcc fork version.
+git checkout 78dc50f0e50e6cd1433149520bd512a4e0eaa1bc
+
+mkdir ../gcc-build ../gcc-install
+cd ../gcc-build
+
+# Building GCC.
+../gcc-src/configure \
+    --enable-host-shared \
+    --enable-languages=jit \
+    --enable-checking=release \
+    --disable-bootstrap \
+    --disable-multilib \
+    --prefix=$(pwd)/../gcc-install
+make
+make install
+
+rm -rf ../gcc-src
+ln -s /scripts/gcc-install/lib/libgccjit.so /usr/lib/x86_64-linux-gnu/libgccjit.so
+ln -s /scripts/gcc-install/lib/libgccjit.so /usr/lib/x86_64-linux-gnu/libgccjit.so.0
diff --git a/src/ci/docker/host-x86_64/test-various/Dockerfile b/src/ci/docker/host-x86_64/test-various/Dockerfile
index 3fcf12dd9f2..944d9aed319 100644
--- a/src/ci/docker/host-x86_64/test-various/Dockerfile
+++ b/src/ci/docker/host-x86_64/test-various/Dockerfile
@@ -3,6 +3,7 @@ FROM ubuntu:22.04
 ARG DEBIAN_FRONTEND=noninteractive
 RUN apt-get update && apt-get install -y --no-install-recommends \
   clang-11 \
+  llvm-11 \
   g++ \
   make \
   ninja-build \
@@ -38,10 +39,14 @@ WORKDIR /
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
+COPY host-x86_64/dist-various-2/build-wasi-toolchain.sh /tmp/
+RUN /tmp/build-wasi-toolchain.sh
+
 ENV RUST_CONFIGURE_ARGS \
   --musl-root-x86_64=/usr/local/x86_64-linux-musl \
   --set build.nodejs=/node-v18.12.0-linux-x64/bin/node \
-  --set rust.lld
+  --set rust.lld \
+  --set target.wasm32-wasip1.wasi-root=/wasm32-wasip1
 
 # Some run-make tests have assertions about code size, and enabling debug
 # assertions in libstd causes the binary to be much bigger than it would
@@ -50,7 +55,11 @@ ENV RUST_CONFIGURE_ARGS \
 ENV NO_DEBUG_ASSERTIONS=1
 ENV NO_OVERFLOW_CHECKS=1
 
-ENV WASM_TARGETS=wasm32-unknown-unknown
+RUN curl -L https://github.com/bytecodealliance/wasmtime/releases/download/v18.0.2/wasmtime-v18.0.2-x86_64-linux.tar.xz | \
+  tar -xJ
+ENV PATH "$PATH:/wasmtime-v18.0.2-x86_64-linux"
+
+ENV WASM_TARGETS=wasm32-wasip1
 ENV WASM_SCRIPT python3 /checkout/x.py --stage 2 test --host='' --target $WASM_TARGETS \
   tests/run-make \
   tests/ui \
@@ -59,7 +68,9 @@ ENV WASM_SCRIPT python3 /checkout/x.py --stage 2 test --host='' --target $WASM_T
   tests/codegen \
   tests/assembly \
   library/core
-ENV CC_wasm32_unknown_unknown=clang-11
+ENV CC_wasm32_wasip1=clang-11 \
+    CFLAGS_wasm32_wasip1="--sysroot /wasm32-wasip1" \
+    AR_wasm32_wasip1=llvm-ar-11
 
 ENV NVPTX_TARGETS=nvptx64-nvidia-cuda
 ENV NVPTX_SCRIPT python3 /checkout/x.py --stage 2 test --host='' --target $NVPTX_TARGETS \
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile
index f4850715e82..6540a500d3a 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-16/Dockerfile
@@ -24,7 +24,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   xz-utils \
   nodejs \
   mingw-w64 \
-  libgccjit-12-dev \
+  # libgccjit dependencies
+  flex \
+  libmpfr-dev \
+  libgmp-dev \
+  libmpc3 \
+  libmpc-dev \
   && rm -rf /var/lib/apt/lists/*
 
 # Note: libgccjit needs to match the default gcc version for the linker to find it.
@@ -54,4 +59,8 @@ ENV RUST_CONFIGURE_ARGS \
 
 COPY host-x86_64/x86_64-gnu-llvm-16/script.sh /tmp/
 
+COPY host-x86_64/dist-x86_64-linux/build-gccjit.sh /scripts/
+
+RUN sh /scripts/build-gccjit.sh /scripts
+
 ENV SCRIPT /tmp/script.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile
index 1eedfe3f09b..ed4e1978c5d 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile
@@ -24,11 +24,14 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   xz-utils \
   nodejs \
   mingw-w64 \
-  libgccjit-13-dev \
+  # libgccjit dependencies
+  flex \
+  libmpfr-dev \
+  libgmp-dev \
+  libmpc3 \
+  libmpc-dev \
   && rm -rf /var/lib/apt/lists/*
 
-# Note: libgccjit needs to match the default gcc version for the linker to find it.
-
 # Install powershell (universal package) so we can test x.ps1 on Linux
 RUN curl -sL "https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/powershell_7.3.1-1.deb_amd64.deb" > powershell.deb && \
     dpkg -i powershell.deb && \
@@ -55,4 +58,8 @@ ENV RUST_CONFIGURE_ARGS \
 
 COPY host-x86_64/x86_64-gnu-llvm-16/script.sh /tmp/
 
+COPY host-x86_64/dist-x86_64-linux/build-gccjit.sh /scripts/
+
+RUN sh /scripts/build-gccjit.sh /scripts
+
 ENV SCRIPT /tmp/script.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
index 82385ea15b7..a03577b4511 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
@@ -15,7 +15,6 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   sudo \
   xz-utils \
   tidy \
-  libgccjit-12-dev \
   \
 # Install dependencies for chromium browser
   gconf-service \
@@ -57,13 +56,17 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   lsb-release \
   xdg-utils \
   wget \
+  # libgccjit dependencies
+  flex \
+  libmpfr-dev \
+  libgmp-dev \
+  libmpc3 \
+  libmpc-dev \
   && rm -rf /var/lib/apt/lists/*
 
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-# Make `libgccjit.so` accessible.
-RUN ln -s /usr/lib/gcc/x86_64-linux-gnu/12/libgccjit.so /usr/lib/x86_64-linux-gnu/libgccjit.so
 # Fix rustc_codegen_gcc lto issues.
 ENV GCC_EXEC_PREFIX="/usr/lib/gcc/"
 
@@ -92,6 +95,10 @@ ENV RUST_CONFIGURE_ARGS \
 
 ENV HOST_TARGET x86_64-unknown-linux-gnu
 
+COPY host-x86_64/dist-x86_64-linux/build-gccjit.sh /scripts/
+
+RUN sh /scripts/build-gccjit.sh /scripts
+
 ENV SCRIPT /tmp/checktools.sh ../x.py && \
   NODE_PATH=`npm root -g` python3 ../x.py test tests/rustdoc-gui --stage 2 \
     --test-args "'--no-sandbox --jobs 1'"
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index c392ccec3dc..bc81b1e04a7 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -540,7 +540,7 @@ jobs:
           - name: dist-x86_64-apple
             env:
               SCRIPT: ./x.py dist bootstrap --include-default-paths --host=x86_64-apple-darwin --target=x86_64-apple-darwin
-              RUST_CONFIGURE_ARGS: --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set rust.lto=thin
+              RUST_CONFIGURE_ARGS: --enable-full-tools --enable-sanitizers --enable-profiler --set rust.jemalloc --set rust.lto=thin --set rust.codegen-units=1
               RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
               MACOSX_DEPLOYMENT_TARGET: 10.12
               SELECT_XCODE: /Applications/Xcode_14.3.1.app
@@ -692,6 +692,7 @@ jobs:
                 --target=x86_64-pc-windows-msvc
                 --enable-full-tools
                 --enable-profiler
+                --set rust.codegen-units=1
               SCRIPT: python x.py build --set rust.debug=true opt-dist && PGO_HOST=x86_64-pc-windows-msvc ./build/x86_64-pc-windows-msvc/stage0-tools-bin/opt-dist windows-ci -- python x.py dist bootstrap --include-default-paths
               DIST_REQUIRE_ALL_TOOLS: 1
             <<: *job-windows-8c
diff --git a/src/ci/scripts/install-msys2.sh b/src/ci/scripts/install-msys2.sh
index 905edf38a09..e3f76744cbe 100755
--- a/src/ci/scripts/install-msys2.sh
+++ b/src/ci/scripts/install-msys2.sh
@@ -31,12 +31,14 @@ if isWindows; then
     # Delete these pre-installed tools so we can't accidentally use them, because we are using the
     # MSYS2 setup action versions instead.
     # Delete pre-installed version of MSYS2
+    echo "Cleaning up tools in PATH"
     rm -r "/c/msys64/"
     # Delete Strawberry Perl, which contains a version of mingw
     rm -r "/c/Strawberry/"
     # Delete these other copies of mingw, I don't even know where they come from.
     rm -r "/c/mingw64/"
     rm -r "/c/mingw32/"
+    echo "Finished cleaning up tools in PATH"
 
     if isKnownToBeMingwBuild; then
         # Use the mingw version of CMake for mingw builds.
@@ -46,11 +48,11 @@ if isWindows; then
         # Install mingw-w64-$arch-cmake
         pacboy -S --noconfirm cmake:p
 
-        # We use Git-for-Windows for MSVC builds, and MSYS2 Git for mingw builds,
-        # so that both are tested.
-        # Delete Windows-Git
-        rm -r "/c/Program Files/Git/"
-        # Install MSYS2 git
-        pacman -S --noconfirm git
+        # It would be nice to use MSYS's git in MinGW builds so that it's tested and known to
+        # work. But it makes everything extremely slow, so it's commented out for now.
+        # # Delete Windows-Git
+        # rm -r "/c/Program Files/Git/"
+        # # Install MSYS2 git
+        # pacman -S --noconfirm git
     fi
 fi
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 308e3235370..537a724579e 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -165,7 +165,6 @@ target | std | notes
 `i686-unknown-freebsd` | ✓ | 32-bit FreeBSD [^x86_32-floats-return-ABI]
 `i686-unknown-linux-musl` | ✓ | 32-bit Linux with musl 1.2.3 [^x86_32-floats-return-ABI]
 [`i686-unknown-uefi`](platform-support/unknown-uefi.md) | * | 32-bit UEFI
-[`loongarch64-unknown-linux-musl`](platform-support/loongarch-linux.md) | ? |  | LoongArch64 Linux (LP64D ABI) with musl 1.2.3
 [`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * |  | LoongArch64 Bare-metal (LP64D ABI)
 [`loongarch64-unknown-none-softfloat`](platform-support/loongarch-none.md) | * |  | LoongArch64 Bare-metal (LP64S ABI)
 [`nvptx64-nvidia-cuda`](platform-support/nvptx64-nvidia-cuda.md) | * | --emit=asm generates PTX code that [runs on NVIDIA GPUs]
@@ -303,6 +302,7 @@ target | std | host | notes
 `i686-uwp-windows-msvc` | ? |  | [^x86_32-floats-return-ABI]
 [`i686-win7-windows-msvc`](platform-support/win7-windows-msvc.md) | ✓ |   | 32-bit Windows 7 support [^x86_32-floats-return-ABI]
 `i686-wrs-vxworks` | ? |  | [^x86_32-floats-return-ABI]
+[`loongarch64-unknown-linux-musl`](platform-support/loongarch-linux.md) | ? |  | LoongArch64 Linux (LP64D ABI) with musl 1.2.3
 [`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? |  | Motorola 680x0 Linux
 `mips-unknown-linux-gnu` | ✓ | ✓ | MIPS Linux (kernel 4.4, glibc 2.23)
 `mips-unknown-linux-musl` | ✓ |  | MIPS Linux with musl 1.2.3
diff --git a/src/doc/rustc/src/platform-support/unknown-uefi.md b/src/doc/rustc/src/platform-support/unknown-uefi.md
index 8fb155e1ffa..e6917502182 100644
--- a/src/doc/rustc/src/platform-support/unknown-uefi.md
+++ b/src/doc/rustc/src/platform-support/unknown-uefi.md
@@ -51,7 +51,7 @@ single stack.
 By default, the UEFI targets use the `link`-flavor of the LLVM linker `lld` to
 link binaries into the final PE32+ file suffixed with `*.efi`. The PE subsystem
 is set to `EFI_APPLICATION`, but can be modified by passing `/subsystem:<...>`
-to the linker. Similarly, the entry-point is to to `efi_main` but can be
+to the linker. Similarly, the entry-point is set to `efi_main` but can be
 changed via `/entry:<...>`. The panic-strategy is set to `abort`,
 
 The UEFI specification is available online for free:
diff --git a/src/etc/wasm32-shim.js b/src/etc/wasm32-shim.js
deleted file mode 100644
index 262a53eabe3..00000000000
--- a/src/etc/wasm32-shim.js
+++ /dev/null
@@ -1,24 +0,0 @@
-// This is a small "shim" program which is used when wasm32 unit tests are run
-// in this repository. This program is intended to be run in node.js and will
-// load a wasm module into memory, instantiate it with a set of imports, and
-// then run it.
-//
-// There's a bunch of helper functions defined here in `imports.env`, but note
-// that most of them aren't actually needed to execute most programs. Many of
-// these are just intended for completeness or debugging. Hopefully over time
-// nothing here is needed for completeness.
-
-const fs = require('fs');
-const process = require('process');
-const buffer = fs.readFileSync(process.argv[2]);
-
-Error.stackTraceLimit = 20;
-
-let m = new WebAssembly.Module(buffer);
-let instance = new WebAssembly.Instance(m, {});
-try {
-  instance.exports.main();
-} catch (e) {
-  console.error(e);
-  process.exit(101);
-}
diff --git a/src/tools/clippy/clippy_lints/src/loops/utils.rs b/src/tools/clippy/clippy_lints/src/loops/utils.rs
index e685274adb8..8bca33754e8 100644
--- a/src/tools/clippy/clippy_lints/src/loops/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/utils.rs
@@ -2,8 +2,8 @@ use clippy_utils::ty::{has_iter_method, implements_trait};
 use clippy_utils::{get_parent_expr, is_integer_const, path_to_local, path_to_local_id, sugg};
 use rustc_ast::ast::{LitIntType, LitKind};
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{walk_expr, walk_local, walk_pat, walk_stmt, Visitor};
-use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, HirId, HirIdMap, Local, Mutability, Pat, PatKind, Stmt};
+use rustc_hir::intravisit::{walk_expr, walk_local, Visitor};
+use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, HirId, HirIdMap, Local, Mutability, PatKind};
 use rustc_lint::LateContext;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, Ty};
@@ -253,62 +253,6 @@ fn is_conditional(expr: &Expr<'_>) -> bool {
     matches!(expr.kind, ExprKind::If(..) | ExprKind::Match(..))
 }
 
-#[derive(PartialEq, Eq)]
-pub(super) enum Nesting {
-    Unknown,     // no nesting detected yet
-    RuledOut,    // the iterator is initialized or assigned within scope
-    LookFurther, // no nesting detected, no further walk required
-}
-
-use self::Nesting::{LookFurther, RuledOut, Unknown};
-
-pub(super) struct LoopNestVisitor {
-    pub(super) hir_id: HirId,
-    pub(super) iterator: HirId,
-    pub(super) nesting: Nesting,
-}
-
-impl<'tcx> Visitor<'tcx> for LoopNestVisitor {
-    fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) {
-        if stmt.hir_id == self.hir_id {
-            self.nesting = LookFurther;
-        } else if self.nesting == Unknown {
-            walk_stmt(self, stmt);
-        }
-    }
-
-    fn visit_expr(&mut self, expr: &'tcx Expr<'_>) {
-        if self.nesting != Unknown {
-            return;
-        }
-        if expr.hir_id == self.hir_id {
-            self.nesting = LookFurther;
-            return;
-        }
-        match expr.kind {
-            ExprKind::Assign(path, _, _) | ExprKind::AssignOp(_, path, _) => {
-                if path_to_local_id(path, self.iterator) {
-                    self.nesting = RuledOut;
-                }
-            },
-            _ => walk_expr(self, expr),
-        }
-    }
-
-    fn visit_pat(&mut self, pat: &'tcx Pat<'_>) {
-        if self.nesting != Unknown {
-            return;
-        }
-        if let PatKind::Binding(_, id, ..) = pat.kind {
-            if id == self.iterator {
-                self.nesting = RuledOut;
-                return;
-            }
-        }
-        walk_pat(self, pat);
-    }
-}
-
 /// If `arg` was the argument to a `for` loop, return the "cleanest" way of writing the
 /// actual `Iterator` that the loop uses.
 pub(super) fn make_iterator_snippet(cx: &LateContext<'_>, arg: &Expr<'_>, applic_ref: &mut Applicability) -> String {
diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs
index 8d3e7520a54..067384b0901 100644
--- a/src/tools/clippy/clippy_lints/src/macro_use.rs
+++ b/src/tools/clippy/clippy_lints/src/macro_use.rs
@@ -30,12 +30,6 @@ declare_clippy_lint! {
     "#[macro_use] is no longer needed"
 }
 
-#[derive(Clone, Debug, PartialEq, Eq)]
-struct PathAndSpan {
-    path: String,
-    span: Span,
-}
-
 /// `MacroRefData` includes the name of the macro.
 #[derive(Debug, Clone)]
 pub struct MacroRefData {
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 06d8f099c33..78246136f2a 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -266,8 +266,10 @@ pub struct Config {
     pub logfile: Option<PathBuf>,
 
     /// A command line to prefix program execution with,
-    /// for running under valgrind
-    pub runtool: Option<String>,
+    /// for running under valgrind for example.
+    ///
+    /// Similar to `CARGO_*_RUNNER` configuration.
+    pub runner: Option<String>,
 
     /// Flags to pass to the compiler when building for the host
     pub host_rustcflags: Vec<String>,
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index f15761354f7..213e2a63517 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -680,7 +680,8 @@ pub fn line_directive<'line>(
 /// This is generated by collecting directives from ui tests and then extracting their directive
 /// names. This is **not** an exhaustive list of all possible directives. Instead, this is a
 /// best-effort approximation for diagnostics.
-const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
+const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
+    // tidy-alphabetical-start
     "assembly-output",
     "aux-build",
     "aux-crate",
@@ -693,6 +694,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
     "check-stdout",
     "check-test-line-numbers-match",
     "compile-flags",
+    "count",
     "dont-check-compiler-stderr",
     "dont-check-compiler-stdout",
     "dont-check-failure-status",
@@ -700,6 +702,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
     "error-pattern",
     "exec-env",
     "failure-status",
+    "filecheck-flags",
     "forbid-output",
     "force-host",
     "ignore-16bit",
@@ -716,6 +719,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
     "ignore-compare-mode-polonius",
     "ignore-cross-compile",
     "ignore-debug",
+    "ignore-eabi",
     "ignore-emscripten",
     "ignore-endian-big",
     "ignore-freebsd",
@@ -731,14 +735,30 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
     "ignore-lldb",
     "ignore-llvm-version",
     "ignore-loongarch64",
+    "ignore-macabi",
     "ignore-macos",
+    "ignore-mode-assembly",
+    "ignore-mode-codegen",
+    "ignore-mode-codegen-units",
     "ignore-mode-coverage-map",
     "ignore-mode-coverage-run",
+    "ignore-mode-debuginfo",
+    "ignore-mode-incremental",
+    "ignore-mode-js-doc-test",
+    "ignore-mode-mir-opt",
+    "ignore-mode-pretty",
+    "ignore-mode-run-make",
+    "ignore-mode-run-pass-valgrind",
+    "ignore-mode-rustdoc",
+    "ignore-mode-rustdoc-json",
+    "ignore-mode-ui",
+    "ignore-mode-ui-fulldeps",
     "ignore-msp430",
     "ignore-msvc",
     "ignore-musl",
     "ignore-netbsd",
     "ignore-nightly",
+    "ignore-none",
     "ignore-nto",
     "ignore-nvptx64",
     "ignore-openbsd",
@@ -750,18 +770,27 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
     "ignore-spirv",
     "ignore-stable",
     "ignore-stage1",
+    "ignore-stage2",
     "ignore-test",
+    "ignore-thumb",
     "ignore-thumbv8m.base-none-eabi",
     "ignore-thumbv8m.main-none-eabi",
+    "ignore-unix",
+    "ignore-unknown",
     "ignore-uwp",
     "ignore-vxworks",
+    "ignore-wasi",
     "ignore-wasm",
     "ignore-wasm32",
     "ignore-wasm32-bare",
+    "ignore-wasm64",
     "ignore-windows",
     "ignore-windows-gnu",
+    "ignore-x32",
     "ignore-x86",
+    "ignore-x86_64",
     "ignore-x86_64-apple-darwin",
+    "ignore-x86_64-unknown-linux-gnu",
     "incremental",
     "known-bug",
     "llvm-cov-flags",
@@ -769,9 +798,11 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
     "min-gdb-version",
     "min-lldb-version",
     "min-llvm-version",
+    "min-system-llvm-version",
     "needs-asm-support",
     "needs-dlltool",
     "needs-dynamic-linking",
+    "needs-git-hash",
     "needs-llvm-components",
     "needs-profiler-support",
     "needs-relocation-model-pic",
@@ -779,6 +810,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
     "needs-rust-lldb",
     "needs-sanitizer-address",
     "needs-sanitizer-cfi",
+    "needs-sanitizer-dataflow",
     "needs-sanitizer-hwaddress",
     "needs-sanitizer-leak",
     "needs-sanitizer-memory",
@@ -801,6 +833,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
     "only-aarch64",
     "only-arm",
     "only-avr",
+    "only-beta",
     "only-bpf",
     "only-cdb",
     "only-gnu",
@@ -818,6 +851,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
     "only-riscv64",
     "only-sparc",
     "only-sparc64",
+    "only-stable",
     "only-thumb",
     "only-wasm32",
     "only-wasm32-bare",
@@ -825,6 +859,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
     "only-x86",
     "only-x86_64",
     "only-x86_64-fortanix-unknown-sgx",
+    "only-x86_64-pc-windows-gnu",
     "only-x86_64-pc-windows-msvc",
     "only-x86_64-unknown-linux-gnu",
     "pp-exact",
@@ -846,6 +881,7 @@ const DIAGNOSTICS_DIRECTIVE_NAMES: &[&str] = &[
     "unit-test",
     "unset-exec-env",
     "unset-rustc-env",
+    // tidy-alphabetical-end
 ];
 
 /// The broken-down contents of a line containing a test header directive,
@@ -876,6 +912,22 @@ struct HeaderLine<'ln> {
     directive: &'ln str,
 }
 
+pub(crate) struct CheckDirectiveResult<'ln> {
+    is_known_directive: bool,
+    directive_name: &'ln str,
+}
+
+// Returns `(is_known_directive, directive_name)`.
+pub(crate) fn check_directive(directive_ln: &str) -> CheckDirectiveResult<'_> {
+    let directive_name =
+        directive_ln.split_once([':', ' ']).map(|(pre, _)| pre).unwrap_or(directive_ln);
+
+    CheckDirectiveResult {
+        is_known_directive: KNOWN_DIRECTIVE_NAMES.contains(&directive_name),
+        directive_name: directive_ln,
+    }
+}
+
 fn iter_header(
     mode: Mode,
     _suite: &str,
@@ -915,6 +967,7 @@ fn iter_header(
     let mut ln = String::new();
     let mut line_number = 0;
 
+    // Match on error annotations like `//~ERROR`.
     static REVISION_MAGIC_COMMENT_RE: Lazy<Regex> =
         Lazy::new(|| Regex::new("//(\\[.*\\])?~.*").unwrap());
 
@@ -933,9 +986,38 @@ fn iter_header(
         if ln.starts_with("fn") || ln.starts_with("mod") {
             return;
 
-        // First try to accept `ui_test` style comments
-        } else if let Some((header_revision, directive)) = line_directive(comment, ln) {
-            it(HeaderLine { line_number, original_line, header_revision, directive });
+        // First try to accept `ui_test` style comments (`//@`)
+        } else if let Some((header_revision, non_revisioned_directive_line)) =
+            line_directive(comment, ln)
+        {
+            // Perform unknown directive check on Rust files.
+            if testfile.extension().map(|e| e == "rs").unwrap_or(false) {
+                let directive_ln = non_revisioned_directive_line.trim();
+
+                let CheckDirectiveResult { is_known_directive, .. } = check_directive(directive_ln);
+
+                if !is_known_directive {
+                    *poisoned = true;
+
+                    eprintln!(
+                        "error: detected unknown compiletest test directive `{}` in {}:{}",
+                        directive_ln,
+                        testfile.display(),
+                        line_number,
+                    );
+
+                    return;
+                }
+            }
+
+            it(HeaderLine {
+                line_number,
+                original_line,
+                header_revision,
+                directive: non_revisioned_directive_line,
+            });
+        // Then we try to check for legacy-style candidates, which are not the magic ~ERROR family
+        // error annotations.
         } else if !REVISION_MAGIC_COMMENT_RE.is_match(ln) {
             let Some((_, rest)) = line_directive("//", ln) else {
                 continue;
@@ -949,34 +1031,18 @@ fn iter_header(
 
             let rest = rest.trim_start();
 
-            for candidate in DIAGNOSTICS_DIRECTIVE_NAMES.iter() {
-                if rest.starts_with(candidate) {
-                    let Some(prefix_removed) = rest.strip_prefix(candidate) else {
-                        // We have a comment that's *successfully* parsed as an legacy-style
-                        // directive. We emit an error here to warn the user.
-                        *poisoned = true;
-                        eprintln!(
-                            "error: detected legacy-style directives in compiletest test: {}:{}, please use `ui_test`-style directives `//@` instead:{:#?}",
-                            testfile.display(),
-                            line_number,
-                            line_directive("//", ln),
-                        );
-                        return;
-                    };
+            let CheckDirectiveResult { is_known_directive, directive_name } = check_directive(rest);
 
-                    if prefix_removed.starts_with([' ', ':']) {
-                        // We have a comment that's *successfully* parsed as an legacy-style
-                        // directive. We emit an error here to warn the user.
-                        *poisoned = true;
-                        eprintln!(
-                            "error: detected legacy-style directives in compiletest test: {}:{}, please use `ui_test`-style directives `//@` instead:{:#?}",
-                            testfile.display(),
-                            line_number,
-                            line_directive("//", ln),
-                        );
-                        return;
-                    }
-                }
+            if is_known_directive {
+                *poisoned = true;
+                eprintln!(
+                    "error: detected legacy-style directive {} in compiletest test: {}:{}, please use `ui_test`-style directives `//@` instead: {:#?}",
+                    directive_name,
+                    testfile.display(),
+                    line_number,
+                    line_directive("//", ln),
+                );
+                return;
             }
         }
     }
diff --git a/src/tools/compiletest/src/header/test-auxillary/error_annotation.rs b/src/tools/compiletest/src/header/test-auxillary/error_annotation.rs
new file mode 100644
index 00000000000..fea66a5e07b
--- /dev/null
+++ b/src/tools/compiletest/src/header/test-auxillary/error_annotation.rs
@@ -0,0 +1,6 @@
+//@ check-pass
+
+//~ HELP
+fn main() {} //~ERROR
+//~^ ERROR
+//~| ERROR
diff --git a/src/tools/compiletest/src/header/test-auxillary/known_directive.rs b/src/tools/compiletest/src/header/test-auxillary/known_directive.rs
new file mode 100644
index 00000000000..99834b14c1e
--- /dev/null
+++ b/src/tools/compiletest/src/header/test-auxillary/known_directive.rs
@@ -0,0 +1,4 @@
+//! ignore-wasm
+//@ ignore-wasm
+//@ check-pass
+// regular comment
diff --git a/src/tools/compiletest/src/header/test-auxillary/known_legacy_directive.rs b/src/tools/compiletest/src/header/test-auxillary/known_legacy_directive.rs
new file mode 100644
index 00000000000..108ca432e13
--- /dev/null
+++ b/src/tools/compiletest/src/header/test-auxillary/known_legacy_directive.rs
@@ -0,0 +1 @@
+// ignore-wasm
diff --git a/src/tools/compiletest/src/header/test-auxillary/not_rs.Makefile b/src/tools/compiletest/src/header/test-auxillary/not_rs.Makefile
new file mode 100644
index 00000000000..4b565e0e6df
--- /dev/null
+++ b/src/tools/compiletest/src/header/test-auxillary/not_rs.Makefile
@@ -0,0 +1 @@
+# ignore-owo
diff --git a/src/tools/compiletest/src/header/test-auxillary/unknown_directive.rs b/src/tools/compiletest/src/header/test-auxillary/unknown_directive.rs
new file mode 100644
index 00000000000..d4406031043
--- /dev/null
+++ b/src/tools/compiletest/src/header/test-auxillary/unknown_directive.rs
@@ -0,0 +1 @@
+//@ needs-headpat
diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs
index 815ac3839df..433f3e8b555 100644
--- a/src/tools/compiletest/src/header/tests.rs
+++ b/src/tools/compiletest/src/header/tests.rs
@@ -5,6 +5,8 @@ use std::str::FromStr;
 use crate::common::{Config, Debugger, Mode};
 use crate::header::{parse_normalization_string, EarlyProps, HeadersCache};
 
+use super::iter_header;
+
 fn make_test_description<R: Read>(
     config: &Config,
     name: test::TestName,
@@ -612,3 +614,63 @@ fn threads_support() {
         assert_eq!(check_ignore(&config, "//@ needs-threads"), !has_threads)
     }
 }
+
+fn run_path(poisoned: &mut bool, path: &Path, buf: &[u8]) {
+    let rdr = std::io::Cursor::new(&buf);
+    iter_header(Mode::Ui, "ui", poisoned, path, rdr, &mut |_| {});
+}
+
+#[test]
+fn test_unknown_directive_check() {
+    let mut poisoned = false;
+    run_path(
+        &mut poisoned,
+        Path::new("a.rs"),
+        include_bytes!("./test-auxillary/unknown_directive.rs"),
+    );
+    assert!(poisoned);
+}
+
+#[test]
+fn test_known_legacy_directive_check() {
+    let mut poisoned = false;
+    run_path(
+        &mut poisoned,
+        Path::new("a.rs"),
+        include_bytes!("./test-auxillary/known_legacy_directive.rs"),
+    );
+    assert!(poisoned);
+}
+
+#[test]
+fn test_known_directive_check_no_error() {
+    let mut poisoned = false;
+    run_path(
+        &mut poisoned,
+        Path::new("a.rs"),
+        include_bytes!("./test-auxillary/known_directive.rs"),
+    );
+    assert!(!poisoned);
+}
+
+#[test]
+fn test_error_annotation_no_error() {
+    let mut poisoned = false;
+    run_path(
+        &mut poisoned,
+        Path::new("a.rs"),
+        include_bytes!("./test-auxillary/error_annotation.rs"),
+    );
+    assert!(!poisoned);
+}
+
+#[test]
+fn test_non_rs_unknown_directive_not_checked() {
+    let mut poisoned = false;
+    run_path(
+        &mut poisoned,
+        Path::new("a.Makefile"),
+        include_bytes!("./test-auxillary/not_rs.Makefile"),
+    );
+    assert!(!poisoned);
+}
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index b32a5a4bf1a..ef02e7fcb4a 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -86,7 +86,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
         .optflag("", "exact", "filters match exactly")
         .optopt(
             "",
-            "runtool",
+            "runner",
             "supervisor program to run tests under \
              (eg. emulator, valgrind)",
             "PROGRAM",
@@ -256,7 +256,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
             _ => panic!("unknown `--run` option `{}` given", mode),
         }),
         logfile: matches.opt_str("logfile").map(|s| PathBuf::from(&s)),
-        runtool: matches.opt_str("runtool"),
+        runner: matches.opt_str("runner"),
         host_rustcflags: matches.opt_strs("host-rustcflags"),
         target_rustcflags: matches.opt_strs("target-rustcflags"),
         optimize_tests: matches.opt_present("optimize-tests"),
@@ -341,7 +341,7 @@ pub fn log_config(config: &Config) {
         c,
         format!("force_pass_mode: {}", opt_str(&config.force_pass_mode.map(|m| format!("{}", m))),),
     );
-    logv(c, format!("runtool: {}", opt_str(&config.runtool)));
+    logv(c, format!("runner: {}", opt_str(&config.runner)));
     logv(c, format!("host-rustcflags: {:?}", config.host_rustcflags));
     logv(c, format!("target-rustcflags: {:?}", config.target_rustcflags));
     logv(c, format!("target: {}", config.target));
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index ae0db88d873..7be0571b111 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -461,7 +461,7 @@ impl<'test> TestCx<'test> {
         }
 
         let mut new_config = self.config.clone();
-        new_config.runtool = new_config.valgrind_path.clone();
+        new_config.runner = new_config.valgrind_path.clone();
         let new_cx = TestCx { config: &new_config, ..*self };
         proc_res = new_cx.exec_compiled_test();
 
@@ -493,12 +493,8 @@ impl<'test> TestCx<'test> {
         let expected_coverage_dump = self.load_expected_output(kind);
         let actual_coverage_dump = self.normalize_output(&proc_res.stdout, &[]);
 
-        let coverage_dump_errors = self.compare_output(
-            kind,
-            &actual_coverage_dump,
-            &expected_coverage_dump,
-            self.props.compare_output_lines_by_subset,
-        );
+        let coverage_dump_errors =
+            self.compare_output(kind, &actual_coverage_dump, &expected_coverage_dump);
 
         if coverage_dump_errors > 0 {
             self.fatal_proc_rec(
@@ -591,12 +587,8 @@ impl<'test> TestCx<'test> {
                 self.fatal_proc_rec(&err, &proc_res);
             });
 
-        let coverage_errors = self.compare_output(
-            kind,
-            &normalized_actual_coverage,
-            &expected_coverage,
-            self.props.compare_output_lines_by_subset,
-        );
+        let coverage_errors =
+            self.compare_output(kind, &normalized_actual_coverage, &expected_coverage);
 
         if coverage_errors > 0 {
             self.fatal_proc_rec(
@@ -2632,9 +2624,7 @@ impl<'test> TestCx<'test> {
         // double the length.
         let mut f = self.output_base_dir().join("a");
         // FIXME: This is using the host architecture exe suffix, not target!
-        if self.config.target.contains("emscripten") {
-            f = f.with_extra_extension("js");
-        } else if self.config.target.contains("wasm32") {
+        if self.config.target.starts_with("wasm") {
             f = f.with_extra_extension("wasm");
         } else if self.config.target.contains("spirv") {
             f = f.with_extra_extension("spv");
@@ -2647,33 +2637,7 @@ impl<'test> TestCx<'test> {
     fn make_run_args(&self) -> ProcArgs {
         // If we've got another tool to run under (valgrind),
         // then split apart its command
-        let mut args = self.split_maybe_args(&self.config.runtool);
-
-        // If this is emscripten, then run tests under nodejs
-        if self.config.target.contains("emscripten") {
-            if let Some(ref p) = self.config.nodejs {
-                args.push(p.into());
-            } else {
-                self.fatal("emscripten target requested and no NodeJS binary found (--nodejs)");
-            }
-        // If this is otherwise wasm, then run tests under nodejs with our
-        // shim
-        } else if self.config.target.contains("wasm32") {
-            if let Some(ref p) = self.config.nodejs {
-                args.push(p.into());
-            } else {
-                self.fatal("wasm32 target requested and no NodeJS binary found (--nodejs)");
-            }
-
-            let src = self
-                .config
-                .src_base
-                .parent()
-                .unwrap() // chop off `ui`
-                .parent()
-                .unwrap(); // chop off `tests`
-            args.push(src.join("src/etc/wasm32-shim.js").into_os_string());
-        }
+        let mut args = self.split_maybe_args(&self.config.runner);
 
         let exe_file = self.make_exe_name();
 
@@ -4079,35 +4043,17 @@ impl<'test> TestCx<'test> {
         match output_kind {
             TestOutput::Compile => {
                 if !self.props.dont_check_compiler_stdout {
-                    errors += self.compare_output(
-                        stdout_kind,
-                        &normalized_stdout,
-                        &expected_stdout,
-                        self.props.compare_output_lines_by_subset,
-                    );
+                    errors +=
+                        self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout);
                 }
                 if !self.props.dont_check_compiler_stderr {
-                    errors += self.compare_output(
-                        stderr_kind,
-                        &normalized_stderr,
-                        &expected_stderr,
-                        self.props.compare_output_lines_by_subset,
-                    );
+                    errors +=
+                        self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr);
                 }
             }
             TestOutput::Run => {
-                errors += self.compare_output(
-                    stdout_kind,
-                    &normalized_stdout,
-                    &expected_stdout,
-                    self.props.compare_output_lines_by_subset,
-                );
-                errors += self.compare_output(
-                    stderr_kind,
-                    &normalized_stderr,
-                    &expected_stderr,
-                    self.props.compare_output_lines_by_subset,
-                );
+                errors += self.compare_output(stdout_kind, &normalized_stdout, &expected_stdout);
+                errors += self.compare_output(stderr_kind, &normalized_stderr, &expected_stderr);
             }
         }
         errors
@@ -4201,12 +4147,7 @@ impl<'test> TestCx<'test> {
                 )
             });
 
-            errors += self.compare_output(
-                "fixed",
-                &fixed_code,
-                &expected_fixed,
-                self.props.compare_output_lines_by_subset,
-            );
+            errors += self.compare_output("fixed", &fixed_code, &expected_fixed);
         } else if !expected_fixed.is_empty() {
             panic!(
                 "the `//@ run-rustfix` directive wasn't found but a `*.fixed` \
@@ -4701,17 +4642,19 @@ impl<'test> TestCx<'test> {
         }
     }
 
-    fn compare_output(
-        &self,
-        kind: &str,
-        actual: &str,
-        expected: &str,
-        compare_output_by_lines: bool,
-    ) -> usize {
+    fn compare_output(&self, kind: &str, actual: &str, expected: &str) -> usize {
         if actual == expected {
             return 0;
         }
 
+        // If `compare-output-lines-by-subset` is not explicitly enabled then
+        // auto-enable it when a `runner` is in use since wrapper tools might
+        // provide extra output on failure, for example a WebAssembly runtime
+        // might print the stack trace of an `unreachable` instruction by
+        // default.
+        let compare_output_by_lines =
+            self.props.compare_output_lines_by_subset || self.config.runner.is_some();
+
         let tmp;
         let (expected, actual): (&str, &str) = if compare_output_by_lines {
             let actual_lines: HashSet<_> = actual.lines().collect();
diff --git a/src/tools/llvm-bitcode-linker/Cargo.toml b/src/tools/llvm-bitcode-linker/Cargo.toml
new file mode 100644
index 00000000000..a9210b562f3
--- /dev/null
+++ b/src/tools/llvm-bitcode-linker/Cargo.toml
@@ -0,0 +1,14 @@
+[package]
+name = "llvm-bitcode-linker"
+version = "0.0.1"
+description = "A self-contained linker for llvm bitcode"
+license = "MIT OR Apache-2.0"
+edition = "2021"
+publish = false
+
+[dependencies]
+anyhow = "1.0"
+tracing = "0.1"
+tracing-subscriber = {version = "0.3.0", features = ["std"] }
+clap = { version = "4.3", features = ["derive"] }
+thiserror = "1.0.24"
diff --git a/src/tools/llvm-bitcode-linker/README.md b/src/tools/llvm-bitcode-linker/README.md
new file mode 100644
index 00000000000..9b8719e3a77
--- /dev/null
+++ b/src/tools/llvm-bitcode-linker/README.md
@@ -0,0 +1,5 @@
+# LLVM Bitcode Linker
+The LLVM bitcode linker can be used to link targets without any dependency on system libraries.
+The code will be linked in llvm-bc before compiling to native code. For some of these targets
+(e.g. ptx) there does not exist a sensible way to link the native format at all. A bitcode linker
+is required to link code compiled for such targets.
diff --git a/src/tools/llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs b/src/tools/llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs
new file mode 100644
index 00000000000..a92af71a36e
--- /dev/null
+++ b/src/tools/llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs
@@ -0,0 +1,62 @@
+use std::path::PathBuf;
+
+use clap::Parser;
+
+use llvm_bitcode_linker::{Optimization, Session, Target};
+
+#[derive(Debug, Parser)]
+/// Linker for embedded code without any system dependencies
+pub struct Args {
+    /// Input files - objects, archives and static libraries.
+    ///
+    /// An archive can be, but not required to be, a Rust rlib.
+    files: Vec<PathBuf>,
+
+    /// A symbol that should be exported
+    #[arg(long)]
+    export_symbol: Vec<String>,
+
+    /// Input files directory
+    #[arg(short = 'L')]
+    input_dir: Vec<PathBuf>,
+
+    /// Target triple for which the code is compiled
+    #[arg(long)]
+    target: Target,
+
+    /// The target cpu
+    #[arg(long)]
+    target_cpu: Option<String>,
+
+    /// Write output to the filename
+    #[arg(short, long)]
+    output: PathBuf,
+
+    // Enable link time optimization
+    #[arg(long)]
+    lto: bool,
+
+    /// Emit debug information
+    #[arg(long)]
+    debug: bool,
+
+    /// The optimization level
+    #[arg(short = 'O', value_enum, default_value = "0")]
+    optimization: Optimization,
+}
+
+fn main() -> anyhow::Result<()> {
+    tracing_subscriber::FmtSubscriber::builder().with_max_level(tracing::Level::DEBUG).init();
+
+    let args = Args::parse();
+
+    let mut linker = Session::new(args.target, args.target_cpu, args.output);
+
+    linker.add_exported_symbols(args.export_symbol);
+
+    for rlib in args.files {
+        linker.add_file(rlib);
+    }
+
+    linker.lto(args.optimization, args.debug)
+}
diff --git a/src/tools/llvm-bitcode-linker/src/lib.rs b/src/tools/llvm-bitcode-linker/src/lib.rs
new file mode 100644
index 00000000000..48f918f631c
--- /dev/null
+++ b/src/tools/llvm-bitcode-linker/src/lib.rs
@@ -0,0 +1,7 @@
+mod linker;
+mod opt;
+mod target;
+
+pub use linker::Session;
+pub use opt::Optimization;
+pub use target::Target;
diff --git a/src/tools/llvm-bitcode-linker/src/linker.rs b/src/tools/llvm-bitcode-linker/src/linker.rs
new file mode 100644
index 00000000000..aa6b6443e4d
--- /dev/null
+++ b/src/tools/llvm-bitcode-linker/src/linker.rs
@@ -0,0 +1,163 @@
+use std::path::PathBuf;
+
+use anyhow::Context;
+
+use crate::Optimization;
+use crate::Target;
+
+#[derive(Debug)]
+pub struct Session {
+    target: Target,
+    cpu: Option<String>,
+    symbols: Vec<String>,
+
+    /// A file that `llvm-link` supports, like a bitcode file or an archive.
+    files: Vec<PathBuf>,
+
+    // Output files
+    link_path: PathBuf,
+    opt_path: PathBuf,
+    sym_path: PathBuf,
+    out_path: PathBuf,
+}
+
+impl Session {
+    pub fn new(target: crate::Target, cpu: Option<String>, out_path: PathBuf) -> Self {
+        let link_path = out_path.with_extension("o");
+        let opt_path = out_path.with_extension("optimized.o");
+        let sym_path = out_path.with_extension("symbols.txt");
+
+        Session {
+            target,
+            cpu,
+            symbols: Vec::new(),
+            files: Vec::new(),
+            link_path,
+            opt_path,
+            sym_path,
+            out_path,
+        }
+    }
+
+    /// Add a file, like an rlib or bitcode file that should be linked
+    pub fn add_file(&mut self, path: PathBuf) {
+        self.files.push(path);
+    }
+
+    /// Add a Vec of symbols to the list of exported symbols
+    pub fn add_exported_symbols(&mut self, symbols: Vec<String>) {
+        self.symbols.extend(symbols);
+    }
+
+    /// Reads every file that was added to the session and link them without optimization.
+    ///
+    /// The resulting artifact will be written to a file that can later be read to perform
+    /// optimizations and/or compilation from bitcode to the final artifact.
+    fn link(&mut self) -> anyhow::Result<()> {
+        tracing::info!("Linking {} files using llvm-link", self.files.len());
+
+        let llvm_link_output = std::process::Command::new("llvm-link")
+            .arg("--ignore-non-bitcode")
+            .args(&self.files)
+            .arg("-o")
+            .arg(&self.link_path)
+            .output()
+            .unwrap();
+
+        if !llvm_link_output.status.success() {
+            tracing::error!(
+                "llvm-link returned with Exit status: {}\n stdout: {}\n stderr: {}",
+                llvm_link_output.status,
+                String::from_utf8(llvm_link_output.stdout).unwrap(),
+                String::from_utf8(llvm_link_output.stderr).unwrap(),
+            );
+            anyhow::bail!("llvm-link failed to link files {:?}", self.files);
+        }
+
+        Ok(())
+    }
+
+    /// Optimize and compile to native format using `opt` and `llc`
+    ///
+    /// Before this can be called `link` needs to be called
+    fn optimize(&mut self, optimization: Optimization, mut debug: bool) -> anyhow::Result<()> {
+        let mut passes = format!("default<{}>", optimization);
+
+        // FIXME(@kjetilkjeka) Debug symbol generation is broken for nvptx64 so we must remove them even in debug mode
+        if debug && self.target == crate::Target::Nvptx64NvidiaCuda {
+            tracing::warn!("nvptx64 target detected - stripping debug symbols");
+            debug = false;
+        }
+
+        // We add an internalize pass as the rust compiler as we require exported symbols to be explicitly marked
+        passes.push_str(",internalize,globaldce");
+        let symbol_file_content = self.symbols.iter().fold(String::new(), |s, x| s + &x + "\n");
+        std::fs::write(&self.sym_path, symbol_file_content)
+            .context(format!("Failed to write symbol file: {}", self.sym_path.display()))?;
+
+        tracing::info!("optimizing bitcode with passes: {}", passes);
+        let mut opt_cmd = std::process::Command::new("opt");
+        opt_cmd
+            .arg(&self.link_path)
+            .arg("-o")
+            .arg(&self.opt_path)
+            .arg(format!("--internalize-public-api-file={}", self.sym_path.display()))
+            .arg(format!("--passes={}", passes));
+
+        if !debug {
+            opt_cmd.arg("--strip-debug");
+        }
+
+        let opt_output = opt_cmd.output().unwrap();
+
+        if !opt_output.status.success() {
+            tracing::error!(
+                "opt returned with Exit status: {}\n stdout: {}\n stderr: {}",
+                opt_output.status,
+                String::from_utf8(opt_output.stdout).unwrap(),
+                String::from_utf8(opt_output.stderr).unwrap(),
+            );
+            anyhow::bail!("opt failed optimize bitcode: {}", self.link_path.display());
+        };
+
+        Ok(())
+    }
+
+    /// Compile the optimized bitcode file to native format using `llc`
+    ///
+    /// Before this can be called `optimize` needs to be called
+    fn compile(&mut self) -> anyhow::Result<()> {
+        let mut lcc_command = std::process::Command::new("llc");
+
+        if let Some(mcpu) = &self.cpu {
+            lcc_command.arg("--mcpu").arg(mcpu);
+        }
+
+        let lcc_output =
+            lcc_command.arg(&self.opt_path).arg("-o").arg(&self.out_path).output().unwrap();
+
+        if !lcc_output.status.success() {
+            tracing::error!(
+                "llc returned with Exit status: {}\n stdout: {}\n stderr: {}",
+                lcc_output.status,
+                String::from_utf8(lcc_output.stdout).unwrap(),
+                String::from_utf8(lcc_output.stderr).unwrap(),
+            );
+
+            anyhow::bail!(
+                "llc failed to compile {} into {}",
+                self.opt_path.display(),
+                self.out_path.display()
+            );
+        }
+
+        Ok(())
+    }
+
+    /// Links, optimizes and compiles to the native format
+    pub fn lto(&mut self, optimization: crate::Optimization, debug: bool) -> anyhow::Result<()> {
+        self.link()?;
+        self.optimize(optimization, debug)?;
+        self.compile()
+    }
+}
diff --git a/src/tools/llvm-bitcode-linker/src/opt.rs b/src/tools/llvm-bitcode-linker/src/opt.rs
new file mode 100644
index 00000000000..93f0ec7e2d6
--- /dev/null
+++ b/src/tools/llvm-bitcode-linker/src/opt.rs
@@ -0,0 +1,53 @@
+use std::fmt::Display;
+use std::fmt::Formatter;
+
+#[derive(Debug, Clone, Copy, Default, Hash, Eq, PartialEq, clap::ValueEnum)]
+pub enum Optimization {
+    #[default]
+    #[value(name = "0")]
+    O0,
+    #[value(name = "1")]
+    O1,
+    #[value(name = "2")]
+    O2,
+    #[value(name = "3")]
+    O3,
+    #[value(name = "s")]
+    Os,
+    #[value(name = "z")]
+    Oz,
+}
+
+#[derive(Debug, Clone, Copy, thiserror::Error)]
+/// An invalid optimization level
+#[error("invalid optimization level")]
+pub struct InvalidOptimizationLevel;
+
+impl std::str::FromStr for Optimization {
+    type Err = InvalidOptimizationLevel;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match s {
+            "0" | "O0" => Ok(Optimization::O0),
+            "1" | "O1" => Ok(Optimization::O1),
+            "2" | "O2" => Ok(Optimization::O2),
+            "3" | "O3" => Ok(Optimization::O3),
+            "s" | "Os" => Ok(Optimization::Os),
+            "z" | "Oz" => Ok(Optimization::Oz),
+            _ => Err(InvalidOptimizationLevel),
+        }
+    }
+}
+
+impl Display for Optimization {
+    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+        match *self {
+            Optimization::O0 => write!(f, "O0"),
+            Optimization::O1 => write!(f, "O1"),
+            Optimization::O2 => write!(f, "O2"),
+            Optimization::O3 => write!(f, "O3"),
+            Optimization::Os => write!(f, "Os"),
+            Optimization::Oz => write!(f, "Oz"),
+        }
+    }
+}
diff --git a/src/tools/llvm-bitcode-linker/src/target.rs b/src/tools/llvm-bitcode-linker/src/target.rs
new file mode 100644
index 00000000000..d9f8ff3852b
--- /dev/null
+++ b/src/tools/llvm-bitcode-linker/src/target.rs
@@ -0,0 +1,20 @@
+#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, clap::ValueEnum)]
+pub enum Target {
+    Nvptx64NvidiaCuda,
+}
+
+#[derive(Debug, Clone, Copy, thiserror::Error)]
+/// The target is not supported by this linker
+#[error("unsupported target")]
+pub struct UnsupportedTarget;
+
+impl std::str::FromStr for Target {
+    type Err = UnsupportedTarget;
+
+    fn from_str(s: &str) -> Result<Target, UnsupportedTarget> {
+        match s {
+            "nvptx64-nvidia-cuda" => Ok(Target::Nvptx64NvidiaCuda),
+            _ => Err(UnsupportedTarget),
+        }
+    }
+}
diff --git a/src/tools/miri/src/shims/time.rs b/src/tools/miri/src/shims/time.rs
index 13ce9d119bc..4535bcf6dfe 100644
--- a/src/tools/miri/src/shims/time.rs
+++ b/src/tools/miri/src/shims/time.rs
@@ -110,12 +110,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
     #[allow(non_snake_case, clippy::arithmetic_side_effects)]
     fn GetSystemTimeAsFileTime(
         &mut self,
+        shim_name: &str,
         LPFILETIME_op: &OpTy<'tcx, Provenance>,
     ) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
 
-        this.assert_target_os("windows", "GetSystemTimeAsFileTime");
-        this.check_no_isolation("`GetSystemTimeAsFileTime`")?;
+        this.assert_target_os("windows", shim_name);
+        this.check_no_isolation(shim_name)?;
 
         let filetime = this.deref_pointer_as(LPFILETIME_op, this.windows_ty_layout("FILETIME"))?;
 
diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs
index 9e0baf86cbc..bb4c325b746 100644
--- a/src/tools/miri/src/shims/windows/foreign_items.rs
+++ b/src/tools/miri/src/shims/windows/foreign_items.rs
@@ -257,11 +257,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             }
 
             // Time related shims
-            "GetSystemTimeAsFileTime" => {
+            "GetSystemTimeAsFileTime" | "GetSystemTimePreciseAsFileTime" => {
                 #[allow(non_snake_case)]
                 let [LPFILETIME] =
                     this.check_shim(abi, Abi::System { unwind: false }, link_name, args)?;
-                this.GetSystemTimeAsFileTime(LPFILETIME)?;
+                this.GetSystemTimeAsFileTime(link_name.as_str(), LPFILETIME)?;
             }
             "QueryPerformanceCounter" => {
                 #[allow(non_snake_case)]
diff --git a/src/tools/miri/tests/pass/alloc-access-tracking.rs b/src/tools/miri/tests/pass/alloc-access-tracking.rs
new file mode 100644
index 00000000000..5c782fca2df
--- /dev/null
+++ b/src/tools/miri/tests/pass/alloc-access-tracking.rs
@@ -0,0 +1,25 @@
+#![feature(start)]
+#![no_std]
+//@compile-flags: -Zmiri-track-alloc-id=17 -Zmiri-track-alloc-accesses -Cpanic=abort
+//@only-target-linux: alloc IDs differ between OSes for some reason
+
+extern "Rust" {
+    fn miri_alloc(size: usize, align: usize) -> *mut u8;
+    fn miri_dealloc(ptr: *mut u8, size: usize, align: usize);
+}
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    unsafe {
+        let ptr = miri_alloc(123, 1);
+        *ptr = 42; // Crucially, only a write is printed here, no read!
+        assert_eq!(*ptr, 42);
+        miri_dealloc(ptr, 123, 1);
+    }
+    0
+}
+
+#[panic_handler]
+fn panic_handler(_: &core::panic::PanicInfo) -> ! {
+    loop {}
+}
diff --git a/src/tools/miri/tests/pass/alloc-access-tracking.stderr b/src/tools/miri/tests/pass/alloc-access-tracking.stderr
new file mode 100644
index 00000000000..5e219fa1bed
--- /dev/null
+++ b/src/tools/miri/tests/pass/alloc-access-tracking.stderr
@@ -0,0 +1,37 @@
+note: tracking was triggered
+  --> $DIR/alloc-access-tracking.rs:LL:CC
+   |
+LL |         let ptr = miri_alloc(123, 1);
+   |                   ^^^^^^^^^^^^^^^^^^ created Miri bare-metal heap allocation of 123 bytes (alignment ALIGN bytes) with id 17
+   |
+   = note: BACKTRACE:
+   = note: inside `start` at $DIR/alloc-access-tracking.rs:LL:CC
+
+note: tracking was triggered
+  --> $DIR/alloc-access-tracking.rs:LL:CC
+   |
+LL |         *ptr = 42; // Crucially, only a write is printed here, no read!
+   |         ^^^^^^^^^ write access to allocation with id 17
+   |
+   = note: BACKTRACE:
+   = note: inside `start` at $DIR/alloc-access-tracking.rs:LL:CC
+
+note: tracking was triggered
+  --> $DIR/alloc-access-tracking.rs:LL:CC
+   |
+LL |         assert_eq!(*ptr, 42);
+   |         ^^^^^^^^^^^^^^^^^^^^ read access to allocation with id 17
+   |
+   = note: BACKTRACE:
+   = note: inside `start` at RUSTLIB/core/src/macros/mod.rs:LL:CC
+   = note: this note originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+note: tracking was triggered
+  --> $DIR/alloc-access-tracking.rs:LL:CC
+   |
+LL |         miri_dealloc(ptr, 123, 1);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ freed allocation with id 17
+   |
+   = note: BACKTRACE:
+   = note: inside `start` at $DIR/alloc-access-tracking.rs:LL:CC
+
diff --git a/src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs b/src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs
index 6daa033835b..18980932f31 100644
--- a/src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs
+++ b/src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs
@@ -84,6 +84,8 @@ unsafe impl Allocator for MyAllocator {
     }
 
     unsafe fn deallocate(&self, ptr: NonNull<u8>, _layout: Layout) {
+        // Make sure accesses via `self` don't disturb anything.
+        let _val = self.bins[0].top.get();
         // Since manually finding the corresponding bin of `ptr` is very expensive,
         // doing pointer arithmetics is preferred.
         // But this means we access `top` via `ptr` rather than `self`!
@@ -93,22 +95,30 @@ unsafe impl Allocator for MyAllocator {
         if self.thread_id == thread_id {
             unsafe { (*their_bin).push(ptr) };
         } else {
-            todo!("Deallocating from another thread")
+            todo!("Deallocating from another thread");
         }
+        // Make sure we can also still access this via `self` after the rest is done.
+        let _val = self.bins[0].top.get();
     }
 }
 
 // Make sure to involve `Box` in allocating these,
 // as that's where `noalias` may come from.
-fn v<T, A: Allocator>(t: T, a: A) -> Vec<T, A> {
+fn v1<T, A: Allocator>(t: T, a: A) -> Vec<T, A> {
     (Box::new_in([t], a) as Box<[T], A>).into_vec()
 }
+fn v2<T, A: Allocator>(t: T, a: A) -> Vec<T, A> {
+    let v = v1(t, a);
+    // There was a bug in `into_boxed_slice` that caused aliasing issues,
+    // so round-trip through that as well.
+    v.into_boxed_slice().into_vec()
+}
 
 fn main() {
     assert!(mem::size_of::<MyBin>() <= 128); // if it grows bigger, the trick to access the "header" no longer works
     let my_alloc = MyAllocator::new();
-    let a = v(1usize, &my_alloc);
-    let b = v(2usize, &my_alloc);
+    let a = v1(1usize, &my_alloc);
+    let b = v2(2usize, &my_alloc);
     assert_eq!(a[0] + 1, b[0]);
     assert_eq!(addr_of!(a[0]).wrapping_add(1), addr_of!(b[0]));
     drop((a, b));
diff --git a/src/tools/run-make-support/Cargo.toml b/src/tools/run-make-support/Cargo.toml
index 178deae6499..958aef69572 100644
--- a/src/tools/run-make-support/Cargo.toml
+++ b/src/tools/run-make-support/Cargo.toml
@@ -4,3 +4,4 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
+wasmparser = "0.118.2"
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index 820218732ce..674860f8413 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -2,13 +2,16 @@ use std::env;
 use std::path::{Path, PathBuf};
 use std::process::{Command, Output};
 
+pub use wasmparser;
+
+pub fn out_dir() -> PathBuf {
+    env::var_os("TMPDIR").unwrap().into()
+}
+
 fn setup_common_build_cmd() -> Command {
     let rustc = env::var("RUSTC").unwrap();
     let mut cmd = Command::new(rustc);
-    cmd.arg("--out-dir")
-        .arg(env::var("TMPDIR").unwrap())
-        .arg("-L")
-        .arg(env::var("TMPDIR").unwrap());
+    cmd.arg("--out-dir").arg(out_dir()).arg("-L").arg(out_dir());
     cmd
 }
 
@@ -45,6 +48,11 @@ impl RustcInvocationBuilder {
         self
     }
 
+    pub fn args(&mut self, args: &[&str]) -> &mut RustcInvocationBuilder {
+        self.cmd.args(args);
+        self
+    }
+
     #[track_caller]
     pub fn run(&mut self) -> Output {
         let caller_location = std::panic::Location::caller();
diff --git a/src/tools/rust-analyzer/.cargo/config.toml b/src/tools/rust-analyzer/.cargo/config.toml
index c3cfda85517..070560dfbc3 100644
--- a/src/tools/rust-analyzer/.cargo/config.toml
+++ b/src/tools/rust-analyzer/.cargo/config.toml
@@ -3,6 +3,7 @@ xtask = "run --package xtask --bin xtask --"
 tq = "test -- -q"
 qt = "tq"
 lint = "clippy --all-targets -- --cap-lints warn"
+codegen = "run --package xtask --bin xtask -- codegen"
 
 [target.x86_64-pc-windows-msvc]
 linker = "rust-lld"
diff --git a/src/tools/rust-analyzer/.github/workflows/ci.yaml b/src/tools/rust-analyzer/.github/workflows/ci.yaml
index 5a8b18e3fe1..2d8946520d5 100644
--- a/src/tools/rust-analyzer/.github/workflows/ci.yaml
+++ b/src/tools/rust-analyzer/.github/workflows/ci.yaml
@@ -79,6 +79,9 @@ jobs:
         if: matrix.os == 'ubuntu-latest'
         run: sed -i '/\[profile.dev]/a opt-level=1' Cargo.toml
 
+      - name: Codegen checks (rust-analyzer)
+        run: cargo codegen --check
+
       - name: Compile (tests)
         run: cargo test --no-run --locked ${{ env.USE_SYSROOT_ABI }}
 
diff --git a/src/tools/rust-analyzer/.typos.toml b/src/tools/rust-analyzer/.typos.toml
index 98dbe3a5d9d..c2e8b265218 100644
--- a/src/tools/rust-analyzer/.typos.toml
+++ b/src/tools/rust-analyzer/.typos.toml
@@ -5,7 +5,6 @@ extend-exclude = [
     "crates/parser/test_data/lexer/err/",
     "crates/project-model/test_data/",
 ]
-ignore-hidden = false
 
 [default]
 extend-ignore-re = [
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index 9acace2fb33..903141eee9a 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -4,9 +4,9 @@ version = 3
 
 [[package]]
 name = "addr2line"
-version = "0.19.0"
+version = "0.21.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97"
+checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb"
 dependencies = [
  "gimli",
 ]
@@ -28,9 +28,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.75"
+version = "1.0.80"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
+checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1"
 
 [[package]]
 name = "arbitrary"
@@ -52,16 +52,16 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
 
 [[package]]
 name = "backtrace"
-version = "0.3.67"
+version = "0.3.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca"
+checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837"
 dependencies = [
  "addr2line",
  "cc",
  "cfg-if",
  "libc",
- "miniz_oxide 0.6.2",
- "object 0.30.4",
+ "miniz_oxide",
+ "object 0.32.2",
  "rustc-demangle",
 ]
 
@@ -71,7 +71,6 @@ version = "0.0.0"
 dependencies = [
  "cfg",
  "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "profile",
  "rustc-hash",
  "salsa",
  "semver",
@@ -91,30 +90,30 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
 name = "bitflags"
-version = "2.4.1"
+version = "2.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
+checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
 
 [[package]]
 name = "byteorder"
-version = "1.4.3"
+version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
 
 [[package]]
 name = "camino"
-version = "1.1.4"
+version = "1.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c530edf18f37068ac2d977409ed5cd50d53d73bc653c7647b48eb78976ac9ae2"
+checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "cargo-platform"
-version = "0.1.2"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cbdb825da8a5df079a43676dbe042702f1707b1109f713a01420fbb4cc71fa27"
+checksum = "694c8807f2ae16faecc43dc17d74b3eb042482789fd0eb64b39a2e04e087053f"
 dependencies = [
  "serde",
 ]
@@ -135,9 +134,9 @@ dependencies = [
 
 [[package]]
 name = "cc"
-version = "1.0.79"
+version = "1.0.89"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
+checksum = "a0ba8f7aaa012f30d5b2861462f6708eccd49c3c39863fe083a308035f63d723"
 
 [[package]]
 name = "cfg"
@@ -177,7 +176,7 @@ version = "0.96.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ff550c2cdd63ff74394214dce03d06386928a641c0f08837535f04af573a966d"
 dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "chalk-derive",
  "lazy_static",
 ]
@@ -217,7 +216,7 @@ version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5080df6b0f0ecb76cab30808f00d937ba725cebe266a3da8cd89dff92f2a9916"
 dependencies = [
- "nix 0.26.2",
+ "nix 0.26.4",
  "winapi",
 ]
 
@@ -240,64 +239,55 @@ checksum = "0d48d8f76bd9331f19fe2aaf3821a9f9fb32c3963e1e3d6ce82a8c09cef7444a"
 
 [[package]]
 name = "crc32fast"
-version = "1.3.2"
+version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
+checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa"
 dependencies = [
  "cfg-if",
 ]
 
 [[package]]
 name = "crossbeam-channel"
-version = "0.5.8"
+version = "0.5.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
+checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95"
 dependencies = [
- "cfg-if",
  "crossbeam-utils",
 ]
 
 [[package]]
 name = "crossbeam-deque"
-version = "0.8.3"
+version = "0.8.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef"
+checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
 dependencies = [
- "cfg-if",
  "crossbeam-epoch",
  "crossbeam-utils",
 ]
 
 [[package]]
 name = "crossbeam-epoch"
-version = "0.9.15"
+version = "0.9.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
+checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
 dependencies = [
- "autocfg",
- "cfg-if",
  "crossbeam-utils",
- "memoffset",
- "scopeguard",
 ]
 
 [[package]]
 name = "crossbeam-utils"
-version = "0.8.16"
+version = "0.8.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
-dependencies = [
- "cfg-if",
-]
+checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
 
 [[package]]
 name = "ctrlc"
-version = "3.4.1"
+version = "3.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "82e95fbd621905b854affdc67943b043a0fbb6ed7385fd5a25650d19a8a6cfdf"
+checksum = "b467862cc8610ca6fc9a1532d7777cee0804e678ab45410897b9396495994a0b"
 dependencies = [
  "nix 0.27.1",
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
@@ -314,6 +304,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "deranged"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
+dependencies = [
+ "powerfmt",
+]
+
+[[package]]
 name = "derive_arbitrary"
 version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -344,9 +343,9 @@ checksum = "9bda8e21c04aca2ae33ffc2fd8c23134f3cac46db123ba97bd9d3f3b8a4a85e1"
 
 [[package]]
 name = "either"
-version = "1.9.0"
+version = "1.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
+checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
 
 [[package]]
 name = "ena"
@@ -358,19 +357,10 @@ dependencies = [
 ]
 
 [[package]]
-name = "env_logger"
-version = "0.10.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4cd405aab171cb85d6735e5c8d9db038c17d3ca007a4d2c25f337935c3d90580"
-dependencies = [
- "log",
-]
-
-[[package]]
 name = "equivalent"
-version = "1.0.0"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88bffebc5d80432c9b140ee17875ff173a8ab62faad5b257da912bd2f6c1c0a1"
+checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
 
 [[package]]
 name = "expect-test"
@@ -384,14 +374,14 @@ dependencies = [
 
 [[package]]
 name = "filetime"
-version = "0.2.22"
+version = "0.2.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0"
+checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd"
 dependencies = [
  "cfg-if",
  "libc",
- "redox_syscall 0.3.5",
- "windows-sys 0.48.0",
+ "redox_syscall",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
@@ -402,12 +392,12 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
 
 [[package]]
 name = "flate2"
-version = "1.0.26"
+version = "1.0.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743"
+checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e"
 dependencies = [
  "crc32fast",
- "miniz_oxide 0.7.1",
+ "miniz_oxide",
 ]
 
 [[package]]
@@ -428,9 +418,9 @@ dependencies = [
 
 [[package]]
 name = "form_urlencoded"
-version = "1.2.0"
+version = "1.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
+checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456"
 dependencies = [
  "percent-encoding",
 ]
@@ -463,9 +453,9 @@ dependencies = [
 
 [[package]]
 name = "gimli"
-version = "0.27.3"
+version = "0.28.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e"
+checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
 
 [[package]]
 name = "hashbrown"
@@ -481,12 +471,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
 
 [[package]]
 name = "hermit-abi"
-version = "0.2.6"
+version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
-dependencies = [
- "libc",
-]
+checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
 
 [[package]]
 name = "hir"
@@ -501,7 +488,6 @@ dependencies = [
  "hir-ty",
  "itertools",
  "once_cell",
- "profile",
  "rustc-hash",
  "smallvec",
  "span",
@@ -518,7 +504,7 @@ version = "0.0.0"
 dependencies = [
  "arrayvec",
  "base-db",
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "cfg",
  "cov-mark",
  "dashmap",
@@ -565,7 +551,6 @@ dependencies = [
  "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "limit",
  "mbe",
- "profile",
  "rustc-hash",
  "smallvec",
  "span",
@@ -582,7 +567,7 @@ version = "0.0.0"
 dependencies = [
  "arrayvec",
  "base-db",
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "chalk-derive",
  "chalk-ir",
  "chalk-recursive",
@@ -601,10 +586,9 @@ dependencies = [
  "nohash-hasher",
  "once_cell",
  "oorandom",
- "profile",
  "project-model",
  "ra-ap-rustc_abi",
- "ra-ap-rustc_index 0.35.0",
+ "ra-ap-rustc_index",
  "ra-ap-rustc_pattern_analysis",
  "rustc-hash",
  "scoped-tls",
@@ -622,11 +606,11 @@ dependencies = [
 
 [[package]]
 name = "home"
-version = "0.5.5"
+version = "0.5.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb"
+checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5"
 dependencies = [
- "windows-sys 0.48.0",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
@@ -673,9 +657,7 @@ dependencies = [
  "hir",
  "ide-db",
  "itertools",
- "profile",
  "smallvec",
- "sourcegen",
  "stdx",
  "syntax",
  "test-fixture",
@@ -695,7 +677,6 @@ dependencies = [
  "ide-db",
  "itertools",
  "once_cell",
- "profile",
  "smallvec",
  "stdx",
  "syntax",
@@ -724,12 +705,10 @@ dependencies = [
  "memchr",
  "nohash-hasher",
  "once_cell",
- "oorandom",
  "parser",
  "profile",
  "rayon",
  "rustc-hash",
- "sourcegen",
  "span",
  "stdx",
  "syntax",
@@ -738,7 +717,6 @@ dependencies = [
  "text-edit",
  "tracing",
  "triomphe",
- "xshell",
 ]
 
 [[package]]
@@ -753,9 +731,7 @@ dependencies = [
  "ide-db",
  "itertools",
  "once_cell",
- "profile",
  "serde_json",
- "sourcegen",
  "stdx",
  "syntax",
  "test-fixture",
@@ -785,9 +761,9 @@ dependencies = [
 
 [[package]]
 name = "idna"
-version = "0.4.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
+checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6"
 dependencies = [
  "unicode-bidi",
  "unicode-normalization",
@@ -795,9 +771,9 @@ dependencies = [
 
 [[package]]
 name = "indexmap"
-version = "2.1.0"
+version = "2.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
+checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4"
 dependencies = [
  "equivalent",
  "hashbrown",
@@ -835,18 +811,18 @@ dependencies = [
 
 [[package]]
 name = "itertools"
-version = "0.12.0"
+version = "0.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25db6b064527c5d482d0423354fcd07a89a2dfe07b67892e62411946db7f07b0"
+checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
 dependencies = [
  "either",
 ]
 
 [[package]]
 name = "itoa"
-version = "1.0.6"
+version = "1.0.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
+checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
 
 [[package]]
 name = "jod-thread"
@@ -856,9 +832,9 @@ checksum = "8b23360e99b8717f20aaa4598f5a6541efbe30630039fbc7706cf954a87947ae"
 
 [[package]]
 name = "kqueue"
-version = "1.0.7"
+version = "1.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c8fc60ba15bf51257aa9807a48a61013db043fcf3a78cb0d916e8e396dcad98"
+checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c"
 dependencies = [
  "kqueue-sys",
  "libc",
@@ -866,9 +842,9 @@ dependencies = [
 
 [[package]]
 name = "kqueue-sys"
-version = "1.0.3"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8367585489f01bc55dd27404dcf56b95e6da061a256a666ab23be9ba96a2e587"
+checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b"
 dependencies = [
  "bitflags 1.3.2",
  "libc",
@@ -892,25 +868,25 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.150"
+version = "0.2.153"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"
+checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
 
 [[package]]
 name = "libloading"
-version = "0.8.0"
+version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d580318f95776505201b28cf98eb1fa5e4be3b689633ba6a3e6cd880ff22d8cb"
+checksum = "2caa5afb8bf9f3a2652760ce7d4f62d21c4d5a423e68466fca30df82f2330164"
 dependencies = [
  "cfg-if",
- "windows-sys 0.48.0",
+ "windows-targets 0.52.4",
 ]
 
 [[package]]
 name = "libmimalloc-sys"
-version = "0.1.33"
+version = "0.1.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4ac0e912c8ef1b735e92369695618dc5b1819f5a7bf3f167301a3ba1cea515e"
+checksum = "3979b5c37ece694f1f5e51e7ecc871fdb0f517ed04ee45f88d15d6d553cb9664"
 dependencies = [
  "cc",
  "libc",
@@ -925,6 +901,7 @@ name = "line-index"
 version = "0.1.1"
 dependencies = [
  "nohash-hasher",
+ "oorandom",
  "text-size",
 ]
 
@@ -964,9 +941,9 @@ dependencies = [
 
 [[package]]
 name = "lock_api"
-version = "0.4.10"
+version = "0.4.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
+checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
 dependencies = [
  "autocfg",
  "scopeguard",
@@ -974,9 +951,9 @@ dependencies = [
 
 [[package]]
 name = "log"
-version = "0.4.19"
+version = "0.4.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
+checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
 
 [[package]]
 name = "lsp-server"
@@ -1057,41 +1034,32 @@ dependencies = [
 
 [[package]]
 name = "mimalloc"
-version = "0.1.37"
+version = "0.1.39"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e2894987a3459f3ffb755608bd82188f8ed00d0ae077f1edea29c068d639d98"
+checksum = "fa01922b5ea280a911e323e4d2fd24b7fe5cc4042e0d2cda3c40775cdc4bdc9c"
 dependencies = [
  "libmimalloc-sys",
 ]
 
 [[package]]
 name = "miniz_oxide"
-version = "0.6.2"
+version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
-dependencies = [
- "adler",
-]
-
-[[package]]
-name = "miniz_oxide"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
+checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
 dependencies = [
  "adler",
 ]
 
 [[package]]
 name = "mio"
-version = "0.8.5"
+version = "0.8.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de"
+checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
 dependencies = [
  "libc",
  "log",
  "wasi",
- "windows-sys 0.42.0",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
@@ -1105,14 +1073,13 @@ dependencies = [
 
 [[package]]
 name = "nix"
-version = "0.26.2"
+version = "0.26.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a"
+checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b"
 dependencies = [
  "bitflags 1.3.2",
  "cfg-if",
  "libc",
- "static_assertions",
 ]
 
 [[package]]
@@ -1121,7 +1088,7 @@ version = "0.27.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
 dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "cfg-if",
  "libc",
 ]
@@ -1138,7 +1105,7 @@ version = "6.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d"
 dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
  "crossbeam-channel",
  "filetime",
  "fsevent-sys",
@@ -1161,10 +1128,16 @@ dependencies = [
 ]
 
 [[package]]
+name = "num-conv"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
+
+[[package]]
 name = "num_cpus"
-version = "1.15.0"
+version = "1.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
+checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
 dependencies = [
  "hermit-abi",
  "libc",
@@ -1172,27 +1145,27 @@ dependencies = [
 
 [[package]]
 name = "object"
-version = "0.30.4"
+version = "0.32.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385"
+checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441"
 dependencies = [
  "memchr",
 ]
 
 [[package]]
 name = "object"
-version = "0.32.0"
+version = "0.33.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe"
+checksum = "d8dd6c0cdf9429bce006e1362bfce61fa1bfd8c898a643ed8d2b471934701d3d"
 dependencies = [
  "memchr",
 ]
 
 [[package]]
 name = "once_cell"
-version = "1.18.0"
+version = "1.19.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
 
 [[package]]
 name = "oorandom"
@@ -1218,9 +1191,9 @@ checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
 dependencies = [
  "cfg-if",
  "libc",
- "redox_syscall 0.4.1",
+ "redox_syscall",
  "smallvec",
- "windows-targets",
+ "windows-targets 0.48.5",
 ]
 
 [[package]]
@@ -1233,13 +1206,14 @@ dependencies = [
  "ra-ap-rustc_lexer",
  "sourcegen",
  "stdx",
+ "tracing",
 ]
 
 [[package]]
 name = "paste"
-version = "1.0.12"
+version = "1.0.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79"
+checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
 
 [[package]]
 name = "paths"
@@ -1247,9 +1221,9 @@ version = "0.0.0"
 
 [[package]]
 name = "percent-encoding"
-version = "2.3.0"
+version = "2.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
+checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
 
 [[package]]
 name = "perf-event"
@@ -1282,9 +1256,15 @@ dependencies = [
 
 [[package]]
 name = "pin-project-lite"
-version = "0.2.9"
+version = "0.2.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
+checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58"
+
+[[package]]
+name = "powerfmt"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
 
 [[package]]
 name = "ppv-lite86"
@@ -1300,9 +1280,8 @@ dependencies = [
  "indexmap",
  "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "memmap2",
- "object 0.32.0",
+ "object 0.33.0",
  "paths",
- "profile",
  "rustc-hash",
  "serde",
  "serde_json",
@@ -1324,7 +1303,7 @@ dependencies = [
  "libloading",
  "mbe",
  "memmap2",
- "object 0.32.0",
+ "object 0.33.0",
  "paths",
  "proc-macro-api",
  "proc-macro-test",
@@ -1347,14 +1326,13 @@ name = "proc-macro-test"
 version = "0.0.0"
 dependencies = [
  "cargo_metadata",
- "toolchain",
 ]
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.69"
+version = "1.0.78"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
+checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
 dependencies = [
  "unicode-ident",
 ]
@@ -1386,7 +1364,6 @@ dependencies = [
  "itertools",
  "la-arena 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "paths",
- "profile",
  "rustc-hash",
  "semver",
  "serde",
@@ -1419,11 +1396,11 @@ dependencies = [
 
 [[package]]
 name = "pulldown-cmark"
-version = "0.9.3"
+version = "0.9.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77a1a2f1f0a7ecff9c31abbe177637be0e97a0aef46cf8738ece09327985d998"
+checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b"
 dependencies = [
- "bitflags 1.3.2",
+ "bitflags 2.4.2",
  "memchr",
  "unicase",
 ]
@@ -1439,63 +1416,40 @@ dependencies = [
 
 [[package]]
 name = "quote"
-version = "1.0.28"
+version = "1.0.35"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
+checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
 dependencies = [
  "proc-macro2",
 ]
 
 [[package]]
 name = "ra-ap-rustc_abi"
-version = "0.35.0"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c0baa423a2c2bfd6e4bd40e7215f7ddebd12a649ce0b65078a38b91068895aa"
+checksum = "c2ae52e2d5b08762c9464b541345f519b8719d57b643b73632bade43ecece9dc"
 dependencies = [
- "bitflags 2.4.1",
- "ra-ap-rustc_index 0.35.0",
+ "bitflags 2.4.2",
+ "ra-ap-rustc_index",
  "tracing",
 ]
 
 [[package]]
 name = "ra-ap-rustc_index"
-version = "0.35.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "322b751895cc4a0a2ee0c6ab36ec80bc8abf5f8d76254c482f96f03c27c92ebe"
-dependencies = [
- "arrayvec",
- "ra-ap-rustc_index_macros 0.35.0",
- "smallvec",
-]
-
-[[package]]
-name = "ra-ap-rustc_index"
-version = "0.37.0"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df5a0ba0d08af366cf235dbe8eb7226cced7a4fe502c98aa434ccf416defd746"
+checksum = "bfd7e10c7853fe79443d46e1d2d8ab09fe99926118e59653fb8b480d5045f126"
 dependencies = [
  "arrayvec",
- "ra-ap-rustc_index_macros 0.37.0",
+ "ra-ap-rustc_index_macros",
  "smallvec",
 ]
 
 [[package]]
 name = "ra-ap-rustc_index_macros"
-version = "0.35.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "054e25eac52f0506c1309ca4317c11ad4925d7b99eb897f71aa7c3cbafb46c2b"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
- "synstructure",
-]
-
-[[package]]
-name = "ra-ap-rustc_index_macros"
-version = "0.37.0"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1971ebf9a701e0e68387c264a32517dcb4861ad3a4862f2e2803c1121ade20d5"
+checksum = "47f1d1c589be6c9a9e852fadee0e60329c0f862e87442ac2fe5adae30663cc76"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1505,9 +1459,9 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_lexer"
-version = "0.35.0"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8da0fa51a1a97ba4296a1c78fa454815a153b472e2546b6338a0902ad59e015"
+checksum = "fa852373a757b4c723bbdc96ced7f575cad68a1e266e45fee12bc4c69a482d80"
 dependencies = [
  "unicode-properties",
  "unicode-xid",
@@ -1515,21 +1469,21 @@ dependencies = [
 
 [[package]]
 name = "ra-ap-rustc_parse_format"
-version = "0.35.0"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3851f930a54adcb76889983dcd5c00a0c4e206e190e1384dbc00d49b82dfb45e"
+checksum = "2afe3c49accd95a53ac4d72ae13bafc7d115bdd80c8cd56ab09e6fc68f482210"
 dependencies = [
- "ra-ap-rustc_index 0.35.0",
+ "ra-ap-rustc_index",
  "ra-ap-rustc_lexer",
 ]
 
 [[package]]
 name = "ra-ap-rustc_pattern_analysis"
-version = "0.37.0"
+version = "0.42.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c3c0e7ca9c5bdc66e3b590688e237a22ac47a48e4eac7f46b05b2abbfaf0abd"
+checksum = "1253da23515d80c377a3998731e0ec3794997b62b989fd47db73efbde6a0bd7c"
 dependencies = [
- "ra-ap-rustc_index 0.37.0",
+ "ra-ap-rustc_index",
  "rustc-hash",
  "rustc_apfloat",
  "smallvec",
@@ -1568,9 +1522,9 @@ dependencies = [
 
 [[package]]
 name = "rayon"
-version = "1.8.0"
+version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1"
+checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd"
 dependencies = [
  "either",
  "rayon-core",
@@ -1578,9 +1532,9 @@ dependencies = [
 
 [[package]]
 name = "rayon-core"
-version = "1.12.0"
+version = "1.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed"
+checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
 dependencies = [
  "crossbeam-deque",
  "crossbeam-utils",
@@ -1588,15 +1542,6 @@ dependencies = [
 
 [[package]]
 name = "redox_syscall"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
-dependencies = [
- "bitflags 1.3.2",
-]
-
-[[package]]
-name = "redox_syscall"
 version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
@@ -1697,9 +1642,9 @@ dependencies = [
 
 [[package]]
 name = "ryu"
-version = "1.0.13"
+version = "1.0.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
+checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
 
 [[package]]
 name = "salsa"
@@ -1717,7 +1662,6 @@ dependencies = [
  "rustc-hash",
  "salsa-macros",
  "smallvec",
- "test-log",
  "tracing",
  "triomphe",
 ]
@@ -1758,33 +1702,33 @@ checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
 
 [[package]]
 name = "scopeguard"
-version = "1.1.0"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
 
 [[package]]
 name = "semver"
-version = "1.0.17"
+version = "1.0.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
+checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "serde"
-version = "1.0.193"
+version = "1.0.197"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
+checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.193"
+version = "1.0.197"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
+checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1793,9 +1737,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.108"
+version = "1.0.114"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
+checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0"
 dependencies = [
  "indexmap",
  "itoa",
@@ -1805,9 +1749,9 @@ dependencies = [
 
 [[package]]
 name = "serde_repr"
-version = "0.1.12"
+version = "0.1.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bcec881020c684085e55a25f7fd888954d56609ef363479dc5a1305eb0d40cab"
+checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1816,18 +1760,18 @@ dependencies = [
 
 [[package]]
 name = "sharded-slab"
-version = "0.1.4"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31"
+checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
 dependencies = [
  "lazy_static",
 ]
 
 [[package]]
 name = "smallvec"
-version = "1.12.0"
+version = "1.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2593d31f82ead8df961d8bd23a64c2ccf2eb5dd34b0a34bfb4dd54011c72009e"
+checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
 
 [[package]]
 name = "smol_str"
@@ -1840,9 +1784,9 @@ dependencies = [
 
 [[package]]
 name = "snap"
-version = "1.1.0"
+version = "1.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e9f0ab6ef7eb7353d9119c170a436d1bf248eea575ac42d19d12f4e34130831"
+checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b"
 
 [[package]]
 name = "sourcegen"
@@ -1871,12 +1815,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
 
 [[package]]
-name = "static_assertions"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
-
-[[package]]
 name = "stdx"
 version = "0.0.0"
 dependencies = [
@@ -1892,9 +1830,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.39"
+version = "2.0.52"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a"
+checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1903,14 +1841,13 @@ dependencies = [
 
 [[package]]
 name = "synstructure"
-version = "0.13.0"
+version = "0.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06"
+checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971"
 dependencies = [
  "proc-macro2",
  "quote",
  "syn",
- "unicode-xid",
 ]
 
 [[package]]
@@ -1925,7 +1862,6 @@ dependencies = [
  "once_cell",
  "parser",
  "proc-macro2",
- "profile",
  "quote",
  "ra-ap-rustc_lexer",
  "rayon",
@@ -1956,27 +1892,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "test-log"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6159ab4116165c99fc88cce31f99fa2c9dbe08d3691cb38da02fc3b45f357d2b"
-dependencies = [
- "env_logger",
- "test-log-macros",
-]
-
-[[package]]
-name = "test-log-macros"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ba277e77219e9eea169e8508942db1bf5d8a41ff2db9b20aab5a5aadc9fa25d"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
 name = "test-utils"
 version = "0.0.0"
 dependencies = [
@@ -2004,18 +1919,18 @@ checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233"
 
 [[package]]
 name = "thiserror"
-version = "1.0.40"
+version = "1.0.57"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
+checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.40"
+version = "1.0.57"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
+checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2024,9 +1939,9 @@ dependencies = [
 
 [[package]]
 name = "thread_local"
-version = "1.1.7"
+version = "1.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
+checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
 dependencies = [
  "cfg-if",
  "once_cell",
@@ -2034,9 +1949,9 @@ dependencies = [
 
 [[package]]
 name = "tikv-jemalloc-ctl"
-version = "0.5.0"
+version = "0.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e37706572f4b151dff7a0146e040804e9c26fe3a3118591112f05cf12a4216c1"
+checksum = "619bfed27d807b54f7f776b9430d4f8060e66ee138a28632ca898584d462c31c"
 dependencies = [
  "libc",
  "paste",
@@ -2045,9 +1960,9 @@ dependencies = [
 
 [[package]]
 name = "tikv-jemalloc-sys"
-version = "0.5.3+5.3.0-patched"
+version = "0.5.4+5.3.0-patched"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a678df20055b43e57ef8cddde41cdfda9a3c1a060b67f4c5836dfb1d78543ba8"
+checksum = "9402443cb8fd499b6f327e40565234ff34dbda27460c5b47db0db77443dd85d1"
 dependencies = [
  "cc",
  "libc",
@@ -2055,9 +1970,9 @@ dependencies = [
 
 [[package]]
 name = "tikv-jemallocator"
-version = "0.5.0"
+version = "0.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20612db8a13a6c06d57ec83953694185a367e16945f66565e8028d2c0bd76979"
+checksum = "965fe0c26be5c56c94e38ba547249074803efd52adfb66de62107d95aab3eaca"
 dependencies = [
  "libc",
  "tikv-jemalloc-sys",
@@ -2065,19 +1980,22 @@ dependencies = [
 
 [[package]]
 name = "time"
-version = "0.3.22"
+version = "0.3.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd"
+checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749"
 dependencies = [
+ "deranged",
+ "num-conv",
+ "powerfmt",
  "serde",
  "time-core",
 ]
 
 [[package]]
 name = "time-core"
-version = "0.1.1"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
+checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
 
 [[package]]
 name = "tinyvec"
@@ -2202,39 +2120,39 @@ checksum = "a3e5df347f0bf3ec1d670aad6ca5c6a1859cd9ea61d2113125794654ccced68f"
 
 [[package]]
 name = "unicase"
-version = "2.6.0"
+version = "2.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6"
+checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89"
 dependencies = [
  "version_check",
 ]
 
 [[package]]
 name = "unicode-bidi"
-version = "0.3.13"
+version = "0.3.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
+checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75"
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.9"
+version = "1.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
+checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
 
 [[package]]
 name = "unicode-normalization"
-version = "0.1.22"
+version = "0.1.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921"
+checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5"
 dependencies = [
  "tinyvec",
 ]
 
 [[package]]
 name = "unicode-properties"
-version = "0.1.0"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c7f91c8b21fbbaa18853c3d0801c78f4fc94cdb976699bb03e832e75f7fd22f0"
+checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291"
 
 [[package]]
 name = "unicode-xid"
@@ -2244,9 +2162,9 @@ checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c"
 
 [[package]]
 name = "url"
-version = "2.4.0"
+version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb"
+checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633"
 dependencies = [
  "form_urlencoded",
  "idna",
@@ -2293,9 +2211,9 @@ dependencies = [
 
 [[package]]
 name = "walkdir"
-version = "2.3.3"
+version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
+checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
 dependencies = [
  "same-file",
  "winapi-util",
@@ -2325,9 +2243,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
 
 [[package]]
 name = "winapi-util"
-version = "0.1.5"
+version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
 dependencies = [
  "winapi",
 ]
@@ -2340,147 +2258,156 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
 [[package]]
 name = "windows-sys"
-version = "0.42.0"
+version = "0.48.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
 dependencies = [
- "windows_aarch64_gnullvm 0.42.2",
- "windows_aarch64_msvc 0.42.2",
- "windows_i686_gnu 0.42.2",
- "windows_i686_msvc 0.42.2",
- "windows_x86_64_gnu 0.42.2",
- "windows_x86_64_gnullvm 0.42.2",
- "windows_x86_64_msvc 0.42.2",
+ "windows-targets 0.48.5",
 ]
 
 [[package]]
 name = "windows-sys"
-version = "0.48.0"
+version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
 dependencies = [
- "windows-targets",
+ "windows-targets 0.52.4",
 ]
 
 [[package]]
 name = "windows-targets"
-version = "0.48.0"
+version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
 dependencies = [
- "windows_aarch64_gnullvm 0.48.0",
- "windows_aarch64_msvc 0.48.0",
- "windows_i686_gnu 0.48.0",
- "windows_i686_msvc 0.48.0",
- "windows_x86_64_gnu 0.48.0",
- "windows_x86_64_gnullvm 0.48.0",
- "windows_x86_64_msvc 0.48.0",
+ "windows_aarch64_gnullvm 0.48.5",
+ "windows_aarch64_msvc 0.48.5",
+ "windows_i686_gnu 0.48.5",
+ "windows_i686_msvc 0.48.5",
+ "windows_x86_64_gnu 0.48.5",
+ "windows_x86_64_gnullvm 0.48.5",
+ "windows_x86_64_msvc 0.48.5",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
+dependencies = [
+ "windows_aarch64_gnullvm 0.52.4",
+ "windows_aarch64_msvc 0.52.4",
+ "windows_i686_gnu 0.52.4",
+ "windows_i686_msvc 0.52.4",
+ "windows_x86_64_gnu 0.52.4",
+ "windows_x86_64_gnullvm 0.52.4",
+ "windows_x86_64_msvc 0.52.4",
 ]
 
 [[package]]
 name = "windows_aarch64_gnullvm"
-version = "0.42.2"
+version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
+checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
 
 [[package]]
 name = "windows_aarch64_gnullvm"
-version = "0.48.0"
+version = "0.52.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
 
 [[package]]
 name = "windows_aarch64_msvc"
-version = "0.42.2"
+version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
+checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
 
 [[package]]
 name = "windows_aarch64_msvc"
-version = "0.48.0"
+version = "0.52.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
 
 [[package]]
 name = "windows_i686_gnu"
-version = "0.42.2"
+version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
+checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
 
 [[package]]
 name = "windows_i686_gnu"
-version = "0.48.0"
+version = "0.52.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
 
 [[package]]
 name = "windows_i686_msvc"
-version = "0.42.2"
+version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
+checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
 
 [[package]]
 name = "windows_i686_msvc"
-version = "0.48.0"
+version = "0.52.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
 
 [[package]]
 name = "windows_x86_64_gnu"
-version = "0.42.2"
+version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
+checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
 
 [[package]]
 name = "windows_x86_64_gnu"
-version = "0.48.0"
+version = "0.52.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
-version = "0.42.2"
+version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
+checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
-version = "0.48.0"
+version = "0.52.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
 
 [[package]]
 name = "windows_x86_64_msvc"
-version = "0.42.2"
+version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
+checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
 
 [[package]]
 name = "windows_x86_64_msvc"
-version = "0.48.0"
+version = "0.52.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
+checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
 
 [[package]]
 name = "write-json"
-version = "0.1.2"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06069a848f95fceae3e5e03c0ddc8cb78452b56654ee0c8e68f938cf790fb9e3"
+checksum = "23f6174b2566cc4a74f95e1367ec343e7fa80c93cc8087f5c4a3d6a1088b2118"
 
 [[package]]
 name = "xflags"
-version = "0.3.1"
+version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4554b580522d0ca238369c16b8f6ce34524d61dafe7244993754bbd05f2c2ea"
+checksum = "7d9e15fbb3de55454b0106e314b28e671279009b363e6f1d8e39fdc3bf048944"
 dependencies = [
  "xflags-macros",
 ]
 
 [[package]]
 name = "xflags-macros"
-version = "0.3.1"
+version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f58e7b3ca8977093aae6b87b6a7730216fc4c53a6530bab5c43a783cd810c1a8"
+checksum = "672423d4fea7ffa2f6c25ba60031ea13dc6258070556f125cc4d790007d4a155"
 
 [[package]]
 name = "xshell"
@@ -2503,6 +2430,7 @@ version = "0.1.0"
 dependencies = [
  "anyhow",
  "flate2",
+ "stdx",
  "time",
  "write-json",
  "xflags",
diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml
index 16dd5103899..440f46a938b 100644
--- a/src/tools/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/Cargo.toml
@@ -84,11 +84,11 @@ tt = { path = "./crates/tt", version = "0.0.0" }
 vfs-notify = { path = "./crates/vfs-notify", version = "0.0.0" }
 vfs = { path = "./crates/vfs", version = "0.0.0" }
 
-ra-ap-rustc_lexer = { version = "0.35.0", default-features = false }
-ra-ap-rustc_parse_format = { version = "0.35.0", default-features = false }
-ra-ap-rustc_index = { version = "0.35.0", default-features = false }
-ra-ap-rustc_abi = { version = "0.35.0", default-features = false }
-ra-ap-rustc_pattern_analysis = { version = "0.37.0", default-features = false }
+ra-ap-rustc_lexer = { version = "0.42.0", default-features = false }
+ra-ap-rustc_parse_format = { version = "0.42.0", default-features = false }
+ra-ap-rustc_index = { version = "0.42.0", default-features = false }
+ra-ap-rustc_abi = { version = "0.42.0", default-features = false }
+ra-ap-rustc_pattern_analysis = { version = "0.42.0", default-features = false }
 
 # local crates that aren't published to crates.io. These should not have versions.
 sourcegen = { path = "./crates/sourcegen" }
@@ -108,6 +108,7 @@ cargo_metadata = "0.18.1"
 command-group = "2.0.1"
 crossbeam-channel = "0.5.8"
 dissimilar = "1.0.7"
+dot = "0.1.4"
 either = "1.9.0"
 expect-test = "1.4.0"
 hashbrown = { version = "0.14", features = [
@@ -117,6 +118,16 @@ indexmap = "2.1.0"
 itertools = "0.12.0"
 libc = "0.2.150"
 nohash-hasher = "0.2.0"
+oorandom = "11.1.3"
+object = { version = "0.33.0", default-features = false, features = [
+    "std",
+    "read_core",
+    "elf",
+    "macho",
+    "pe",
+] }
+pulldown-cmark-to-cmark = "10.0.4"
+pulldown-cmark = { version = "0.9.0", default-features = false }
 rayon = "1.8.0"
 rustc-hash = "1.1.0"
 semver = "1.0.14"
@@ -137,6 +148,7 @@ tracing-subscriber = { version = "0.3.18", default-features = false, features =
   "tracing-log",
 ] }
 triomphe = { version = "0.1.10", default-features = false, features = ["std"] }
+url = "2.3.1"
 xshell = "0.2.5"
 
 
@@ -146,6 +158,7 @@ dashmap = { version = "=5.5.3", features = ["raw-api"] }
 [workspace.lints.rust]
 rust_2018_idioms = "warn"
 unused_lifetimes = "warn"
+unreachable_pub = "warn"
 semicolon_in_expressions_from_macros = "warn"
 
 [workspace.lints.clippy]
diff --git a/src/tools/rust-analyzer/crates/base-db/Cargo.toml b/src/tools/rust-analyzer/crates/base-db/Cargo.toml
index 801ba2d1f6c..118abf5d6eb 100644
--- a/src/tools/rust-analyzer/crates/base-db/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/base-db/Cargo.toml
@@ -21,7 +21,6 @@ tracing.workspace = true
 
 # local deps
 cfg.workspace = true
-profile.workspace = true
 stdx.workspace = true
 syntax.workspace = true
 vfs.workspace = true
diff --git a/src/tools/rust-analyzer/crates/base-db/src/lib.rs b/src/tools/rust-analyzer/crates/base-db/src/lib.rs
index cb2e6cdaa28..758d2a45c8f 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/lib.rs
@@ -43,7 +43,7 @@ pub trait Upcast<T: ?Sized> {
 }
 
 pub const DEFAULT_PARSE_LRU_CAP: usize = 128;
-pub const DEFAULT_BORROWCK_LRU_CAP: usize = 256;
+pub const DEFAULT_BORROWCK_LRU_CAP: usize = 1024;
 
 pub trait FileLoader {
     /// Text of the file.
diff --git a/src/tools/rust-analyzer/crates/flycheck/src/command.rs b/src/tools/rust-analyzer/crates/flycheck/src/command.rs
new file mode 100644
index 00000000000..091146a0010
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/flycheck/src/command.rs
@@ -0,0 +1,156 @@
+//! Utilities for running a cargo command like `cargo check` or `cargo test` in a separate thread and
+//! parse its stdout/stderr.
+
+use std::{
+    ffi::OsString,
+    fmt, io,
+    path::PathBuf,
+    process::{ChildStderr, ChildStdout, Command, Stdio},
+};
+
+use command_group::{CommandGroup, GroupChild};
+use crossbeam_channel::{unbounded, Receiver, Sender};
+use stdx::process::streaming_output;
+
+/// Cargo output is structured as a one JSON per line. This trait abstracts parsing one line of
+/// cargo output into a Rust data type.
+pub(crate) trait ParseFromLine: Sized + Send + 'static {
+    fn from_line(line: &str, error: &mut String) -> Option<Self>;
+    fn from_eof() -> Option<Self>;
+}
+
+struct CargoActor<T> {
+    sender: Sender<T>,
+    stdout: ChildStdout,
+    stderr: ChildStderr,
+}
+
+impl<T: ParseFromLine> CargoActor<T> {
+    fn new(sender: Sender<T>, stdout: ChildStdout, stderr: ChildStderr) -> Self {
+        CargoActor { sender, stdout, stderr }
+    }
+
+    fn run(self) -> io::Result<(bool, String)> {
+        // We manually read a line at a time, instead of using serde's
+        // stream deserializers, because the deserializer cannot recover
+        // from an error, resulting in it getting stuck, because we try to
+        // be resilient against failures.
+        //
+        // Because cargo only outputs one JSON object per line, we can
+        // simply skip a line if it doesn't parse, which just ignores any
+        // erroneous output.
+
+        let mut stdout_errors = String::new();
+        let mut stderr_errors = String::new();
+        let mut read_at_least_one_stdout_message = false;
+        let mut read_at_least_one_stderr_message = false;
+        let process_line = |line: &str, error: &mut String| {
+            // Try to deserialize a message from Cargo or Rustc.
+            if let Some(t) = T::from_line(line, error) {
+                self.sender.send(t).unwrap();
+                true
+            } else {
+                false
+            }
+        };
+        let output = streaming_output(
+            self.stdout,
+            self.stderr,
+            &mut |line| {
+                if process_line(line, &mut stdout_errors) {
+                    read_at_least_one_stdout_message = true;
+                }
+            },
+            &mut |line| {
+                if process_line(line, &mut stderr_errors) {
+                    read_at_least_one_stderr_message = true;
+                }
+            },
+            &mut || {
+                if let Some(t) = T::from_eof() {
+                    self.sender.send(t).unwrap();
+                }
+            },
+        );
+
+        let read_at_least_one_message =
+            read_at_least_one_stdout_message || read_at_least_one_stderr_message;
+        let mut error = stdout_errors;
+        error.push_str(&stderr_errors);
+        match output {
+            Ok(_) => Ok((read_at_least_one_message, error)),
+            Err(e) => Err(io::Error::new(e.kind(), format!("{e:?}: {error}"))),
+        }
+    }
+}
+
+struct JodGroupChild(GroupChild);
+
+impl Drop for JodGroupChild {
+    fn drop(&mut self) {
+        _ = self.0.kill();
+        _ = self.0.wait();
+    }
+}
+
+/// A handle to a cargo process used for fly-checking.
+pub(crate) struct CommandHandle<T> {
+    /// The handle to the actual cargo process. As we cannot cancel directly from with
+    /// a read syscall dropping and therefore terminating the process is our best option.
+    child: JodGroupChild,
+    thread: stdx::thread::JoinHandle<io::Result<(bool, String)>>,
+    pub(crate) receiver: Receiver<T>,
+    program: OsString,
+    arguments: Vec<OsString>,
+    current_dir: Option<PathBuf>,
+}
+
+impl<T> fmt::Debug for CommandHandle<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("CommandHandle")
+            .field("program", &self.program)
+            .field("arguments", &self.arguments)
+            .field("current_dir", &self.current_dir)
+            .finish()
+    }
+}
+
+impl<T: ParseFromLine> CommandHandle<T> {
+    pub(crate) fn spawn(mut command: Command) -> std::io::Result<Self> {
+        command.stdout(Stdio::piped()).stderr(Stdio::piped()).stdin(Stdio::null());
+        let mut child = command.group_spawn().map(JodGroupChild)?;
+
+        let program = command.get_program().into();
+        let arguments = command.get_args().map(|arg| arg.into()).collect::<Vec<OsString>>();
+        let current_dir = command.get_current_dir().map(|arg| arg.to_path_buf());
+
+        let stdout = child.0.inner().stdout.take().unwrap();
+        let stderr = child.0.inner().stderr.take().unwrap();
+
+        let (sender, receiver) = unbounded();
+        let actor = CargoActor::<T>::new(sender, stdout, stderr);
+        let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker)
+            .name("CommandHandle".to_owned())
+            .spawn(move || actor.run())
+            .expect("failed to spawn thread");
+        Ok(CommandHandle { program, arguments, current_dir, child, thread, receiver })
+    }
+
+    pub(crate) fn cancel(mut self) {
+        let _ = self.child.0.kill();
+        let _ = self.child.0.wait();
+    }
+
+    pub(crate) fn join(mut self) -> io::Result<()> {
+        let _ = self.child.0.kill();
+        let exit_status = self.child.0.wait()?;
+        let (read_at_least_one_message, error) = self.thread.join()?;
+        if read_at_least_one_message || exit_status.success() {
+            Ok(())
+        } else {
+            Err(io::Error::new(io::ErrorKind::Other, format!(
+            "Cargo watcher failed, the command produced no valid metadata (exit code: {exit_status:?}):\n{error}"
+        )))
+        }
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
index 8bcdca5bb82..f8efb520222 100644
--- a/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/flycheck/src/lib.rs
@@ -2,22 +2,18 @@
 //! another compatible command (f.x. clippy) in a background thread and provide
 //! LSP diagnostics based on the output of the command.
 
+// FIXME: This crate now handles running `cargo test` needed in the test explorer in
+// addition to `cargo check`. Either split it into 3 crates (one for test, one for check
+// and one common utilities) or change its name and docs to reflect the current state.
+
 #![warn(rust_2018_idioms, unused_lifetimes)]
 
-use std::{
-    ffi::OsString,
-    fmt, io,
-    path::PathBuf,
-    process::{ChildStderr, ChildStdout, Command, Stdio},
-    time::Duration,
-};
+use std::{fmt, io, path::PathBuf, process::Command, time::Duration};
 
-use command_group::{CommandGroup, GroupChild};
 use crossbeam_channel::{never, select, unbounded, Receiver, Sender};
 use paths::{AbsPath, AbsPathBuf};
 use rustc_hash::FxHashMap;
 use serde::Deserialize;
-use stdx::process::streaming_output;
 
 pub use cargo_metadata::diagnostic::{
     Applicability, Diagnostic, DiagnosticCode, DiagnosticLevel, DiagnosticSpan,
@@ -25,6 +21,12 @@ pub use cargo_metadata::diagnostic::{
 };
 use toolchain::Tool;
 
+mod command;
+mod test_runner;
+
+use command::{CommandHandle, ParseFromLine};
+pub use test_runner::{CargoTestHandle, CargoTestMessage, TestState};
+
 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
 pub enum InvocationStrategy {
     Once,
@@ -181,12 +183,12 @@ struct FlycheckActor {
     /// doesn't provide a way to read sub-process output without blocking, so we
     /// have to wrap sub-processes output handling in a thread and pass messages
     /// back over a channel.
-    command_handle: Option<CommandHandle>,
+    command_handle: Option<CommandHandle<CargoCheckMessage>>,
 }
 
 enum Event {
     RequestStateChange(StateChange),
-    CheckEvent(Option<CargoMessage>),
+    CheckEvent(Option<CargoCheckMessage>),
 }
 
 const SAVED_FILE_PLACEHOLDER: &str = "$saved_file";
@@ -282,7 +284,7 @@ impl FlycheckActor {
                     self.report_progress(Progress::DidFinish(res));
                 }
                 Event::CheckEvent(Some(message)) => match message {
-                    CargoMessage::CompilerArtifact(msg) => {
+                    CargoCheckMessage::CompilerArtifact(msg) => {
                         tracing::trace!(
                             flycheck_id = self.id,
                             artifact = msg.target.name,
@@ -291,7 +293,7 @@ impl FlycheckActor {
                         self.report_progress(Progress::DidCheckCrate(msg.target.name));
                     }
 
-                    CargoMessage::Diagnostic(msg) => {
+                    CargoCheckMessage::Diagnostic(msg) => {
                         tracing::trace!(
                             flycheck_id = self.id,
                             message = msg.message,
@@ -448,161 +450,42 @@ impl FlycheckActor {
     }
 }
 
-struct JodGroupChild(GroupChild);
-
-impl Drop for JodGroupChild {
-    fn drop(&mut self) {
-        _ = self.0.kill();
-        _ = self.0.wait();
-    }
-}
-
-/// A handle to a cargo process used for fly-checking.
-struct CommandHandle {
-    /// The handle to the actual cargo process. As we cannot cancel directly from with
-    /// a read syscall dropping and therefore terminating the process is our best option.
-    child: JodGroupChild,
-    thread: stdx::thread::JoinHandle<io::Result<(bool, String)>>,
-    receiver: Receiver<CargoMessage>,
-    program: OsString,
-    arguments: Vec<OsString>,
-    current_dir: Option<PathBuf>,
-}
-
-impl fmt::Debug for CommandHandle {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.debug_struct("CommandHandle")
-            .field("program", &self.program)
-            .field("arguments", &self.arguments)
-            .field("current_dir", &self.current_dir)
-            .finish()
-    }
+#[allow(clippy::large_enum_variant)]
+enum CargoCheckMessage {
+    CompilerArtifact(cargo_metadata::Artifact),
+    Diagnostic(Diagnostic),
 }
 
-impl CommandHandle {
-    fn spawn(mut command: Command) -> std::io::Result<CommandHandle> {
-        command.stdout(Stdio::piped()).stderr(Stdio::piped()).stdin(Stdio::null());
-        let mut child = command.group_spawn().map(JodGroupChild)?;
-
-        let program = command.get_program().into();
-        let arguments = command.get_args().map(|arg| arg.into()).collect::<Vec<OsString>>();
-        let current_dir = command.get_current_dir().map(|arg| arg.to_path_buf());
-
-        let stdout = child.0.inner().stdout.take().unwrap();
-        let stderr = child.0.inner().stderr.take().unwrap();
-
-        let (sender, receiver) = unbounded();
-        let actor = CargoActor::new(sender, stdout, stderr);
-        let thread = stdx::thread::Builder::new(stdx::thread::ThreadIntent::Worker)
-            .name("CommandHandle".to_owned())
-            .spawn(move || actor.run())
-            .expect("failed to spawn thread");
-        Ok(CommandHandle { program, arguments, current_dir, child, thread, receiver })
-    }
-
-    fn cancel(mut self) {
-        let _ = self.child.0.kill();
-        let _ = self.child.0.wait();
-    }
-
-    fn join(mut self) -> io::Result<()> {
-        let _ = self.child.0.kill();
-        let exit_status = self.child.0.wait()?;
-        let (read_at_least_one_message, error) = self.thread.join()?;
-        if read_at_least_one_message || exit_status.success() {
-            Ok(())
-        } else {
-            Err(io::Error::new(io::ErrorKind::Other, format!(
-                "Cargo watcher failed, the command produced no valid metadata (exit code: {exit_status:?}):\n{error}"
-            )))
+impl ParseFromLine for CargoCheckMessage {
+    fn from_line(line: &str, error: &mut String) -> Option<Self> {
+        let mut deserializer = serde_json::Deserializer::from_str(line);
+        deserializer.disable_recursion_limit();
+        if let Ok(message) = JsonMessage::deserialize(&mut deserializer) {
+            return match message {
+                // Skip certain kinds of messages to only spend time on what's useful
+                JsonMessage::Cargo(message) => match message {
+                    cargo_metadata::Message::CompilerArtifact(artifact) if !artifact.fresh => {
+                        Some(CargoCheckMessage::CompilerArtifact(artifact))
+                    }
+                    cargo_metadata::Message::CompilerMessage(msg) => {
+                        Some(CargoCheckMessage::Diagnostic(msg.message))
+                    }
+                    _ => None,
+                },
+                JsonMessage::Rustc(message) => Some(CargoCheckMessage::Diagnostic(message)),
+            };
         }
-    }
-}
 
-struct CargoActor {
-    sender: Sender<CargoMessage>,
-    stdout: ChildStdout,
-    stderr: ChildStderr,
-}
-
-impl CargoActor {
-    fn new(sender: Sender<CargoMessage>, stdout: ChildStdout, stderr: ChildStderr) -> CargoActor {
-        CargoActor { sender, stdout, stderr }
+        error.push_str(line);
+        error.push('\n');
+        None
     }
 
-    fn run(self) -> io::Result<(bool, String)> {
-        // We manually read a line at a time, instead of using serde's
-        // stream deserializers, because the deserializer cannot recover
-        // from an error, resulting in it getting stuck, because we try to
-        // be resilient against failures.
-        //
-        // Because cargo only outputs one JSON object per line, we can
-        // simply skip a line if it doesn't parse, which just ignores any
-        // erroneous output.
-
-        let mut stdout_errors = String::new();
-        let mut stderr_errors = String::new();
-        let mut read_at_least_one_stdout_message = false;
-        let mut read_at_least_one_stderr_message = false;
-        let process_line = |line: &str, error: &mut String| {
-            // Try to deserialize a message from Cargo or Rustc.
-            let mut deserializer = serde_json::Deserializer::from_str(line);
-            deserializer.disable_recursion_limit();
-            if let Ok(message) = JsonMessage::deserialize(&mut deserializer) {
-                match message {
-                    // Skip certain kinds of messages to only spend time on what's useful
-                    JsonMessage::Cargo(message) => match message {
-                        cargo_metadata::Message::CompilerArtifact(artifact) if !artifact.fresh => {
-                            self.sender.send(CargoMessage::CompilerArtifact(artifact)).unwrap();
-                        }
-                        cargo_metadata::Message::CompilerMessage(msg) => {
-                            self.sender.send(CargoMessage::Diagnostic(msg.message)).unwrap();
-                        }
-                        _ => (),
-                    },
-                    JsonMessage::Rustc(message) => {
-                        self.sender.send(CargoMessage::Diagnostic(message)).unwrap();
-                    }
-                }
-                return true;
-            }
-
-            error.push_str(line);
-            error.push('\n');
-            false
-        };
-        let output = streaming_output(
-            self.stdout,
-            self.stderr,
-            &mut |line| {
-                if process_line(line, &mut stdout_errors) {
-                    read_at_least_one_stdout_message = true;
-                }
-            },
-            &mut |line| {
-                if process_line(line, &mut stderr_errors) {
-                    read_at_least_one_stderr_message = true;
-                }
-            },
-        );
-
-        let read_at_least_one_message =
-            read_at_least_one_stdout_message || read_at_least_one_stderr_message;
-        let mut error = stdout_errors;
-        error.push_str(&stderr_errors);
-        match output {
-            Ok(_) => Ok((read_at_least_one_message, error)),
-            Err(e) => Err(io::Error::new(e.kind(), format!("{e:?}: {error}"))),
-        }
+    fn from_eof() -> Option<Self> {
+        None
     }
 }
 
-#[allow(clippy::large_enum_variant)]
-enum CargoMessage {
-    CompilerArtifact(cargo_metadata::Artifact),
-    Diagnostic(Diagnostic),
-}
-
 #[derive(Deserialize)]
 #[serde(untagged)]
 enum JsonMessage {
diff --git a/src/tools/rust-analyzer/crates/flycheck/src/test_runner.rs b/src/tools/rust-analyzer/crates/flycheck/src/test_runner.rs
new file mode 100644
index 00000000000..6dac5899ee3
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/flycheck/src/test_runner.rs
@@ -0,0 +1,76 @@
+//! This module provides the functionality needed to run `cargo test` in a background
+//! thread and report the result of each test in a channel.
+
+use std::process::Command;
+
+use crossbeam_channel::Receiver;
+use serde::Deserialize;
+use toolchain::Tool;
+
+use crate::command::{CommandHandle, ParseFromLine};
+
+#[derive(Debug, Deserialize)]
+#[serde(tag = "event", rename_all = "camelCase")]
+pub enum TestState {
+    Started,
+    Ok,
+    Ignored,
+    Failed { stdout: String },
+}
+
+#[derive(Debug, Deserialize)]
+#[serde(tag = "type", rename_all = "camelCase")]
+pub enum CargoTestMessage {
+    Test {
+        name: String,
+        #[serde(flatten)]
+        state: TestState,
+    },
+    Suite,
+    Finished,
+}
+
+impl ParseFromLine for CargoTestMessage {
+    fn from_line(line: &str, error: &mut String) -> Option<Self> {
+        let mut deserializer = serde_json::Deserializer::from_str(line);
+        deserializer.disable_recursion_limit();
+        if let Ok(message) = CargoTestMessage::deserialize(&mut deserializer) {
+            return Some(message);
+        }
+
+        error.push_str(line);
+        error.push('\n');
+        None
+    }
+
+    fn from_eof() -> Option<Self> {
+        Some(CargoTestMessage::Finished)
+    }
+}
+
+#[derive(Debug)]
+pub struct CargoTestHandle {
+    handle: CommandHandle<CargoTestMessage>,
+}
+
+// Example of a cargo test command:
+// cargo test -- module::func -Z unstable-options --format=json
+
+impl CargoTestHandle {
+    pub fn new(path: Option<&str>) -> std::io::Result<Self> {
+        let mut cmd = Command::new(Tool::Cargo.path());
+        cmd.env("RUSTC_BOOTSTRAP", "1");
+        cmd.arg("test");
+        cmd.arg("--");
+        if let Some(path) = path {
+            cmd.arg(path);
+        }
+        cmd.args(["-Z", "unstable-options"]);
+        cmd.arg("--format=json");
+        Ok(Self { handle: CommandHandle::spawn(cmd)? })
+    }
+
+    pub fn receiver(&self) -> &Receiver<CargoTestMessage> {
+        &self.handle.receiver
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
index 519706c65f2..21536098b82 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
@@ -348,7 +348,7 @@ impl AttrsWithOwner {
                         .raw_attrs(AttrOwner::ModItem(definition_tree_id.value.into()))
                         .clone(),
                     ModuleOrigin::BlockExpr { id, .. } => {
-                        let tree = db.block_item_tree_query(id);
+                        let tree = db.block_item_tree(id);
                         tree.raw_attrs(AttrOwner::TopLevel).clone()
                     }
                 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/body.rs
index ce8a9eab14a..37d37fd3311 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body.rs
@@ -13,7 +13,6 @@ use cfg::{CfgExpr, CfgOptions};
 use either::Either;
 use hir_expand::{name::Name, HirFileId, InFile};
 use la_arena::{Arena, ArenaMap};
-use profile::Count;
 use rustc_hash::FxHashMap;
 use syntax::{ast, AstPtr, SyntaxNodePtr};
 use triomphe::Arc;
@@ -51,7 +50,6 @@ pub struct Body {
     pub body_expr: ExprId,
     /// Block expressions in this body that may contain inner items.
     block_scopes: Vec<BlockId>,
-    _c: Count<Self>,
 }
 
 pub type ExprPtr = AstPtr<ast::Expr>;
@@ -216,7 +214,6 @@ impl Body {
 
     fn shrink_to_fit(&mut self) {
         let Self {
-            _c: _,
             body_expr: _,
             block_scopes,
             exprs,
@@ -300,7 +297,6 @@ impl Default for Body {
             params: Default::default(),
             block_scopes: Default::default(),
             binding_owners: Default::default(),
-            _c: Default::default(),
         }
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
index ad8782d3d1e..66691277894 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
@@ -10,7 +10,6 @@ use hir_expand::{
     ExpandError, InFile,
 };
 use intern::Interned;
-use profile::Count;
 use rustc_hash::FxHashMap;
 use smallvec::SmallVec;
 use span::AstIdMap;
@@ -76,7 +75,6 @@ pub(super) fn lower(
             params: Vec::new(),
             body_expr: dummy_expr_id(),
             block_scopes: Vec::new(),
-            _c: Count::new(),
         },
         expander,
         current_try_block_label: None,
@@ -705,7 +703,8 @@ impl ExprCollector<'_> {
         let Some(try_from_output) = LangItem::TryTraitFromOutput.path(self.db, self.krate) else {
             return self.collect_block(e);
         };
-        let label = self.alloc_label_desugared(Label { name: Name::generate_new_name() });
+        let label = self
+            .alloc_label_desugared(Label { name: Name::generate_new_name(self.body.labels.len()) });
         let old_label = self.current_try_block_label.replace(label);
 
         let (btail, expr_id) = self.with_labeled_rib(label, |this| {
@@ -842,7 +841,7 @@ impl ExprCollector<'_> {
                 this.collect_expr_opt(e.loop_body().map(|it| it.into()))
             }),
         };
-        let iter_name = Name::generate_new_name();
+        let iter_name = Name::generate_new_name(self.body.exprs.len());
         let iter_expr = self.alloc_expr(Expr::Path(Path::from(iter_name.clone())), syntax_ptr);
         let iter_expr_mut = self.alloc_expr(
             Expr::Ref { expr: iter_expr, rawness: Rawness::Ref, mutability: Mutability::Mut },
@@ -903,7 +902,7 @@ impl ExprCollector<'_> {
             Expr::Call { callee: try_branch, args: Box::new([operand]), is_assignee_expr: false },
             syntax_ptr,
         );
-        let continue_name = Name::generate_new_name();
+        let continue_name = Name::generate_new_name(self.body.bindings.len());
         let continue_binding =
             self.alloc_binding(continue_name.clone(), BindingAnnotation::Unannotated);
         let continue_bpat =
@@ -918,7 +917,7 @@ impl ExprCollector<'_> {
             guard: None,
             expr: self.alloc_expr(Expr::Path(Path::from(continue_name)), syntax_ptr),
         };
-        let break_name = Name::generate_new_name();
+        let break_name = Name::generate_new_name(self.body.bindings.len());
         let break_binding = self.alloc_binding(break_name.clone(), BindingAnnotation::Unannotated);
         let break_bpat = self.alloc_pat_desugared(Pat::Bind { id: break_binding, subpat: None });
         self.add_definition_to_binding(break_binding, break_bpat);
@@ -1415,16 +1414,10 @@ impl ExprCollector<'_> {
                         ast::Pat::LiteralPat(it) => {
                             Some(Box::new(LiteralOrConst::Literal(pat_literal_to_hir(it)?.0)))
                         }
-                        ast::Pat::IdentPat(p) => {
-                            let name =
-                                p.name().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
-                            Some(Box::new(LiteralOrConst::Const(name.into())))
+                        pat @ (ast::Pat::IdentPat(_) | ast::Pat::PathPat(_)) => {
+                            let subpat = self.collect_pat(pat.clone(), binding_list);
+                            Some(Box::new(LiteralOrConst::Const(subpat)))
                         }
-                        ast::Pat::PathPat(p) => p
-                            .path()
-                            .and_then(|path| self.expander.parse_path(self.db, path))
-                            .map(LiteralOrConst::Const)
-                            .map(Box::new),
                         _ => None,
                     })
                 };
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs
index cd14f7b855a..b2aab55a6a8 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/pretty.rs
@@ -635,7 +635,7 @@ impl Printer<'_> {
     fn print_literal_or_const(&mut self, literal_or_const: &LiteralOrConst) {
         match literal_or_const {
             LiteralOrConst::Literal(l) => self.print_literal(l),
-            LiteralOrConst::Const(c) => self.print_path(c),
+            LiteralOrConst::Const(c) => self.print_pat(*c),
         }
     }
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
index f506864902c..d4c1db8b95b 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
@@ -788,11 +788,12 @@ impl<'a> AssocItemCollector<'a> {
             };
             self.diagnostics.push(diag);
         }
-        if let errors @ [_, ..] = parse.errors() {
+        let errors = parse.errors();
+        if !errors.is_empty() {
             self.diagnostics.push(DefDiagnostic::macro_expansion_parse_error(
                 self.module_id.local_id,
                 error_call_kind(),
-                errors,
+                errors.into_boxed_slice(),
             ));
         }
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs
index f07b1257662..5790e600f63 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/data/adt.rs
@@ -400,7 +400,7 @@ pub(crate) fn lower_struct(
     item_tree: &ItemTree,
     fields: &Fields,
 ) -> StructKind {
-    let ctx = LowerCtx::with_file_id(db, ast.file_id);
+    let ctx = LowerCtx::new(db, ast.file_id);
 
     match (&ast.value, fields) {
         (ast::StructKind::Tuple(fl), Fields::Tuple(fields)) => {
@@ -415,7 +415,9 @@ pub(crate) fn lower_struct(
                     || FieldData {
                         name: Name::new_tuple_field(i),
                         type_ref: Interned::new(TypeRef::from_ast_opt(&ctx, fd.ty())),
-                        visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())),
+                        visibility: RawVisibility::from_ast(db, fd.visibility(), &mut |range| {
+                            ctx.span_map().span_for_range(range).ctx
+                        }),
                     },
                 );
             }
@@ -433,7 +435,9 @@ pub(crate) fn lower_struct(
                     || FieldData {
                         name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
                         type_ref: Interned::new(TypeRef::from_ast_opt(&ctx, fd.ty())),
-                        visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())),
+                        visibility: RawVisibility::from_ast(db, fd.visibility(), &mut |range| {
+                            ctx.span_map().span_for_range(range).ctx
+                        }),
                     },
                 );
             }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs
index 68f57600ec4..544ed6bc347 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs
@@ -87,14 +87,10 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
     fn file_item_tree(&self, file_id: HirFileId) -> Arc<ItemTree>;
 
     #[salsa::invoke(ItemTree::block_item_tree_query)]
-    fn block_item_tree_query(&self, block_id: BlockId) -> Arc<ItemTree>;
-
-    #[salsa::invoke(crate_def_map_wait)]
-    #[salsa::transparent]
-    fn crate_def_map(&self, krate: CrateId) -> Arc<DefMap>;
+    fn block_item_tree(&self, block_id: BlockId) -> Arc<ItemTree>;
 
     #[salsa::invoke(DefMap::crate_def_map_query)]
-    fn crate_def_map_query(&self, krate: CrateId) -> Arc<DefMap>;
+    fn crate_def_map(&self, krate: CrateId) -> Arc<DefMap>;
 
     /// Computes the block-level `DefMap`.
     #[salsa::invoke(DefMap::block_def_map_query)]
@@ -253,11 +249,6 @@ fn include_macro_invoc(db: &dyn DefDatabase, krate: CrateId) -> Vec<(MacroCallId
         .collect()
 }
 
-fn crate_def_map_wait(db: &dyn DefDatabase, krate: CrateId) -> Arc<DefMap> {
-    let _p = tracing::span!(tracing::Level::INFO, "crate_def_map:wait").entered();
-    db.crate_def_map_query(krate)
-}
-
 fn crate_supports_no_std(db: &dyn DefDatabase, crate_id: CrateId) -> bool {
     let file = db.crate_graph()[crate_id].root_file_id;
     let item_tree = db.file_item_tree(file.into());
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/expander.rs b/src/tools/rust-analyzer/crates/hir-def/src/expander.rs
index b99df1ed593..b0872fcdc0e 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/expander.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/expander.rs
@@ -1,5 +1,7 @@
 //! Macro expansion utilities.
 
+use std::cell::OnceCell;
+
 use base_db::CrateId;
 use cfg::CfgOptions;
 use drop_bomb::DropBomb;
@@ -18,7 +20,7 @@ use crate::{
 #[derive(Debug)]
 pub struct Expander {
     cfg_options: CfgOptions,
-    span_map: SpanMap,
+    span_map: OnceCell<SpanMap>,
     krate: CrateId,
     current_file_id: HirFileId,
     pub(crate) module: ModuleId,
@@ -42,7 +44,7 @@ impl Expander {
             recursion_depth: 0,
             recursion_limit,
             cfg_options: db.crate_graph()[module.krate].cfg_options.clone(),
-            span_map: db.span_map(current_file_id),
+            span_map: OnceCell::new(),
             krate: module.krate,
         }
     }
@@ -100,7 +102,7 @@ impl Expander {
     }
 
     pub fn ctx<'a>(&self, db: &'a dyn DefDatabase) -> LowerCtx<'a> {
-        LowerCtx::new(db, self.span_map.clone(), self.current_file_id)
+        LowerCtx::with_span_map_cell(db, self.current_file_id, self.span_map.clone())
     }
 
     pub(crate) fn in_file<T>(&self, value: T) -> InFile<T> {
@@ -108,7 +110,15 @@ impl Expander {
     }
 
     pub(crate) fn parse_attrs(&self, db: &dyn DefDatabase, owner: &dyn ast::HasAttrs) -> Attrs {
-        Attrs::filter(db, self.krate, RawAttrs::new(db.upcast(), owner, self.span_map.as_ref()))
+        Attrs::filter(
+            db,
+            self.krate,
+            RawAttrs::new(
+                db.upcast(),
+                owner,
+                self.span_map.get_or_init(|| db.span_map(self.current_file_id)).as_ref(),
+            ),
+        )
     }
 
     pub(crate) fn cfg_options(&self) -> &CfgOptions {
@@ -120,7 +130,7 @@ impl Expander {
     }
 
     pub(crate) fn parse_path(&mut self, db: &dyn DefDatabase, path: ast::Path) -> Option<Path> {
-        let ctx = LowerCtx::new(db, self.span_map.clone(), self.current_file_id);
+        let ctx = LowerCtx::with_span_map_cell(db, self.current_file_id, self.span_map.clone());
         Path::from_src(&ctx, path)
     }
 
@@ -165,10 +175,11 @@ impl Expander {
                     let parse = res.value.0.cast::<T>()?;
 
                     self.recursion_depth += 1;
-                    let old_span_map = std::mem::replace(
-                        &mut self.span_map,
-                        SpanMap::ExpansionSpanMap(res.value.1),
-                    );
+                    let old_span_map = OnceCell::new();
+                    if let Some(prev) = self.span_map.take() {
+                        _ = old_span_map.set(prev);
+                    };
+                    _ = self.span_map.set(SpanMap::ExpansionSpanMap(res.value.1));
                     let old_file_id =
                         std::mem::replace(&mut self.current_file_id, macro_file.into());
                     let mark = Mark {
@@ -187,6 +198,6 @@ impl Expander {
 #[derive(Debug)]
 pub struct Mark {
     file_id: HirFileId,
-    span_map: SpanMap,
+    span_map: OnceCell<SpanMap>,
     bomb: DropBomb,
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs
index 26247ba5b50..0cd4a5db8c3 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs
@@ -611,8 +611,10 @@ mod tests {
         let parsed_path_file = syntax::SourceFile::parse(&format!("use {path};"));
         let ast_path =
             parsed_path_file.syntax_node().descendants().find_map(syntax::ast::Path::cast).unwrap();
-        let mod_path =
-            ModPath::from_src(&db, ast_path, db.span_map(pos.file_id.into()).as_ref()).unwrap();
+        let mod_path = ModPath::from_src(&db, ast_path, &mut |range| {
+            db.span_map(pos.file_id.into()).as_ref().span_for_range(range).ctx
+        })
+        .unwrap();
 
         let def_map = module.def_map(&db);
         let resolved = def_map
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs
index 34b2910b4f5..ac0caaf0dc8 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/hir.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/hir.rs
@@ -101,7 +101,7 @@ pub enum Literal {
 /// Used in range patterns.
 pub enum LiteralOrConst {
     Literal(Literal),
-    Const(Path),
+    Const(PatId),
 }
 
 impl Literal {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs
index 8db00f9d76e..ec207a7f965 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs
@@ -251,7 +251,7 @@ impl TypeRef {
                 TypeRef::DynTrait(type_bounds_from_ast(ctx, inner.type_bound_list()))
             }
             ast::Type::MacroType(mt) => match mt.macro_call() {
-                Some(mc) => ctx.ast_id(&mc).map(TypeRef::Macro).unwrap_or(TypeRef::Error),
+                Some(mc) => TypeRef::Macro(ctx.ast_id(&mc)),
                 None => TypeRef::Error,
             },
         }
@@ -398,9 +398,8 @@ pub enum ConstRef {
 impl ConstRef {
     pub(crate) fn from_const_arg(lower_ctx: &LowerCtx<'_>, arg: Option<ast::ConstArg>) -> Self {
         if let Some(arg) = arg {
-            let ast_id = lower_ctx.ast_id(&arg);
             if let Some(expr) = arg.expr() {
-                return Self::from_expr(expr, ast_id);
+                return Self::from_expr(expr, Some(lower_ctx.ast_id(&arg)));
             }
         }
         Self::Scalar(LiteralConstRef::Unknown)
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
index c7cf611589b..bd3d377ec08 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
@@ -29,9 +29,6 @@
 //!
 //! In general, any item in the `ItemTree` stores its `AstId`, which allows mapping it back to its
 //! surface syntax.
-//!
-//! Note that we cannot store [`span::Span`]s inside of this, as typing in an item invalidates its
-//! encompassing span!
 
 mod lower;
 mod pretty;
@@ -50,7 +47,6 @@ use either::Either;
 use hir_expand::{attrs::RawAttrs, name::Name, ExpandTo, HirFileId, InFile};
 use intern::Interned;
 use la_arena::{Arena, Idx, IdxRange, RawIdx};
-use profile::Count;
 use rustc_hash::FxHashMap;
 use smallvec::SmallVec;
 use span::{AstIdNode, FileAstId, Span};
@@ -94,8 +90,6 @@ impl fmt::Debug for RawVisibilityId {
 /// The item tree of a source file.
 #[derive(Debug, Default, Eq, PartialEq)]
 pub struct ItemTree {
-    _c: Count<Self>,
-
     top_level: SmallVec<[ModItem; 1]>,
     attrs: FxHashMap<AttrOwner, RawAttrs>,
 
@@ -263,14 +257,6 @@ impl ItemVisibilities {
     }
 }
 
-static VIS_PUB: RawVisibility = RawVisibility::Public;
-static VIS_PRIV_IMPLICIT: RawVisibility =
-    RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)), VisibilityExplicitness::Implicit);
-static VIS_PRIV_EXPLICIT: RawVisibility =
-    RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)), VisibilityExplicitness::Explicit);
-static VIS_PUB_CRATE: RawVisibility =
-    RawVisibility::Module(ModPath::from_kind(PathKind::Crate), VisibilityExplicitness::Explicit);
-
 #[derive(Default, Debug, Eq, PartialEq)]
 struct ItemTreeData {
     uses: Arena<Use>,
@@ -403,7 +389,7 @@ impl TreeId {
 
     pub(crate) fn item_tree(&self, db: &dyn DefDatabase) -> Arc<ItemTree> {
         match self.block {
-            Some(block) => db.block_item_tree_query(block),
+            Some(block) => db.block_item_tree(block),
             None => db.file_item_tree(self.file),
         }
     }
@@ -562,6 +548,20 @@ impl_index!(fields: Field, variants: Variant, params: Param);
 impl Index<RawVisibilityId> for ItemTree {
     type Output = RawVisibility;
     fn index(&self, index: RawVisibilityId) -> &Self::Output {
+        static VIS_PUB: RawVisibility = RawVisibility::Public;
+        static VIS_PRIV_IMPLICIT: RawVisibility = RawVisibility::Module(
+            ModPath::from_kind(PathKind::Super(0)),
+            VisibilityExplicitness::Implicit,
+        );
+        static VIS_PRIV_EXPLICIT: RawVisibility = RawVisibility::Module(
+            ModPath::from_kind(PathKind::Super(0)),
+            VisibilityExplicitness::Explicit,
+        );
+        static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module(
+            ModPath::from_kind(PathKind::Crate),
+            VisibilityExplicitness::Explicit,
+        );
+
         match index {
             RawVisibilityId::PRIV_IMPLICIT => &VIS_PRIV_IMPLICIT,
             RawVisibilityId::PRIV_EXPLICIT => &VIS_PRIV_EXPLICIT,
@@ -821,11 +821,13 @@ impl Use {
         // Note: The AST unwraps are fine, since if they fail we should have never obtained `index`.
         let ast = InFile::new(file_id, self.ast_id).to_node(db.upcast());
         let ast_use_tree = ast.use_tree().expect("missing `use_tree`");
-        let span_map = db.span_map(file_id);
-        let (_, source_map) = lower::lower_use_tree(db, span_map.as_ref(), ast_use_tree)
-            .expect("failed to lower use tree");
+        let (_, source_map) = lower::lower_use_tree(db, ast_use_tree, &mut |range| {
+            db.span_map(file_id).span_for_range(range).ctx
+        })
+        .expect("failed to lower use tree");
         source_map[index].clone()
     }
+
     /// Maps a `UseTree` contained in this import back to its AST node.
     pub fn use_tree_source_map(
         &self,
@@ -836,10 +838,11 @@ impl Use {
         // Note: The AST unwraps are fine, since if they fail we should have never obtained `index`.
         let ast = InFile::new(file_id, self.ast_id).to_node(db.upcast());
         let ast_use_tree = ast.use_tree().expect("missing `use_tree`");
-        let span_map = db.span_map(file_id);
-        lower::lower_use_tree(db, span_map.as_ref(), ast_use_tree)
-            .expect("failed to lower use tree")
-            .1
+        lower::lower_use_tree(db, ast_use_tree, &mut |range| {
+            db.span_map(file_id).span_for_range(range).ctx
+        })
+        .expect("failed to lower use tree")
+        .1
     }
 }
 
@@ -871,25 +874,19 @@ impl UseTree {
             prefix: Option<ModPath>,
             path: &ModPath,
         ) -> Option<(ModPath, ImportKind)> {
-            match (prefix, &path.kind) {
+            match (prefix, path.kind) {
                 (None, _) => Some((path.clone(), ImportKind::Plain)),
                 (Some(mut prefix), PathKind::Plain) => {
-                    for segment in path.segments() {
-                        prefix.push_segment(segment.clone());
-                    }
+                    prefix.extend(path.segments().iter().cloned());
                     Some((prefix, ImportKind::Plain))
                 }
-                (Some(mut prefix), PathKind::Super(n))
-                    if *n > 0 && prefix.segments().is_empty() =>
-                {
+                (Some(mut prefix), PathKind::Super(n)) if n > 0 && prefix.segments().is_empty() => {
                     // `super::super` + `super::rest`
                     match &mut prefix.kind {
                         PathKind::Super(m) => {
                             cov_mark::hit!(concat_super_mod_paths);
-                            *m += *n;
-                            for segment in path.segments() {
-                                prefix.push_segment(segment.clone());
-                            }
+                            *m += n;
+                            prefix.extend(path.segments().iter().cloned());
                             Some((prefix, ImportKind::Plain))
                         }
                         _ => None,
@@ -963,10 +960,10 @@ impl ModItem {
             | ModItem::Mod(_)
             | ModItem::MacroRules(_)
             | ModItem::Macro2(_) => None,
-            ModItem::MacroCall(call) => Some(AssocItem::MacroCall(*call)),
-            ModItem::Const(konst) => Some(AssocItem::Const(*konst)),
-            ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(*alias)),
-            ModItem::Function(func) => Some(AssocItem::Function(*func)),
+            &ModItem::MacroCall(call) => Some(AssocItem::MacroCall(call)),
+            &ModItem::Const(konst) => Some(AssocItem::Const(konst)),
+            &ModItem::TypeAlias(alias) => Some(AssocItem::TypeAlias(alias)),
+            &ModItem::Function(func) => Some(AssocItem::Function(func)),
         }
     }
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
index 21cffafa952..bf3d54f4caf 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
@@ -4,7 +4,7 @@ use std::collections::hash_map::Entry;
 
 use hir_expand::{mod_path::path, name, name::AsName, span_map::SpanMapRef, HirFileId};
 use la_arena::Arena;
-use span::AstIdMap;
+use span::{AstIdMap, SyntaxContextId};
 use syntax::{
     ast::{self, HasModuleItem, HasName, HasTypeBounds, IsString},
     AstNode,
@@ -45,7 +45,7 @@ impl<'a> Ctx<'a> {
             db,
             tree: ItemTree::default(),
             source_ast_id_map: db.ast_id_map(file),
-            body_ctx: crate::lower::LowerCtx::with_file_id(db, file),
+            body_ctx: crate::lower::LowerCtx::new(db, file),
         }
     }
 
@@ -535,7 +535,9 @@ impl<'a> Ctx<'a> {
     fn lower_use(&mut self, use_item: &ast::Use) -> Option<FileItemTreeId<Use>> {
         let visibility = self.lower_visibility(use_item);
         let ast_id = self.source_ast_id_map.ast_id(use_item);
-        let (use_tree, _) = lower_use_tree(self.db, self.span_map(), use_item.use_tree()?)?;
+        let (use_tree, _) = lower_use_tree(self.db, use_item.use_tree()?, &mut |range| {
+            self.span_map().span_for_range(range).ctx
+        })?;
 
         let res = Use { visibility, ast_id, use_tree };
         Some(id(self.data().uses.alloc(res)))
@@ -558,7 +560,9 @@ impl<'a> Ctx<'a> {
 
     fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> {
         let span_map = self.span_map();
-        let path = Interned::new(ModPath::from_src(self.db.upcast(), m.path()?, span_map)?);
+        let path = Interned::new(ModPath::from_src(self.db.upcast(), m.path()?, &mut |range| {
+            span_map.span_for_range(range).ctx
+        })?);
         let ast_id = self.source_ast_id_map.ast_id(m);
         let expand_to = hir_expand::ExpandTo::from_call_site(m);
         let res = MacroCall {
@@ -672,8 +676,9 @@ impl<'a> Ctx<'a> {
     }
 
     fn lower_visibility(&mut self, item: &dyn ast::HasVisibility) -> RawVisibilityId {
-        let vis =
-            RawVisibility::from_opt_ast_with_span_map(self.db, item.visibility(), self.span_map());
+        let vis = RawVisibility::from_ast(self.db, item.visibility(), &mut |range| {
+            self.span_map().span_for_range(range).ctx
+        });
         self.data().vis.alloc(vis)
     }
 
@@ -745,12 +750,15 @@ fn lower_abi(abi: ast::Abi) -> Interned<str> {
 
 struct UseTreeLowering<'a> {
     db: &'a dyn DefDatabase,
-    span_map: SpanMapRef<'a>,
     mapping: Arena<ast::UseTree>,
 }
 
 impl UseTreeLowering<'_> {
-    fn lower_use_tree(&mut self, tree: ast::UseTree) -> Option<UseTree> {
+    fn lower_use_tree(
+        &mut self,
+        tree: ast::UseTree,
+        span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId,
+    ) -> Option<UseTree> {
         if let Some(use_tree_list) = tree.use_tree_list() {
             let prefix = match tree.path() {
                 // E.g. use something::{{{inner}}};
@@ -758,15 +766,17 @@ impl UseTreeLowering<'_> {
                 // E.g. `use something::{inner}` (prefix is `None`, path is `something`)
                 // or `use something::{path::{inner::{innerer}}}` (prefix is `something::path`, path is `inner`)
                 Some(path) => {
-                    match ModPath::from_src(self.db.upcast(), path, self.span_map) {
+                    match ModPath::from_src(self.db.upcast(), path, span_for_range) {
                         Some(it) => Some(it),
                         None => return None, // FIXME: report errors somewhere
                     }
                 }
             };
 
-            let list =
-                use_tree_list.use_trees().filter_map(|tree| self.lower_use_tree(tree)).collect();
+            let list = use_tree_list
+                .use_trees()
+                .filter_map(|tree| self.lower_use_tree(tree, span_for_range))
+                .collect();
 
             Some(
                 self.use_tree(
@@ -777,7 +787,7 @@ impl UseTreeLowering<'_> {
         } else {
             let is_glob = tree.star_token().is_some();
             let path = match tree.path() {
-                Some(path) => Some(ModPath::from_src(self.db.upcast(), path, self.span_map)?),
+                Some(path) => Some(ModPath::from_src(self.db.upcast(), path, span_for_range)?),
                 None => None,
             };
             let alias = tree.rename().map(|a| {
@@ -813,10 +823,10 @@ impl UseTreeLowering<'_> {
 
 pub(crate) fn lower_use_tree(
     db: &dyn DefDatabase,
-    span_map: SpanMapRef<'_>,
     tree: ast::UseTree,
+    span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId,
 ) -> Option<(UseTree, Arena<ast::UseTree>)> {
-    let mut lowering = UseTreeLowering { db, span_map, mapping: Arena::new() };
-    let tree = lowering.lower_use_tree(tree)?;
+    let mut lowering = UseTreeLowering { db, mapping: Arena::new() };
+    let tree = lowering.lower_use_tree(tree, span_for_range)?;
     Some((tree, lowering.mapping))
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
index de3ab57a124..d63f2268aa4 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
@@ -1341,8 +1341,11 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
         let expands_to = hir_expand::ExpandTo::from_call_site(self.value);
         let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value));
         let span_map = db.span_map(self.file_id);
-        let path =
-            self.value.path().and_then(|path| path::ModPath::from_src(db, path, span_map.as_ref()));
+        let path = self.value.path().and_then(|path| {
+            path::ModPath::from_src(db, path, &mut |range| {
+                span_map.as_ref().span_for_range(range).ctx
+            })
+        });
 
         let Some(path) = path else {
             return Ok(ExpandResult::only_err(ExpandError::other("malformed macro invocation")));
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/lower.rs
index 2fa6acdf175..d574d80a8e0 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lower.rs
@@ -13,39 +13,36 @@ use crate::{db::DefDatabase, path::Path};
 
 pub struct LowerCtx<'a> {
     pub db: &'a dyn DefDatabase,
-    span_map: SpanMap,
-    // FIXME: This optimization is probably pointless, ast id map should pretty much always exist anyways.
-    ast_id_map: Option<(HirFileId, OnceCell<Arc<AstIdMap>>)>,
+    file_id: HirFileId,
+    span_map: OnceCell<SpanMap>,
+    ast_id_map: OnceCell<Arc<AstIdMap>>,
 }
 
 impl<'a> LowerCtx<'a> {
-    pub fn new(db: &'a dyn DefDatabase, span_map: SpanMap, file_id: HirFileId) -> Self {
-        LowerCtx { db, span_map, ast_id_map: Some((file_id, OnceCell::new())) }
+    pub fn new(db: &'a dyn DefDatabase, file_id: HirFileId) -> Self {
+        LowerCtx { db, file_id, span_map: OnceCell::new(), ast_id_map: OnceCell::new() }
     }
 
-    pub fn with_file_id(db: &'a dyn DefDatabase, file_id: HirFileId) -> Self {
-        LowerCtx {
-            db,
-            span_map: db.span_map(file_id),
-            ast_id_map: Some((file_id, OnceCell::new())),
-        }
-    }
-
-    pub fn with_span_map(db: &'a dyn DefDatabase, span_map: SpanMap) -> Self {
-        LowerCtx { db, span_map, ast_id_map: None }
+    pub fn with_span_map_cell(
+        db: &'a dyn DefDatabase,
+        file_id: HirFileId,
+        span_map: OnceCell<SpanMap>,
+    ) -> Self {
+        LowerCtx { db, file_id, span_map, ast_id_map: OnceCell::new() }
     }
 
     pub(crate) fn span_map(&self) -> SpanMapRef<'_> {
-        self.span_map.as_ref()
+        self.span_map.get_or_init(|| self.db.span_map(self.file_id)).as_ref()
     }
 
     pub(crate) fn lower_path(&self, ast: ast::Path) -> Option<Path> {
         Path::from_src(self, ast)
     }
 
-    pub(crate) fn ast_id<N: AstIdNode>(&self, item: &N) -> Option<AstId<N>> {
-        let &(file_id, ref ast_id_map) = self.ast_id_map.as_ref()?;
-        let ast_id_map = ast_id_map.get_or_init(|| self.db.ast_id_map(file_id));
-        Some(InFile::new(file_id, ast_id_map.ast_id(item)))
+    pub(crate) fn ast_id<N: AstIdNode>(&self, item: &N) -> AstId<N> {
+        InFile::new(
+            self.file_id,
+            self.ast_id_map.get_or_init(|| self.db.ast_id_map(self.file_id)).ast_id(item),
+        )
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
index 270468ad0a6..764617eafb7 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
@@ -65,7 +65,6 @@ use hir_expand::{
 };
 use itertools::Itertools;
 use la_arena::Arena;
-use profile::Count;
 use rustc_hash::{FxHashMap, FxHashSet};
 use span::FileAstId;
 use stdx::format_to;
@@ -95,7 +94,6 @@ use crate::{
 /// is computed by the `block_def_map` query.
 #[derive(Debug, PartialEq, Eq)]
 pub struct DefMap {
-    _c: Count<Self>,
     /// When this is a block def map, this will hold the block id of the block and module that
     /// contains this block.
     block: Option<BlockInfo>,
@@ -154,6 +152,23 @@ struct DefMapCrateData {
 }
 
 impl DefMapCrateData {
+    fn new(edition: Edition) -> Self {
+        Self {
+            extern_prelude: FxHashMap::default(),
+            exported_derives: FxHashMap::default(),
+            fn_proc_macro_mapping: FxHashMap::default(),
+            proc_macro_loading_error: None,
+            registered_attrs: Vec::new(),
+            registered_tools: Vec::new(),
+            unstable_features: FxHashSet::default(),
+            rustc_coherence_is_core: false,
+            no_core: false,
+            no_std: false,
+            edition,
+            recursion_limit: None,
+        }
+    }
+
     fn shrink_to_fit(&mut self) {
         let Self {
             extern_prelude,
@@ -305,67 +320,67 @@ impl DefMap {
     /// The module id of a crate or block root.
     pub const ROOT: LocalModuleId = LocalModuleId::from_raw(la_arena::RawIdx::from_u32(0));
 
-    pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<DefMap> {
+    pub(crate) fn crate_def_map_query(db: &dyn DefDatabase, crate_id: CrateId) -> Arc<DefMap> {
         let crate_graph = db.crate_graph();
-        let krate_name = crate_graph[krate].display_name.as_deref().unwrap_or_default();
-
-        let _p = tracing::span!(tracing::Level::INFO, "crate_def_map_query", ?krate_name).entered();
+        let krate = &crate_graph[crate_id];
+        let name = krate.display_name.as_deref().unwrap_or_default();
+        let _p = tracing::span!(tracing::Level::INFO, "crate_def_map_query", ?name).entered();
 
-        let crate_graph = db.crate_graph();
+        let module_data = ModuleData::new(
+            ModuleOrigin::CrateRoot { definition: krate.root_file_id },
+            Visibility::Public,
+        );
 
-        let edition = crate_graph[krate].edition;
-        let origin = ModuleOrigin::CrateRoot { definition: crate_graph[krate].root_file_id };
-        let def_map = DefMap::empty(krate, edition, ModuleData::new(origin, Visibility::Public));
-        let def_map = collector::collect_defs(
-            db,
-            def_map,
-            TreeId::new(crate_graph[krate].root_file_id.into(), None),
+        let def_map = DefMap::empty(
+            crate_id,
+            Arc::new(DefMapCrateData::new(krate.edition)),
+            module_data,
+            None,
         );
+        let def_map =
+            collector::collect_defs(db, def_map, TreeId::new(krate.root_file_id.into(), None));
 
         Arc::new(def_map)
     }
 
     pub(crate) fn block_def_map_query(db: &dyn DefDatabase, block_id: BlockId) -> Arc<DefMap> {
-        let block: BlockLoc = block_id.lookup(db);
-
-        let parent_map = block.module.def_map(db);
-        let krate = block.module.krate;
-        let local_id = LocalModuleId::from_raw(la_arena::RawIdx::from(0));
-        // NB: we use `None` as block here, which would be wrong for implicit
-        // modules declared by blocks with items. At the moment, we don't use
-        // this visibility for anything outside IDE, so that's probably OK.
+        let BlockLoc { ast_id, module } = block_id.lookup(db);
+
         let visibility = Visibility::Module(
-            ModuleId { krate, local_id, block: None },
+            ModuleId { krate: module.krate, local_id: Self::ROOT, block: module.block },
             VisibilityExplicitness::Implicit,
         );
-        let module_data = ModuleData::new(
-            ModuleOrigin::BlockExpr { block: block.ast_id, id: block_id },
-            visibility,
+        let module_data =
+            ModuleData::new(ModuleOrigin::BlockExpr { block: ast_id, id: block_id }, visibility);
+
+        let parent_map = module.def_map(db);
+        let def_map = DefMap::empty(
+            module.krate,
+            parent_map.data.clone(),
+            module_data,
+            Some(BlockInfo {
+                block: block_id,
+                parent: BlockRelativeModuleId { block: module.block, local_id: module.local_id },
+            }),
         );
 
-        let mut def_map = DefMap::empty(krate, parent_map.data.edition, module_data);
-        def_map.data = parent_map.data.clone();
-        def_map.block = Some(BlockInfo {
-            block: block_id,
-            parent: BlockRelativeModuleId {
-                block: block.module.block,
-                local_id: block.module.local_id,
-            },
-        });
-
         let def_map =
-            collector::collect_defs(db, def_map, TreeId::new(block.ast_id.file_id, Some(block_id)));
+            collector::collect_defs(db, def_map, TreeId::new(ast_id.file_id, Some(block_id)));
         Arc::new(def_map)
     }
 
-    fn empty(krate: CrateId, edition: Edition, module_data: ModuleData) -> DefMap {
+    fn empty(
+        krate: CrateId,
+        crate_data: Arc<DefMapCrateData>,
+        module_data: ModuleData,
+        block: Option<BlockInfo>,
+    ) -> DefMap {
         let mut modules: Arena<ModuleData> = Arena::default();
         let root = modules.alloc(module_data);
         assert_eq!(root, Self::ROOT);
 
         DefMap {
-            _c: Count::new(),
-            block: None,
+            block,
             modules,
             krate,
             prelude: None,
@@ -373,23 +388,36 @@ impl DefMap {
             derive_helpers_in_scope: FxHashMap::default(),
             diagnostics: Vec::new(),
             enum_definitions: FxHashMap::default(),
-            data: Arc::new(DefMapCrateData {
-                extern_prelude: FxHashMap::default(),
-                exported_derives: FxHashMap::default(),
-                fn_proc_macro_mapping: FxHashMap::default(),
-                proc_macro_loading_error: None,
-                registered_attrs: Vec::new(),
-                registered_tools: Vec::new(),
-                unstable_features: FxHashSet::default(),
-                rustc_coherence_is_core: false,
-                no_core: false,
-                no_std: false,
-                edition,
-                recursion_limit: None,
-            }),
+            data: crate_data,
+        }
+    }
+    fn shrink_to_fit(&mut self) {
+        // Exhaustive match to require handling new fields.
+        let Self {
+            macro_use_prelude,
+            diagnostics,
+            modules,
+            derive_helpers_in_scope,
+            block: _,
+            krate: _,
+            prelude: _,
+            data: _,
+            enum_definitions,
+        } = self;
+
+        macro_use_prelude.shrink_to_fit();
+        diagnostics.shrink_to_fit();
+        modules.shrink_to_fit();
+        derive_helpers_in_scope.shrink_to_fit();
+        enum_definitions.shrink_to_fit();
+        for (_, module) in modules.iter_mut() {
+            module.children.shrink_to_fit();
+            module.scope.shrink_to_fit();
         }
     }
+}
 
+impl DefMap {
     pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator<Item = LocalModuleId> + '_ {
         self.modules
             .iter()
@@ -440,26 +468,6 @@ impl DefMap {
         self.krate
     }
 
-    pub(crate) fn block_id(&self) -> Option<BlockId> {
-        self.block.map(|block| block.block)
-    }
-
-    pub(crate) fn prelude(&self) -> Option<(ModuleId, Option<UseId>)> {
-        self.prelude
-    }
-
-    pub(crate) fn extern_prelude(
-        &self,
-    ) -> impl Iterator<Item = (&Name, (CrateRootModuleId, Option<ExternCrateId>))> + '_ {
-        self.data.extern_prelude.iter().map(|(name, &def)| (name, def))
-    }
-
-    pub(crate) fn macro_use_prelude(
-        &self,
-    ) -> impl Iterator<Item = (&Name, (MacroId, Option<ExternCrateId>))> + '_ {
-        self.macro_use_prelude.iter().map(|(name, &def)| (name, def))
-    }
-
     pub fn module_id(&self, local_id: LocalModuleId) -> ModuleId {
         let block = self.block.map(|b| b.block);
         ModuleId { krate: self.krate, local_id, block }
@@ -475,68 +483,6 @@ impl DefMap {
         self.module_id(Self::ROOT)
     }
 
-    pub(crate) fn resolve_path(
-        &self,
-        db: &dyn DefDatabase,
-        original_module: LocalModuleId,
-        path: &ModPath,
-        shadow: BuiltinShadowMode,
-        expected_macro_subns: Option<MacroSubNs>,
-    ) -> (PerNs, Option<usize>) {
-        let res = self.resolve_path_fp_with_macro(
-            db,
-            ResolveMode::Other,
-            original_module,
-            path,
-            shadow,
-            expected_macro_subns,
-        );
-        (res.resolved_def, res.segment_index)
-    }
-
-    pub(crate) fn resolve_path_locally(
-        &self,
-        db: &dyn DefDatabase,
-        original_module: LocalModuleId,
-        path: &ModPath,
-        shadow: BuiltinShadowMode,
-    ) -> (PerNs, Option<usize>) {
-        let res = self.resolve_path_fp_with_macro_single(
-            db,
-            ResolveMode::Other,
-            original_module,
-            path,
-            shadow,
-            None, // Currently this function isn't used for macro resolution.
-        );
-        (res.resolved_def, res.segment_index)
-    }
-
-    /// Ascends the `DefMap` hierarchy and calls `f` with every `DefMap` and containing module.
-    ///
-    /// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns
-    /// `None`, iteration continues.
-    pub(crate) fn with_ancestor_maps<T>(
-        &self,
-        db: &dyn DefDatabase,
-        local_mod: LocalModuleId,
-        f: &mut dyn FnMut(&DefMap, LocalModuleId) -> Option<T>,
-    ) -> Option<T> {
-        if let Some(it) = f(self, local_mod) {
-            return Some(it);
-        }
-        let mut block = self.block;
-        while let Some(block_info) = block {
-            let parent = block_info.parent.def_map(db, self.krate);
-            if let Some(it) = f(&parent, block_info.parent.local_id) {
-                return Some(it);
-            }
-            block = parent.block;
-        }
-
-        None
-    }
-
     /// If this `DefMap` is for a block expression, returns the module containing the block (which
     /// might again be a block, or a module inside a block).
     pub fn parent(&self) -> Option<ModuleId> {
@@ -559,6 +505,16 @@ impl DefMap {
         }
     }
 
+    /// Get a reference to the def map's diagnostics.
+    pub fn diagnostics(&self) -> &[DefDiagnostic] {
+        self.diagnostics.as_slice()
+    }
+
+    pub fn recursion_limit(&self) -> u32 {
+        // 128 is the default in rustc
+        self.data.recursion_limit.unwrap_or(128)
+    }
+
     // FIXME: this can use some more human-readable format (ideally, an IR
     // even), as this should be a great debugging aid.
     pub fn dump(&self, db: &dyn DefDatabase) -> String {
@@ -608,41 +564,89 @@ impl DefMap {
         format_to!(buf, "crate scope\n");
         buf
     }
+}
 
-    fn shrink_to_fit(&mut self) {
-        // Exhaustive match to require handling new fields.
-        let Self {
-            _c: _,
-            macro_use_prelude,
-            diagnostics,
-            modules,
-            derive_helpers_in_scope,
-            block: _,
-            krate: _,
-            prelude: _,
-            data: _,
-            enum_definitions,
-        } = self;
+impl DefMap {
+    pub(crate) fn block_id(&self) -> Option<BlockId> {
+        self.block.map(|block| block.block)
+    }
 
-        macro_use_prelude.shrink_to_fit();
-        diagnostics.shrink_to_fit();
-        modules.shrink_to_fit();
-        derive_helpers_in_scope.shrink_to_fit();
-        enum_definitions.shrink_to_fit();
-        for (_, module) in modules.iter_mut() {
-            module.children.shrink_to_fit();
-            module.scope.shrink_to_fit();
-        }
+    pub(crate) fn prelude(&self) -> Option<(ModuleId, Option<UseId>)> {
+        self.prelude
     }
 
-    /// Get a reference to the def map's diagnostics.
-    pub fn diagnostics(&self) -> &[DefDiagnostic] {
-        self.diagnostics.as_slice()
+    pub(crate) fn extern_prelude(
+        &self,
+    ) -> impl Iterator<Item = (&Name, (CrateRootModuleId, Option<ExternCrateId>))> + '_ {
+        self.data.extern_prelude.iter().map(|(name, &def)| (name, def))
     }
 
-    pub fn recursion_limit(&self) -> u32 {
-        // 128 is the default in rustc
-        self.data.recursion_limit.unwrap_or(128)
+    pub(crate) fn macro_use_prelude(
+        &self,
+    ) -> impl Iterator<Item = (&Name, (MacroId, Option<ExternCrateId>))> + '_ {
+        self.macro_use_prelude.iter().map(|(name, &def)| (name, def))
+    }
+
+    pub(crate) fn resolve_path(
+        &self,
+        db: &dyn DefDatabase,
+        original_module: LocalModuleId,
+        path: &ModPath,
+        shadow: BuiltinShadowMode,
+        expected_macro_subns: Option<MacroSubNs>,
+    ) -> (PerNs, Option<usize>) {
+        let res = self.resolve_path_fp_with_macro(
+            db,
+            ResolveMode::Other,
+            original_module,
+            path,
+            shadow,
+            expected_macro_subns,
+        );
+        (res.resolved_def, res.segment_index)
+    }
+
+    pub(crate) fn resolve_path_locally(
+        &self,
+        db: &dyn DefDatabase,
+        original_module: LocalModuleId,
+        path: &ModPath,
+        shadow: BuiltinShadowMode,
+    ) -> (PerNs, Option<usize>) {
+        let res = self.resolve_path_fp_with_macro_single(
+            db,
+            ResolveMode::Other,
+            original_module,
+            path,
+            shadow,
+            None, // Currently this function isn't used for macro resolution.
+        );
+        (res.resolved_def, res.segment_index)
+    }
+
+    /// Ascends the `DefMap` hierarchy and calls `f` with every `DefMap` and containing module.
+    ///
+    /// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns
+    /// `None`, iteration continues.
+    pub(crate) fn with_ancestor_maps<T>(
+        &self,
+        db: &dyn DefDatabase,
+        local_mod: LocalModuleId,
+        f: &mut dyn FnMut(&DefMap, LocalModuleId) -> Option<T>,
+    ) -> Option<T> {
+        if let Some(it) = f(self, local_mod) {
+            return Some(it);
+        }
+        let mut block = self.block;
+        while let Some(block_info) = block {
+            let parent = block_info.parent.def_map(db, self.krate);
+            if let Some(it) = f(&parent, block_info.parent.local_id) {
+                return Some(it);
+            }
+            block = parent.block;
+        }
+
+        None
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
index 538e735688b..f9fe6d3b903 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
@@ -64,19 +64,18 @@ static FIXED_POINT_LIMIT: Limit = Limit::new(8192);
 pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeId) -> DefMap {
     let crate_graph = db.crate_graph();
 
-    let mut deps = FxHashMap::default();
-    // populate external prelude and dependency list
     let krate = &crate_graph[def_map.krate];
+
+    // populate external prelude and dependency list
+    let mut deps =
+        FxHashMap::with_capacity_and_hasher(krate.dependencies.len(), Default::default());
     for dep in &krate.dependencies {
         tracing::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
 
         deps.insert(dep.as_name(), dep.clone());
     }
 
-    let cfg_options = &krate.cfg_options;
-
-    let is_proc_macro = krate.is_proc_macro;
-    let proc_macros = if is_proc_macro {
+    let proc_macros = if krate.is_proc_macro {
         match db.proc_macros().get(&def_map.krate) {
             Some(Ok(proc_macros)) => {
                 Ok(proc_macros
@@ -124,11 +123,11 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, def_map: DefMap, tree_id: TreeI
         indeterminate_imports: Vec::new(),
         unresolved_macros: Vec::new(),
         mod_dirs: FxHashMap::default(),
-        cfg_options,
+        cfg_options: &krate.cfg_options,
         proc_macros,
         from_glob_import: Default::default(),
         skip_attrs: Default::default(),
-        is_proc_macro,
+        is_proc_macro: krate.is_proc_macro,
     };
     if tree_id.is_block() {
         collector.seed_with_inner(tree_id);
@@ -302,71 +301,50 @@ impl DefCollector<'_> {
                     return;
                 }
             }
-            let attr_name = match attr.path.as_ident() {
-                Some(name) => name,
-                None => continue,
-            };
+            let Some(attr_name) = attr.path.as_ident() else { continue };
 
-            if *attr_name == hir_expand::name![recursion_limit] {
-                if let Some(limit) = attr.string_value() {
-                    if let Ok(limit) = limit.parse() {
-                        crate_data.recursion_limit = Some(limit);
+            match () {
+                () if *attr_name == hir_expand::name![recursion_limit] => {
+                    if let Some(limit) = attr.string_value() {
+                        if let Ok(limit) = limit.parse() {
+                            crate_data.recursion_limit = Some(limit);
+                        }
                     }
                 }
-                continue;
-            }
-
-            if *attr_name == hir_expand::name![crate_type] {
-                if let Some("proc-macro") = attr.string_value().map(SmolStr::as_str) {
-                    self.is_proc_macro = true;
+                () if *attr_name == hir_expand::name![crate_type] => {
+                    if let Some("proc-macro") = attr.string_value().map(SmolStr::as_str) {
+                        self.is_proc_macro = true;
+                    }
                 }
-                continue;
-            }
-
-            if *attr_name == hir_expand::name![no_core] {
-                crate_data.no_core = true;
-                continue;
-            }
-
-            if *attr_name == hir_expand::name![no_std] {
-                crate_data.no_std = true;
-                continue;
-            }
-
-            if attr_name.as_text().as_deref() == Some("rustc_coherence_is_core") {
-                crate_data.rustc_coherence_is_core = true;
-                continue;
-            }
-
-            if *attr_name == hir_expand::name![feature] {
-                let features = attr
-                    .parse_path_comma_token_tree(self.db.upcast())
-                    .into_iter()
-                    .flatten()
-                    .filter_map(|(feat, _)| match feat.segments() {
-                        [name] => Some(name.to_smol_str()),
-                        _ => None,
-                    });
-                crate_data.unstable_features.extend(features);
-            }
-
-            let attr_is_register_like = *attr_name == hir_expand::name![register_attr]
-                || *attr_name == hir_expand::name![register_tool];
-            if !attr_is_register_like {
-                continue;
-            }
-
-            let registered_name = match attr.single_ident_value() {
-                Some(ident) => ident.as_name(),
-                _ => continue,
-            };
-
-            if *attr_name == hir_expand::name![register_attr] {
-                crate_data.registered_attrs.push(registered_name.to_smol_str());
-                cov_mark::hit!(register_attr);
-            } else {
-                crate_data.registered_tools.push(registered_name.to_smol_str());
-                cov_mark::hit!(register_tool);
+                () if *attr_name == hir_expand::name![no_core] => crate_data.no_core = true,
+                () if *attr_name == hir_expand::name![no_std] => crate_data.no_std = true,
+                () if attr_name.as_text().as_deref() == Some("rustc_coherence_is_core") => {
+                    crate_data.rustc_coherence_is_core = true;
+                }
+                () if *attr_name == hir_expand::name![feature] => {
+                    let features = attr
+                        .parse_path_comma_token_tree(self.db.upcast())
+                        .into_iter()
+                        .flatten()
+                        .filter_map(|(feat, _)| match feat.segments() {
+                            [name] => Some(name.to_smol_str()),
+                            _ => None,
+                        });
+                    crate_data.unstable_features.extend(features);
+                }
+                () if *attr_name == hir_expand::name![register_attr] => {
+                    if let Some(ident) = attr.single_ident_value() {
+                        crate_data.registered_attrs.push(ident.text.clone());
+                        cov_mark::hit!(register_attr);
+                    }
+                }
+                () if *attr_name == hir_expand::name![register_tool] => {
+                    if let Some(ident) = attr.single_ident_value() {
+                        crate_data.registered_tools.push(ident.text.clone());
+                        cov_mark::hit!(register_tool);
+                    }
+                }
+                () => (),
             }
         }
 
@@ -409,6 +387,7 @@ impl DefCollector<'_> {
         // main name resolution fixed-point loop.
         let mut i = 0;
         'resolve_attr: loop {
+            let _p = tracing::span!(tracing::Level::INFO, "resolve_macros loop").entered();
             'resolve_macros: loop {
                 self.db.unwind_if_cancelled();
 
@@ -466,9 +445,8 @@ impl DefCollector<'_> {
             // Additionally, while the proc macro entry points must be `pub`, they are not publicly
             // exported in type/value namespace. This function reduces the visibility of all items
             // in the crate root that aren't proc macros.
-            let root = DefMap::ROOT;
-            let module_id = self.def_map.module_id(root);
-            let root = &mut self.def_map.modules[root];
+            let module_id = self.def_map.module_id(DefMap::ROOT);
+            let root = &mut self.def_map.modules[DefMap::ROOT];
             root.scope.censor_non_proc_macros(module_id);
         }
     }
@@ -828,12 +806,10 @@ impl DefCollector<'_> {
                     return PartialResolvedImport::Unresolved;
                 }
 
-                if let Some(krate) = res.krate {
-                    if krate != self.def_map.krate {
-                        return PartialResolvedImport::Resolved(
-                            def.filter_visibility(|v| matches!(v, Visibility::Public)),
-                        );
-                    }
+                if res.from_differing_crate {
+                    return PartialResolvedImport::Resolved(
+                        def.filter_visibility(|v| matches!(v, Visibility::Public)),
+                    );
                 }
 
                 // Check whether all namespaces are resolved.
@@ -1408,7 +1384,9 @@ impl DefCollector<'_> {
         // First, fetch the raw expansion result for purposes of error reporting. This goes through
         // `parse_macro_expansion_error` to avoid depending on the full expansion result (to improve
         // incrementality).
-        let ExpandResult { value, err } = self.db.parse_macro_expansion_error(macro_call_id);
+        // FIXME: This kind of error fetching feels a bit odd?
+        let ExpandResult { value: errors, err } =
+            self.db.parse_macro_expansion_error(macro_call_id);
         if let Some(err) = err {
             let loc: MacroCallLoc = self.db.lookup_intern_macro_call(macro_call_id);
             let diag = match err {
@@ -1422,7 +1400,7 @@ impl DefCollector<'_> {
 
             self.def_map.diagnostics.push(diag);
         }
-        if let errors @ [_, ..] = &*value {
+        if !errors.is_empty() {
             let loc: MacroCallLoc = self.db.lookup_intern_macro_call(macro_call_id);
             let diag = DefDiagnostic::macro_expansion_parse_error(module_id, loc.kind, errors);
             self.def_map.diagnostics.push(diag);
@@ -1920,7 +1898,7 @@ impl ModCollector<'_, '_> {
     }
 
     fn collect_module(&mut self, module_id: FileItemTreeId<Mod>, attrs: &Attrs) {
-        let path_attr = attrs.by_key("path").string_value();
+        let path_attr = attrs.by_key("path").string_value().map(SmolStr::as_str);
         let is_macro_use = attrs.by_key("macro_use").exists();
         let module = &self.item_tree[module_id];
         match &module.kind {
@@ -1934,25 +1912,26 @@ impl ModCollector<'_, '_> {
                     module_id,
                 );
 
-                if let Some(mod_dir) = self.mod_dir.descend_into_definition(&module.name, path_attr)
-                {
-                    ModCollector {
-                        def_collector: &mut *self.def_collector,
-                        macro_depth: self.macro_depth,
-                        module_id,
-                        tree_id: self.tree_id,
-                        item_tree: self.item_tree,
-                        mod_dir,
-                    }
-                    .collect_in_top_module(items);
-                    if is_macro_use {
-                        self.import_all_legacy_macros(module_id);
-                    }
+                let Some(mod_dir) = self.mod_dir.descend_into_definition(&module.name, path_attr)
+                else {
+                    return;
+                };
+                ModCollector {
+                    def_collector: &mut *self.def_collector,
+                    macro_depth: self.macro_depth,
+                    module_id,
+                    tree_id: self.tree_id,
+                    item_tree: self.item_tree,
+                    mod_dir,
+                }
+                .collect_in_top_module(items);
+                if is_macro_use {
+                    self.import_all_legacy_macros(module_id);
                 }
             }
             // out of line module, resolve, parse and recurse
             ModKind::Outline => {
-                let ast_id = AstId::new(self.tree_id.file_id(), module.ast_id);
+                let ast_id = AstId::new(self.file_id(), module.ast_id);
                 let db = self.def_collector.db;
                 match self.mod_dir.resolve_declaration(db, self.file_id(), &module.name, path_attr)
                 {
@@ -2445,7 +2424,7 @@ mod tests {
     use base_db::SourceDatabase;
     use test_fixture::WithFixture;
 
-    use crate::test_db::TestDB;
+    use crate::{nameres::DefMapCrateData, test_db::TestDB};
 
     use super::*;
 
@@ -2476,8 +2455,12 @@ mod tests {
 
         let edition = db.crate_graph()[krate].edition;
         let module_origin = ModuleOrigin::CrateRoot { definition: file_id };
-        let def_map =
-            DefMap::empty(krate, edition, ModuleData::new(module_origin, Visibility::Public));
+        let def_map = DefMap::empty(
+            krate,
+            Arc::new(DefMapCrateData::new(edition)),
+            ModuleData::new(module_origin, Visibility::Public),
+            None,
+        );
         do_collect_defs(&db, def_map)
     }
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs
index 161b2c05990..8c7fdaaf58b 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/diagnostics.rs
@@ -1,5 +1,7 @@
 //! Diagnostics emitted during DefMap construction.
 
+use std::ops::Not;
+
 use base_db::CrateId;
 use cfg::{CfgExpr, CfgOptions};
 use hir_expand::{attrs::AttrId, ErasedAstId, MacroCallKind};
@@ -16,27 +18,16 @@ use crate::{
 #[derive(Debug, PartialEq, Eq)]
 pub enum DefDiagnosticKind {
     UnresolvedModule { ast: AstId<ast::Module>, candidates: Box<[String]> },
-
     UnresolvedExternCrate { ast: AstId<ast::ExternCrate> },
-
     UnresolvedImport { id: ItemTreeId<item_tree::Use>, index: Idx<ast::UseTree> },
-
     UnconfiguredCode { ast: ErasedAstId, cfg: CfgExpr, opts: CfgOptions },
-
     UnresolvedProcMacro { ast: MacroCallKind, krate: CrateId },
-
     UnresolvedMacroCall { ast: MacroCallKind, path: ModPath },
-
     MacroError { ast: MacroCallKind, message: String },
-
     MacroExpansionParseError { ast: MacroCallKind, errors: Box<[SyntaxError]> },
-
     UnimplementedBuiltinMacro { ast: AstId<ast::Macro> },
-
     InvalidDeriveTarget { ast: AstId<ast::Item>, id: usize },
-
     MalformedDerive { ast: AstId<ast::Adt>, id: usize },
-
     MacroDefError { ast: AstId<ast::Macro>, message: String },
 }
 
@@ -45,11 +36,12 @@ pub struct DefDiagnostics(Option<triomphe::Arc<Box<[DefDiagnostic]>>>);
 
 impl DefDiagnostics {
     pub fn new(diagnostics: Vec<DefDiagnostic>) -> Self {
-        Self(if diagnostics.is_empty() {
-            None
-        } else {
-            Some(triomphe::Arc::new(diagnostics.into_boxed_slice()))
-        })
+        Self(
+            diagnostics
+                .is_empty()
+                .not()
+                .then(|| triomphe::Arc::new(diagnostics.into_boxed_slice())),
+        )
     }
 
     pub fn iter(&self) -> impl Iterator<Item = &DefDiagnostic> {
@@ -125,14 +117,11 @@ impl DefDiagnostic {
     pub(crate) fn macro_expansion_parse_error(
         container: LocalModuleId,
         ast: MacroCallKind,
-        errors: &[SyntaxError],
+        errors: Box<[SyntaxError]>,
     ) -> Self {
         Self {
             in_module: container,
-            kind: DefDiagnosticKind::MacroExpansionParseError {
-                ast,
-                errors: errors.to_vec().into_boxed_slice(),
-            },
+            kind: DefDiagnosticKind::MacroExpansionParseError { ast, errors },
         }
     }
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs
index c45200e2de9..696fb6a961c 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/mod_resolution.rs
@@ -3,7 +3,6 @@ use arrayvec::ArrayVec;
 use base_db::{AnchoredPath, FileId};
 use hir_expand::{name::Name, HirFileIdExt, MacroFileIdExt};
 use limit::Limit;
-use syntax::SmolStr;
 
 use crate::{db::DefDatabase, HirFileId};
 
@@ -29,9 +28,9 @@ impl ModDir {
     pub(super) fn descend_into_definition(
         &self,
         name: &Name,
-        attr_path: Option<&SmolStr>,
+        attr_path: Option<&str>,
     ) -> Option<ModDir> {
-        let path = match attr_path.map(SmolStr::as_str) {
+        let path = match attr_path {
             None => {
                 let mut path = self.dir_path.clone();
                 path.push(&name.unescaped().to_smol_str());
@@ -63,10 +62,9 @@ impl ModDir {
         db: &dyn DefDatabase,
         file_id: HirFileId,
         name: &Name,
-        attr_path: Option<&SmolStr>,
+        attr_path: Option<&str>,
     ) -> Result<(FileId, bool, ModDir), Box<[String]>> {
         let name = name.unescaped();
-        let orig_file_id = file_id.original_file_respecting_includes(db.upcast());
 
         let mut candidate_files = ArrayVec::<_, 2>::new();
         match attr_path {
@@ -91,17 +89,19 @@ impl ModDir {
             }
         };
 
+        let orig_file_id = file_id.original_file_respecting_includes(db.upcast());
         for candidate in candidate_files.iter() {
             let path = AnchoredPath { anchor: orig_file_id, path: candidate.as_str() };
             if let Some(file_id) = db.resolve_path(path) {
                 let is_mod_rs = candidate.ends_with("/mod.rs");
 
-                let (dir_path, root_non_dir_owner) = if is_mod_rs || attr_path.is_some() {
-                    (DirPath::empty(), false)
+                let root_dir_owner = is_mod_rs || attr_path.is_some();
+                let dir_path = if root_dir_owner {
+                    DirPath::empty()
                 } else {
-                    (DirPath::new(format!("{}/", name.display(db.upcast()))), true)
+                    DirPath::new(format!("{}/", name.display(db.upcast())))
                 };
-                if let Some(mod_dir) = self.child(dir_path, root_non_dir_owner) {
+                if let Some(mod_dir) = self.child(dir_path, !root_dir_owner) {
                     return Ok((file_id, is_mod_rs, mod_dir));
                 }
             }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
index 1e13f7f8fd0..9e53b037283 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
@@ -22,7 +22,7 @@ use crate::{
     path::{ModPath, PathKind},
     per_ns::PerNs,
     visibility::{RawVisibility, Visibility},
-    AdtId, CrateId, LocalModuleId, ModuleDefId,
+    AdtId, LocalModuleId, ModuleDefId,
 };
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -42,21 +42,21 @@ pub(super) struct ResolvePathResult {
     pub(super) resolved_def: PerNs,
     pub(super) segment_index: Option<usize>,
     pub(super) reached_fixedpoint: ReachedFixedPoint,
-    pub(super) krate: Option<CrateId>,
+    pub(super) from_differing_crate: bool,
 }
 
 impl ResolvePathResult {
     fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult {
-        ResolvePathResult::with(PerNs::none(), reached_fixedpoint, None, None)
+        ResolvePathResult::new(PerNs::none(), reached_fixedpoint, None, false)
     }
 
-    fn with(
+    fn new(
         resolved_def: PerNs,
         reached_fixedpoint: ReachedFixedPoint,
         segment_index: Option<usize>,
-        krate: Option<CrateId>,
+        from_differing_crate: bool,
     ) -> ResolvePathResult {
-        ResolvePathResult { resolved_def, segment_index, reached_fixedpoint, krate }
+        ResolvePathResult { resolved_def, segment_index, reached_fixedpoint, from_differing_crate }
     }
 }
 
@@ -134,7 +134,19 @@ impl DefMap {
         // resolving them to. Pass `None` otherwise, e.g. when we're resolving import paths.
         expected_macro_subns: Option<MacroSubNs>,
     ) -> ResolvePathResult {
-        let mut result = ResolvePathResult::empty(ReachedFixedPoint::No);
+        let mut result = self.resolve_path_fp_with_macro_single(
+            db,
+            mode,
+            original_module,
+            path,
+            shadow,
+            expected_macro_subns,
+        );
+
+        if self.block.is_none() {
+            // If we're in the root `DefMap`, we can resolve the path directly.
+            return result;
+        }
 
         let mut arc;
         let mut current_map = self;
@@ -153,8 +165,7 @@ impl DefMap {
             if result.reached_fixedpoint == ReachedFixedPoint::No {
                 result.reached_fixedpoint = new.reached_fixedpoint;
             }
-            // FIXME: this doesn't seem right; what if the different namespace resolutions come from different crates?
-            result.krate = result.krate.or(new.krate);
+            result.from_differing_crate |= new.from_differing_crate;
             result.segment_index = match (result.segment_index, new.segment_index) {
                 (Some(idx), None) => Some(idx),
                 (Some(old), Some(new)) => Some(old.max(new)),
@@ -333,11 +344,11 @@ impl DefMap {
                         // expectation is discarded.
                         let (def, s) =
                             defp_map.resolve_path(db, module.local_id, &path, shadow, None);
-                        return ResolvePathResult::with(
+                        return ResolvePathResult::new(
                             def,
                             ReachedFixedPoint::Yes,
                             s.map(|s| s + i),
-                            Some(module.krate),
+                            true,
                         );
                     }
 
@@ -385,11 +396,11 @@ impl DefMap {
                     match res {
                         Some(res) => res,
                         None => {
-                            return ResolvePathResult::with(
+                            return ResolvePathResult::new(
                                 PerNs::types(e.into(), vis, imp),
                                 ReachedFixedPoint::Yes,
                                 Some(i),
-                                Some(self.krate),
+                                false,
                             )
                         }
                     }
@@ -403,11 +414,11 @@ impl DefMap {
                         curr,
                     );
 
-                    return ResolvePathResult::with(
+                    return ResolvePathResult::new(
                         PerNs::types(s, vis, imp),
                         ReachedFixedPoint::Yes,
                         Some(i),
-                        Some(self.krate),
+                        false,
                     );
                 }
             };
@@ -416,7 +427,7 @@ impl DefMap {
                 .filter_visibility(|vis| vis.is_visible_from_def_map(db, self, original_module));
         }
 
-        ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None, Some(self.krate))
+        ResolvePathResult::new(curr_per_ns, ReachedFixedPoint::Yes, None, false)
     }
 
     fn resolve_name_in_module(
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs
index 0f3fac1cecd..1ef8fa772a1 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/visibility.rs
@@ -2,8 +2,8 @@
 
 use std::iter;
 
-use hir_expand::{span_map::SpanMapRef, InFile};
 use la_arena::ArenaMap;
+use span::SyntaxContextId;
 use syntax::ast;
 use triomphe::Arc;
 
@@ -35,35 +35,24 @@ impl RawVisibility {
 
     pub(crate) fn from_ast(
         db: &dyn DefDatabase,
-        node: InFile<Option<ast::Visibility>>,
-    ) -> RawVisibility {
-        let node = match node.transpose() {
-            None => return RawVisibility::private(),
-            Some(node) => node,
-        };
-        Self::from_ast_with_span_map(db, node.value, db.span_map(node.file_id).as_ref())
-    }
-
-    pub(crate) fn from_opt_ast_with_span_map(
-        db: &dyn DefDatabase,
         node: Option<ast::Visibility>,
-        span_map: SpanMapRef<'_>,
+        span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId,
     ) -> RawVisibility {
         let node = match node {
             None => return RawVisibility::private(),
             Some(node) => node,
         };
-        Self::from_ast_with_span_map(db, node, span_map)
+        Self::from_ast_with_span_map(db, node, span_for_range)
     }
 
     fn from_ast_with_span_map(
         db: &dyn DefDatabase,
         node: ast::Visibility,
-        span_map: SpanMapRef<'_>,
+        span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId,
     ) -> RawVisibility {
         let path = match node.kind() {
             ast::VisibilityKind::In(path) => {
-                let path = ModPath::from_src(db.upcast(), path, span_map);
+                let path = ModPath::from_src(db.upcast(), path, span_for_range);
                 match path {
                     None => return RawVisibility::private(),
                     Some(path) => path,
diff --git a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml
index 506a188a211..4f308080156 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-expand/Cargo.toml
@@ -28,7 +28,6 @@ intern.workspace = true
 base-db.workspace = true
 cfg.workspace = true
 syntax.workspace = true
-profile.workspace = true
 tt.workspace = true
 mbe.workspace = true
 limit.workspace = true
@@ -38,4 +37,4 @@ span.workspace = true
 expect-test = "1.4.0"
 
 [lints]
-workspace = true
\ No newline at end of file
+workspace = true
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs
index 1c92dea38e6..7793e995323 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs
@@ -90,7 +90,7 @@ impl RawAttrs {
     }
 
     /// Processes `cfg_attr`s, returning the resulting semantic `Attrs`.
-    // FIXME: This should return a different type
+    // FIXME: This should return a different type, signaling it was filtered?
     pub fn filter(self, db: &dyn ExpandDatabase, krate: CrateId) -> RawAttrs {
         let has_cfg_attrs = self
             .iter()
@@ -201,7 +201,9 @@ impl Attr {
         span_map: SpanMapRef<'_>,
         id: AttrId,
     ) -> Option<Attr> {
-        let path = Interned::new(ModPath::from_src(db, ast.path()?, span_map)?);
+        let path = Interned::new(ModPath::from_src(db, ast.path()?, &mut |range| {
+            span_map.span_for_range(range).ctx
+        })?);
         let span = span_map.span_for_range(ast.syntax().text_range());
         let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() {
             let value = match lit.kind() {
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_attr_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_attr_macro.rs
index 903b0d48070..a0102f36aff 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_attr_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_attr_macro.rs
@@ -4,23 +4,17 @@ use span::{MacroCallId, Span};
 use crate::{db::ExpandDatabase, name, tt, ExpandResult, MacroCallKind};
 
 macro_rules! register_builtin {
-    ($expand_fn:ident: $(($name:ident, $variant:ident) => $expand:ident),* ) => {
+    ($(($name:ident, $variant:ident) => $expand:ident),* ) => {
         #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
         pub enum BuiltinAttrExpander {
             $($variant),*
         }
 
         impl BuiltinAttrExpander {
-            pub fn $expand_fn(
-                &self,
-                db: &dyn ExpandDatabase,
-                id: MacroCallId,
-                tt: &tt::Subtree,
-            ) -> ExpandResult<tt::Subtree> {
-                let expander = match *self {
+            pub fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::Subtree) -> ExpandResult<tt::Subtree>  {
+                match *self {
                     $( BuiltinAttrExpander::$variant => $expand, )*
-                };
-                expander(db, id, tt)
+                }
             }
 
             fn find_by_name(name: &name::Name) -> Option<Self> {
@@ -35,6 +29,15 @@ macro_rules! register_builtin {
 }
 
 impl BuiltinAttrExpander {
+    pub fn expand(
+        &self,
+        db: &dyn ExpandDatabase,
+        id: MacroCallId,
+        tt: &tt::Subtree,
+    ) -> ExpandResult<tt::Subtree> {
+        self.expander()(db, id, tt)
+    }
+
     pub fn is_derive(self) -> bool {
         matches!(self, BuiltinAttrExpander::Derive | BuiltinAttrExpander::DeriveConst)
     }
@@ -46,7 +49,7 @@ impl BuiltinAttrExpander {
     }
 }
 
-register_builtin! { expand:
+register_builtin! {
     (bench, Bench) => dummy_attr_expand,
     (cfg, Cfg) => dummy_attr_expand,
     (cfg_attr, CfgAttr) => dummy_attr_expand,
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs
index 27954875143..66dec7d89e5 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_derive_macro.rs
@@ -10,10 +10,12 @@ use crate::{
     hygiene::span_with_def_site_ctxt,
     name::{AsName, Name},
     quote::dollar_crate,
-    span_map::SpanMapRef,
+    span_map::ExpansionSpanMap,
     tt,
 };
-use syntax::ast::{self, AstNode, FieldList, HasAttrs, HasGenericParams, HasName, HasTypeBounds};
+use syntax::ast::{
+    self, AstNode, FieldList, HasAttrs, HasGenericParams, HasModuleItem, HasName, HasTypeBounds,
+};
 
 use crate::{db::ExpandDatabase, name, quote, ExpandError, ExpandResult};
 
@@ -25,20 +27,10 @@ macro_rules! register_builtin {
         }
 
         impl BuiltinDeriveExpander {
-            pub fn expand(
-                &self,
-                db: &dyn ExpandDatabase,
-                id: MacroCallId,
-                tt: &ast::Adt,
-                token_map: SpanMapRef<'_>,
-            ) -> ExpandResult<tt::Subtree> {
-                let expander = match *self {
+            pub fn expander(&self) -> fn(Span, &tt::Subtree) -> ExpandResult<tt::Subtree>  {
+                match *self {
                     $( BuiltinDeriveExpander::$trait => $expand, )*
-                };
-
-                let span = db.lookup_intern_macro_call(id).call_site;
-                let span = span_with_def_site_ctxt(db, span, id);
-                expander(span, tt, token_map)
+                }
             }
 
             fn find_by_name(name: &name::Name) -> Option<Self> {
@@ -52,6 +44,19 @@ macro_rules! register_builtin {
     };
 }
 
+impl BuiltinDeriveExpander {
+    pub fn expand(
+        &self,
+        db: &dyn ExpandDatabase,
+        id: MacroCallId,
+        tt: &tt::Subtree,
+    ) -> ExpandResult<tt::Subtree> {
+        let span = db.lookup_intern_macro_call(id).call_site;
+        let span = span_with_def_site_ctxt(db, span, id);
+        self.expander()(span, tt)
+    }
+}
+
 register_builtin! {
     Copy => copy_expand,
     Clone => clone_expand,
@@ -122,7 +127,7 @@ impl VariantShape {
         }
     }
 
-    fn from(tm: SpanMapRef<'_>, value: Option<FieldList>) -> Result<Self, ExpandError> {
+    fn from(tm: &ExpansionSpanMap, value: Option<FieldList>) -> Result<Self, ExpandError> {
         let r = match value {
             None => VariantShape::Unit,
             Some(FieldList::RecordFieldList(it)) => VariantShape::Struct(
@@ -198,11 +203,13 @@ struct BasicAdtInfo {
     associated_types: Vec<tt::Subtree>,
 }
 
-fn parse_adt(
-    tm: SpanMapRef<'_>,
-    adt: &ast::Adt,
-    call_site: Span,
-) -> Result<BasicAdtInfo, ExpandError> {
+fn parse_adt(tt: &tt::Subtree, call_site: Span) -> Result<BasicAdtInfo, ExpandError> {
+    let (parsed, tm) = &mbe::token_tree_to_syntax_node(tt, mbe::TopEntryPoint::MacroItems);
+    let macro_items = ast::MacroItems::cast(parsed.syntax_node())
+        .ok_or_else(|| ExpandError::other("invalid item definition"))?;
+    let item = macro_items.items().next().ok_or_else(|| ExpandError::other("no item found"))?;
+    let adt = &ast::Adt::cast(item.syntax().clone())
+        .ok_or_else(|| ExpandError::other("expected struct, enum or union"))?;
     let (name, generic_param_list, where_clause, shape) = match adt {
         ast::Adt::Struct(it) => (
             it.name(),
@@ -318,14 +325,14 @@ fn parse_adt(
 }
 
 fn name_to_token(
-    token_map: SpanMapRef<'_>,
+    token_map: &ExpansionSpanMap,
     name: Option<ast::Name>,
 ) -> Result<tt::Ident, ExpandError> {
     let name = name.ok_or_else(|| {
         debug!("parsed item has no name");
         ExpandError::other("missing name")
     })?;
-    let span = token_map.span_for_range(name.syntax().text_range());
+    let span = token_map.span_at(name.syntax().text_range().start());
     let name_token = tt::Ident { span, text: name.text().into() };
     Ok(name_token)
 }
@@ -362,14 +369,12 @@ fn name_to_token(
 /// where B1, ..., BN are the bounds given by `bounds_paths`. Z is a phantom type, and
 /// therefore does not get bound by the derived trait.
 fn expand_simple_derive(
-    // FIXME: use
     invoc_span: Span,
-    tt: &ast::Adt,
-    tm: SpanMapRef<'_>,
+    tt: &tt::Subtree,
     trait_path: tt::Subtree,
     make_trait_body: impl FnOnce(&BasicAdtInfo) -> tt::Subtree,
 ) -> ExpandResult<tt::Subtree> {
-    let info = match parse_adt(tm, tt, invoc_span) {
+    let info = match parse_adt(tt, invoc_span) {
         Ok(info) => info,
         Err(e) => {
             return ExpandResult::new(
@@ -412,14 +417,14 @@ fn expand_simple_derive(
     ExpandResult::ok(expanded)
 }
 
-fn copy_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
+fn copy_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
     let krate = dollar_crate(span);
-    expand_simple_derive(span, tt, tm, quote! {span => #krate::marker::Copy }, |_| quote! {span =>})
+    expand_simple_derive(span, tt, quote! {span => #krate::marker::Copy }, |_| quote! {span =>})
 }
 
-fn clone_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
+fn clone_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
     let krate = dollar_crate(span);
-    expand_simple_derive(span, tt, tm, quote! {span => #krate::clone::Clone }, |adt| {
+    expand_simple_derive(span, tt, quote! {span => #krate::clone::Clone }, |adt| {
         if matches!(adt.shape, AdtShape::Union) {
             let star = tt::Punct { char: '*', spacing: ::tt::Spacing::Alone, span };
             return quote! {span =>
@@ -468,9 +473,9 @@ fn and_and(span: Span) -> tt::Subtree {
     quote! {span => #and& }
 }
 
-fn default_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
+fn default_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
     let krate = &dollar_crate(span);
-    expand_simple_derive(span, tt, tm, quote! {span => #krate::default::Default }, |adt| {
+    expand_simple_derive(span, tt, quote! {span => #krate::default::Default }, |adt| {
         let body = match &adt.shape {
             AdtShape::Struct(fields) => {
                 let name = &adt.name;
@@ -507,9 +512,9 @@ fn default_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult
     })
 }
 
-fn debug_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
+fn debug_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
     let krate = &dollar_crate(span);
-    expand_simple_derive(span, tt, tm, quote! {span => #krate::fmt::Debug }, |adt| {
+    expand_simple_derive(span, tt, quote! {span => #krate::fmt::Debug }, |adt| {
         let for_variant = |name: String, v: &VariantShape| match v {
             VariantShape::Struct(fields) => {
                 let for_fields = fields.iter().map(|it| {
@@ -579,9 +584,9 @@ fn debug_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<t
     })
 }
 
-fn hash_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
+fn hash_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
     let krate = &dollar_crate(span);
-    expand_simple_derive(span, tt, tm, quote! {span => #krate::hash::Hash }, |adt| {
+    expand_simple_derive(span, tt, quote! {span => #krate::hash::Hash }, |adt| {
         if matches!(adt.shape, AdtShape::Union) {
             // FIXME: Return expand error here
             return quote! {span =>};
@@ -626,14 +631,14 @@ fn hash_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt
     })
 }
 
-fn eq_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
+fn eq_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
     let krate = dollar_crate(span);
-    expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::Eq }, |_| quote! {span =>})
+    expand_simple_derive(span, tt, quote! {span => #krate::cmp::Eq }, |_| quote! {span =>})
 }
 
-fn partial_eq_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
+fn partial_eq_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
     let krate = dollar_crate(span);
-    expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::PartialEq }, |adt| {
+    expand_simple_derive(span, tt, quote! {span => #krate::cmp::PartialEq }, |adt| {
         if matches!(adt.shape, AdtShape::Union) {
             // FIXME: Return expand error here
             return quote! {span =>};
@@ -703,9 +708,9 @@ fn self_and_other_patterns(
     (self_patterns, other_patterns)
 }
 
-fn ord_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
+fn ord_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
     let krate = &dollar_crate(span);
-    expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::Ord }, |adt| {
+    expand_simple_derive(span, tt, quote! {span => #krate::cmp::Ord }, |adt| {
         fn compare(
             krate: &tt::Ident,
             left: tt::Subtree,
@@ -761,9 +766,9 @@ fn ord_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt:
     })
 }
 
-fn partial_ord_expand(span: Span, tt: &ast::Adt, tm: SpanMapRef<'_>) -> ExpandResult<tt::Subtree> {
+fn partial_ord_expand(span: Span, tt: &tt::Subtree) -> ExpandResult<tt::Subtree> {
     let krate = &dollar_crate(span);
-    expand_simple_derive(span, tt, tm, quote! {span => #krate::cmp::PartialOrd }, |adt| {
+    expand_simple_derive(span, tt, quote! {span => #krate::cmp::PartialOrd }, |adt| {
         fn compare(
             krate: &tt::Ident,
             left: tt::Subtree,
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs
index 90cd3af7578..0fd0c25dcce 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/builtin_fn_macro.rs
@@ -31,36 +31,18 @@ macro_rules! register_builtin {
         }
 
         impl BuiltinFnLikeExpander {
-            pub fn expand(
-                &self,
-                db: &dyn ExpandDatabase,
-                id: MacroCallId,
-                tt: &tt::Subtree,
-            ) -> ExpandResult<tt::Subtree> {
-                let expander = match *self {
+            pub fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::Subtree, Span) -> ExpandResult<tt::Subtree>  {
+                match *self {
                     $( BuiltinFnLikeExpander::$kind => $expand, )*
-                };
-
-                let span = db.lookup_intern_macro_call(id).call_site;
-                let span = span_with_def_site_ctxt(db, span, id);
-                expander(db, id, tt, span)
+                }
             }
         }
 
         impl EagerExpander {
-            pub fn expand(
-                &self,
-                db: &dyn ExpandDatabase,
-                id: MacroCallId,
-                tt: &tt::Subtree,
-            ) -> ExpandResult<tt::Subtree> {
-                let expander = match *self {
+            pub fn expander(&self) -> fn (&dyn ExpandDatabase, MacroCallId, &tt::Subtree, Span) -> ExpandResult<tt::Subtree>  {
+                match *self {
                     $( EagerExpander::$e_kind => $e_expand, )*
-                };
-
-                let span = db.lookup_intern_macro_call(id).call_site;
-                let span = span_with_def_site_ctxt(db, span, id);
-                expander(db, id, tt, span)
+                }
             }
         }
 
@@ -74,7 +56,31 @@ macro_rules! register_builtin {
     };
 }
 
+impl BuiltinFnLikeExpander {
+    pub fn expand(
+        &self,
+        db: &dyn ExpandDatabase,
+        id: MacroCallId,
+        tt: &tt::Subtree,
+    ) -> ExpandResult<tt::Subtree> {
+        let span = db.lookup_intern_macro_call(id).call_site;
+        let span = span_with_def_site_ctxt(db, span, id);
+        self.expander()(db, id, tt, span)
+    }
+}
+
 impl EagerExpander {
+    pub fn expand(
+        &self,
+        db: &dyn ExpandDatabase,
+        id: MacroCallId,
+        tt: &tt::Subtree,
+    ) -> ExpandResult<tt::Subtree> {
+        let span = db.lookup_intern_macro_call(id).call_site;
+        let span = span_with_def_site_ctxt(db, span, id);
+        self.expander()(db, id, tt, span)
+    }
+
     pub fn is_include(&self) -> bool {
         matches!(self, EagerExpander::Include)
     }
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/change.rs b/src/tools/rust-analyzer/crates/hir-expand/src/change.rs
index c6611438e64..8b9e5a59df8 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/change.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/change.rs
@@ -11,14 +11,14 @@ use triomphe::Arc;
 use crate::{db::ExpandDatabase, proc_macro::ProcMacros};
 
 #[derive(Debug, Default)]
-pub struct Change {
+pub struct ChangeWithProcMacros {
     pub source_change: FileChange,
     pub proc_macros: Option<ProcMacros>,
     pub toolchains: Option<Vec<Option<Version>>>,
     pub target_data_layouts: Option<Vec<TargetLayoutLoadResult>>,
 }
 
-impl Change {
+impl ChangeWithProcMacros {
     pub fn new() -> Self {
         Self::default()
     }
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
index f1f0d8990f1..6f69ee15aca 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/db.rs
@@ -215,11 +215,6 @@ pub fn expand_speculative(
         MacroDefKind::BuiltInAttr(BuiltinAttrExpander::Derive, _) => {
             pseudo_derive_attr_expansion(&tt, attr_arg.as_ref()?, loc.call_site)
         }
-        MacroDefKind::BuiltInDerive(expander, ..) => {
-            // this cast is a bit sus, can we avoid losing the typedness here?
-            let adt = ast::Adt::cast(speculative_args.clone()).unwrap();
-            expander.expand(db, actual_macro_call, &adt, span_map)
-        }
         MacroDefKind::Declarative(it) => db.decl_macro_expander(loc.krate, it).expand_unhygienic(
             db,
             tt,
@@ -227,6 +222,9 @@ pub fn expand_speculative(
             loc.call_site,
         ),
         MacroDefKind::BuiltIn(it, _) => it.expand(db, actual_macro_call, &tt).map_err(Into::into),
+        MacroDefKind::BuiltInDerive(it, ..) => {
+            it.expand(db, actual_macro_call, &tt).map_err(Into::into)
+        }
         MacroDefKind::BuiltInEager(it, _) => {
             it.expand(db, actual_macro_call, &tt).map_err(Into::into)
         }
@@ -303,7 +301,7 @@ fn parse_macro_expansion_error(
     macro_call_id: MacroCallId,
 ) -> ExpandResult<Box<[SyntaxError]>> {
     db.parse_macro_expansion(MacroFileId { macro_call_id })
-        .map(|it| it.0.errors().to_vec().into_boxed_slice())
+        .map(|it| it.0.errors().into_boxed_slice())
 }
 
 pub(crate) fn parse_with_map(
@@ -321,6 +319,7 @@ pub(crate) fn parse_with_map(
     }
 }
 
+// FIXME: for derive attributes, this will return separate copies of the same structures!
 fn macro_arg(
     db: &dyn ExpandDatabase,
     id: MacroCallId,
@@ -445,7 +444,7 @@ fn macro_arg(
 
         if matches!(loc.def.kind, MacroDefKind::BuiltInEager(..)) {
             match parse.errors() {
-                [] => ValueResult::ok((Arc::new(tt), undo_info)),
+                errors if errors.is_empty() => ValueResult::ok((Arc::new(tt), undo_info)),
                 errors => ValueResult::new(
                     (Arc::new(tt), undo_info),
                     // Box::<[_]>::from(res.errors()), not stable yet
@@ -526,16 +525,6 @@ fn macro_expand(
 
     let ExpandResult { value: tt, mut err } = match loc.def.kind {
         MacroDefKind::ProcMacro(..) => return db.expand_proc_macro(macro_call_id).map(CowArc::Arc),
-        MacroDefKind::BuiltInDerive(expander, ..) => {
-            let (root, map) = parse_with_map(db, loc.kind.file_id());
-            let root = root.syntax_node();
-            let MacroCallKind::Derive { ast_id, .. } = loc.kind else { unreachable!() };
-            let node = ast_id.to_ptr(db).to_node(&root);
-
-            // FIXME: Use censoring
-            let _censor = censor_for_macro_input(&loc, node.syntax());
-            expander.expand(db, macro_call_id, &node, map.as_ref())
-        }
         _ => {
             let ValueResult { value: (macro_arg, undo_info), err } = db.macro_arg(macro_call_id);
             let format_parse_err = |err: Arc<Box<[SyntaxError]>>| {
@@ -569,6 +558,9 @@ fn macro_expand(
                         err: err.map(format_parse_err),
                     };
                 }
+                MacroDefKind::BuiltInDerive(it, _) => {
+                    it.expand(db, macro_call_id, arg).map_err(Into::into)
+                }
                 MacroDefKind::BuiltInEager(it, _) => {
                     it.expand(db, macro_call_id, arg).map_err(Into::into)
                 }
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs b/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs
index da85c2ec7ac..5337a5bb028 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/eager.rs
@@ -27,7 +27,6 @@ use crate::{
     ast::{self, AstNode},
     db::ExpandDatabase,
     mod_path::ModPath,
-    span_map::SpanMapRef,
     EagerCallInfo, ExpandError, ExpandResult, ExpandTo, ExpansionSpanMap, InFile, Intern,
     MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind,
 };
@@ -155,10 +154,9 @@ fn eager_macro_recur(
             }
         };
 
-        let def = match call
-            .path()
-            .and_then(|path| ModPath::from_src(db, path, SpanMapRef::ExpansionSpanMap(span_map)))
-        {
+        let def = match call.path().and_then(|path| {
+            ModPath::from_src(db, path, &mut |range| span_map.span_at(range.start()).ctx)
+        }) {
             Some(path) => match macro_resolver(path.clone()) {
                 Some(def) => def,
                 None => {
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs
index 66ceb1b7d42..a500c24ce88 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/files.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/files.rs
@@ -252,7 +252,7 @@ impl InFile<&SyntaxNode> {
             map_node_range_up(db, &db.expansion_span_map(file_id), self.value.text_range())?;
 
         // FIXME: Figure out an API that makes proper use of ctx, this only exists to
-        // keep pre-token map rewrite behaviour.
+        // keep pre-token map rewrite behavior.
         if !ctx.is_root() {
             return None;
         }
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs
index 0cf1fadec97..fc186d2c26d 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/mod_path.rs
@@ -9,7 +9,6 @@ use crate::{
     db::ExpandDatabase,
     hygiene::{marks_rev, SyntaxContextExt, Transparency},
     name::{known, AsName, Name},
-    span_map::SpanMapRef,
     tt,
 };
 use base_db::CrateId;
@@ -49,9 +48,9 @@ impl ModPath {
     pub fn from_src(
         db: &dyn ExpandDatabase,
         path: ast::Path,
-        span_map: SpanMapRef<'_>,
+        span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId,
     ) -> Option<ModPath> {
-        convert_path(db, path, span_map)
+        convert_path(db, path, span_for_range)
     }
 
     pub fn from_tt(db: &dyn ExpandDatabase, tt: &[tt::TokenTree]) -> Option<ModPath> {
@@ -144,6 +143,12 @@ impl ModPath {
     }
 }
 
+impl Extend<Name> for ModPath {
+    fn extend<T: IntoIterator<Item = Name>>(&mut self, iter: T) {
+        self.segments.extend(iter);
+    }
+}
+
 struct Display<'a> {
     db: &'a dyn ExpandDatabase,
     path: &'a ModPath,
@@ -215,7 +220,7 @@ fn display_fmt_path(
 fn convert_path(
     db: &dyn ExpandDatabase,
     path: ast::Path,
-    span_map: SpanMapRef<'_>,
+    span_for_range: &mut dyn FnMut(::tt::TextRange) -> SyntaxContextId,
 ) -> Option<ModPath> {
     let mut segments = path.segments();
 
@@ -224,12 +229,9 @@ fn convert_path(
         ast::PathSegmentKind::Name(name_ref) => {
             if name_ref.text() == "$crate" {
                 ModPath::from_kind(
-                    resolve_crate_root(
-                        db,
-                        span_map.span_for_range(name_ref.syntax().text_range()).ctx,
-                    )
-                    .map(PathKind::DollarCrate)
-                    .unwrap_or(PathKind::Crate),
+                    resolve_crate_root(db, span_for_range(name_ref.syntax().text_range()))
+                        .map(PathKind::DollarCrate)
+                        .unwrap_or(PathKind::Crate),
                 )
             } else {
                 let mut res = ModPath::from_kind(
@@ -283,7 +285,7 @@ fn convert_path(
     // We follow what it did anyway :)
     if mod_path.segments.len() == 1 && mod_path.kind == PathKind::Plain {
         if let Some(_macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) {
-            let syn_ctx = span_map.span_for_range(segment.syntax().text_range()).ctx;
+            let syn_ctx = span_for_range(segment.syntax().text_range());
             if let Some(macro_call_id) = db.lookup_intern_syntax_context(syn_ctx).outer_expn {
                 if db.lookup_intern_macro_call(macro_call_id).def.local_inner {
                     mod_path.kind = match resolve_crate_root(db, syn_ctx) {
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs
index cf17d90ed12..0b69799e6bf 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/name.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/name.rs
@@ -111,15 +111,11 @@ impl Name {
         self == &Name::missing()
     }
 
-    /// Generates a new name which is only equal to itself, by incrementing a counter. Due
-    /// its implementation, it should not be used in things that salsa considers, like
-    /// type names or field names, and it should be only used in names of local variables
-    /// and labels and similar things.
-    pub fn generate_new_name() -> Name {
-        use std::sync::atomic::{AtomicUsize, Ordering};
-        static CNT: AtomicUsize = AtomicUsize::new(0);
-        let c = CNT.fetch_add(1, Ordering::Relaxed);
-        Name::new_text(format_smolstr!("<ra@gennew>{c}"))
+    /// Generates a new name that attempts to be unique. Should only be used when body lowering and
+    /// creating desugared locals and labels. The caller is responsible for picking an index
+    /// that is stable across re-executions
+    pub fn generate_new_name(idx: usize) -> Name {
+        Name::new_text(format_smolstr!("<ra@gennew>{idx}"))
     }
 
     /// Returns the tuple index this name represents if it is a tuple field.
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/span_map.rs b/src/tools/rust-analyzer/crates/hir-expand/src/span_map.rs
index 4a60a948560..ef86be67096 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/span_map.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/span_map.rs
@@ -31,11 +31,13 @@ impl mbe::SpanMapper<Span> for SpanMap {
         self.span_for_range(range)
     }
 }
+
 impl mbe::SpanMapper<Span> for SpanMapRef<'_> {
     fn span_for(&self, range: TextRange) -> Span {
         self.span_for_range(range)
     }
 }
+
 impl SpanMap {
     pub fn span_for_range(&self, range: TextRange) -> Span {
         match self {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
index 1f8f8744f9e..41e2f7ad73c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir-ty/Cargo.toml
@@ -45,7 +45,6 @@ intern.workspace = true
 hir-def.workspace = true
 hir-expand.workspace = true
 base-db.workspace = true
-profile.workspace = true
 syntax.workspace = true
 limit.workspace = true
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
index f9e8cff5539..28c497989fe 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/db.rs
@@ -31,12 +31,8 @@ use hir_expand::name::Name;
 
 #[salsa::query_group(HirDatabaseStorage)]
 pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
-    #[salsa::invoke(infer_wait)]
-    #[salsa::transparent]
-    fn infer(&self, def: DefWithBodyId) -> Arc<InferenceResult>;
-
     #[salsa::invoke(crate::infer::infer_query)]
-    fn infer_query(&self, def: DefWithBodyId) -> Arc<InferenceResult>;
+    fn infer(&self, def: DefWithBodyId) -> Arc<InferenceResult>;
 
     // region:mir
 
@@ -258,17 +254,8 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
         env: Arc<TraitEnvironment>,
     ) -> Ty;
 
-    #[salsa::invoke(trait_solve_wait)]
-    #[salsa::transparent]
-    fn trait_solve(
-        &self,
-        krate: CrateId,
-        block: Option<BlockId>,
-        goal: crate::Canonical<crate::InEnvironment<crate::Goal>>,
-    ) -> Option<crate::Solution>;
-
     #[salsa::invoke(crate::traits::trait_solve_query)]
-    fn trait_solve_query(
+    fn trait_solve(
         &self,
         krate: CrateId,
         block: Option<BlockId>,
@@ -284,38 +271,6 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
     ) -> chalk_ir::ProgramClauses<Interner>;
 }
 
-fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> {
-    let detail = match def {
-        DefWithBodyId::FunctionId(it) => db.function_data(it).name.display(db.upcast()).to_string(),
-        DefWithBodyId::StaticId(it) => {
-            db.static_data(it).name.clone().display(db.upcast()).to_string()
-        }
-        DefWithBodyId::ConstId(it) => db
-            .const_data(it)
-            .name
-            .clone()
-            .unwrap_or_else(Name::missing)
-            .display(db.upcast())
-            .to_string(),
-        DefWithBodyId::VariantId(it) => {
-            db.enum_variant_data(it).name.display(db.upcast()).to_string()
-        }
-        DefWithBodyId::InTypeConstId(it) => format!("in type const {it:?}"),
-    };
-    let _p = tracing::span!(tracing::Level::INFO, "infer:wait", ?detail).entered();
-    db.infer_query(def)
-}
-
-fn trait_solve_wait(
-    db: &dyn HirDatabase,
-    krate: CrateId,
-    block: Option<BlockId>,
-    goal: crate::Canonical<crate::InEnvironment<crate::Goal>>,
-) -> Option<crate::Solution> {
-    let _p = tracing::span!(tracing::Level::INFO, "trait_solve::wait").entered();
-    db.trait_solve_query(krate, block, goal)
-}
-
 #[test]
 fn hir_database_is_object_safe() {
     fn _assert_object_safe(_: &dyn HirDatabase) {}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
index 1a134e6d780..67cfbc294df 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/expr.rs
@@ -60,12 +60,17 @@ pub enum BodyValidationDiagnostic {
 }
 
 impl BodyValidationDiagnostic {
-    pub fn collect(db: &dyn HirDatabase, owner: DefWithBodyId) -> Vec<BodyValidationDiagnostic> {
+    pub fn collect(
+        db: &dyn HirDatabase,
+        owner: DefWithBodyId,
+        validate_lints: bool,
+    ) -> Vec<BodyValidationDiagnostic> {
         let _p =
             tracing::span!(tracing::Level::INFO, "BodyValidationDiagnostic::collect").entered();
         let infer = db.infer(owner);
         let body = db.body(owner);
-        let mut validator = ExprValidator { owner, body, infer, diagnostics: Vec::new() };
+        let mut validator =
+            ExprValidator { owner, body, infer, diagnostics: Vec::new(), validate_lints };
         validator.validate_body(db);
         validator.diagnostics
     }
@@ -76,6 +81,7 @@ struct ExprValidator {
     body: Arc<Body>,
     infer: Arc<InferenceResult>,
     diagnostics: Vec<BodyValidationDiagnostic>,
+    validate_lints: bool,
 }
 
 impl ExprValidator {
@@ -139,6 +145,9 @@ impl ExprValidator {
         expr: &Expr,
         filter_map_next_checker: &mut Option<FilterMapNextChecker>,
     ) {
+        if !self.validate_lints {
+            return;
+        }
         // Check that the number of arguments matches the number of parameters.
 
         if self.infer.expr_type_mismatches().next().is_some() {
@@ -173,7 +182,7 @@ impl ExprValidator {
         db: &dyn HirDatabase,
     ) {
         let scrut_ty = &self.infer[scrutinee_expr];
-        if scrut_ty.is_unknown() {
+        if scrut_ty.contains_unknown() {
             return;
         }
 
@@ -230,6 +239,7 @@ impl ExprValidator {
             m_arms.as_slice(),
             scrut_ty.clone(),
             ValidityConstraint::ValidOnly,
+            None,
         ) {
             Ok(report) => report,
             Err(()) => return,
@@ -257,6 +267,9 @@ impl ExprValidator {
             };
             let Some(initializer) = initializer else { continue };
             let ty = &self.infer[initializer];
+            if ty.contains_unknown() {
+                continue;
+            }
 
             let mut have_errors = false;
             let deconstructed_pat = self.lower_pattern(&cx, pat, db, &mut have_errors);
@@ -274,6 +287,7 @@ impl ExprValidator {
                 &[match_arm],
                 ty.clone(),
                 ValidityConstraint::ValidOnly,
+                None,
             ) {
                 Ok(v) => v,
                 Err(e) => {
@@ -308,6 +322,9 @@ impl ExprValidator {
     }
 
     fn check_for_trailing_return(&mut self, body_expr: ExprId, body: &Body) {
+        if !self.validate_lints {
+            return;
+        }
         match &body.exprs[body_expr] {
             Expr::Block { statements, tail, .. } => {
                 let last_stmt = tail.or_else(|| match statements.last()? {
@@ -340,6 +357,9 @@ impl ExprValidator {
     }
 
     fn check_for_unnecessary_else(&mut self, id: ExprId, expr: &Expr, db: &dyn HirDatabase) {
+        if !self.validate_lints {
+            return;
+        }
         if let Expr::If { condition: _, then_branch, else_branch } = expr {
             if else_branch.is_none() {
                 return;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
index e98a946a870..ca058428796 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/match_check/pat_analysis.rs
@@ -8,7 +8,7 @@ use rustc_hash::FxHashMap;
 use rustc_pattern_analysis::{
     constructor::{Constructor, ConstructorSet, VariantVisibility},
     index::IdxContainer,
-    Captures, TypeCx,
+    Captures, PrivateUninhabitedField, TypeCx,
 };
 use smallvec::{smallvec, SmallVec};
 use stdx::never;
@@ -88,39 +88,21 @@ impl<'p> MatchCheckCtx<'p> {
         }
     }
 
-    // In the cases of either a `#[non_exhaustive]` field list or a non-public field, we hide
-    // uninhabited fields in order not to reveal the uninhabitedness of the whole variant.
-    // This lists the fields we keep along with their types.
-    fn list_variant_nonhidden_fields<'a>(
+    // This lists the fields of a variant along with their types.
+    fn list_variant_fields<'a>(
         &'a self,
         ty: &'a Ty,
         variant: VariantId,
     ) -> impl Iterator<Item = (LocalFieldId, Ty)> + Captures<'a> + Captures<'p> {
-        let cx = self;
-        let (adt, substs) = ty.as_adt().unwrap();
-
-        let adt_is_local = variant.module(cx.db.upcast()).krate() == cx.module.krate();
-
-        // Whether we must not match the fields of this variant exhaustively.
-        let is_non_exhaustive =
-            cx.db.attrs(variant.into()).by_key("non_exhaustive").exists() && !adt_is_local;
+        let (_, substs) = ty.as_adt().unwrap();
 
-        let visibility = cx.db.field_visibilities(variant);
-        let field_ty = cx.db.field_types(variant);
-        let fields_len = variant.variant_data(cx.db.upcast()).fields().len() as u32;
+        let field_tys = self.db.field_types(variant);
+        let fields_len = variant.variant_data(self.db.upcast()).fields().len() as u32;
 
-        (0..fields_len).map(|idx| LocalFieldId::from_raw(idx.into())).filter_map(move |fid| {
-            let ty = field_ty[fid].clone().substitute(Interner, substs);
-            let ty = normalize(cx.db, cx.db.trait_environment_for_body(cx.body), ty);
-            let is_visible = matches!(adt, hir_def::AdtId::EnumId(..))
-                || visibility[fid].is_visible_from(cx.db.upcast(), cx.module);
-            let is_uninhabited = cx.is_uninhabited(&ty);
-
-            if is_uninhabited && (!is_visible || is_non_exhaustive) {
-                None
-            } else {
-                Some((fid, ty))
-            }
+        (0..fields_len).map(|idx| LocalFieldId::from_raw(idx.into())).map(move |fid| {
+            let ty = field_tys[fid].clone().substitute(Interner, substs);
+            let ty = normalize(self.db, self.db.trait_environment_for_body(self.body), ty);
+            (fid, ty)
         })
     }
 
@@ -199,23 +181,16 @@ impl<'p> MatchCheckCtx<'p> {
                             }
                         };
                         let variant = Self::variant_id_for_adt(&ctor, adt.0).unwrap();
-                        let fields_len = variant.variant_data(self.db.upcast()).fields().len();
-                        // For each field in the variant, we store the relevant index into `self.fields` if any.
-                        let mut field_id_to_id: Vec<Option<usize>> = vec![None; fields_len];
-                        let tys = self
-                            .list_variant_nonhidden_fields(&pat.ty, variant)
-                            .enumerate()
-                            .map(|(i, (fid, ty))| {
-                                let field_idx: u32 = fid.into_raw().into();
-                                field_id_to_id[field_idx as usize] = Some(i);
-                                ty
-                            });
-                        let mut wilds: Vec<_> = tys.map(DeconstructedPat::wildcard).collect();
+                        // Fill a vec with wildcards, then place the fields we have at the right
+                        // index.
+                        let mut wilds: Vec<_> = self
+                            .list_variant_fields(&pat.ty, variant)
+                            .map(|(_, ty)| ty)
+                            .map(DeconstructedPat::wildcard)
+                            .collect();
                         for pat in subpatterns {
-                            let field_idx: u32 = pat.field.into_raw().into();
-                            if let Some(i) = field_id_to_id[field_idx as usize] {
-                                wilds[i] = self.lower_pat(&pat.pattern);
-                            }
+                            let field_id: u32 = pat.field.into_raw().into();
+                            wilds[field_id as usize] = self.lower_pat(&pat.pattern);
                         }
                         fields = wilds;
                     }
@@ -263,7 +238,7 @@ impl<'p> MatchCheckCtx<'p> {
                 TyKind::Adt(adt, substs) => {
                     let variant = Self::variant_id_for_adt(pat.ctor(), adt.0).unwrap();
                     let subpatterns = self
-                        .list_variant_nonhidden_fields(pat.ty(), variant)
+                        .list_variant_fields(pat.ty(), variant)
                         .zip(subpatterns)
                         .map(|((field, _ty), pattern)| FieldPat { field, pattern })
                         .collect();
@@ -286,7 +261,7 @@ impl<'p> MatchCheckCtx<'p> {
             Ref => PatKind::Deref { subpattern: subpatterns.next().unwrap() },
             Slice(_) => unimplemented!(),
             &Str(void) => match void {},
-            Wildcard | NonExhaustive | Hidden => PatKind::Wild,
+            Wildcard | NonExhaustive | Hidden | PrivateUninhabited => PatKind::Wild,
             Missing | F32Range(..) | F64Range(..) | Opaque(..) | Or => {
                 never!("can't convert to pattern: {:?}", pat.ctor());
                 PatKind::Wild
@@ -326,7 +301,7 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
                         1
                     } else {
                         let variant = Self::variant_id_for_adt(ctor, adt).unwrap();
-                        self.list_variant_nonhidden_fields(ty, variant).count()
+                        variant.variant_data(self.db.upcast()).fields().len()
                     }
                 }
                 _ => {
@@ -337,7 +312,7 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
             Ref => 1,
             Slice(..) => unimplemented!(),
             Bool(..) | IntRange(..) | F32Range(..) | F64Range(..) | Str(..) | Opaque(..)
-            | NonExhaustive | Hidden | Missing | Wildcard => 0,
+            | NonExhaustive | PrivateUninhabited | Hidden | Missing | Wildcard => 0,
             Or => {
                 never!("The `Or` constructor doesn't have a fixed arity");
                 0
@@ -349,13 +324,13 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
         &'a self,
         ctor: &'a rustc_pattern_analysis::constructor::Constructor<Self>,
         ty: &'a Self::Ty,
-    ) -> impl ExactSizeIterator<Item = Self::Ty> + Captures<'a> {
-        let single = |ty| smallvec![ty];
+    ) -> impl ExactSizeIterator<Item = (Self::Ty, PrivateUninhabitedField)> + Captures<'a> {
+        let single = |ty| smallvec![(ty, PrivateUninhabitedField(false))];
         let tys: SmallVec<[_; 2]> = match ctor {
             Struct | Variant(_) | UnionField => match ty.kind(Interner) {
                 TyKind::Tuple(_, substs) => {
                     let tys = substs.iter(Interner).map(|ty| ty.assert_ty_ref(Interner));
-                    tys.cloned().collect()
+                    tys.cloned().map(|ty| (ty, PrivateUninhabitedField(false))).collect()
                 }
                 TyKind::Ref(.., rty) => single(rty.clone()),
                 &TyKind::Adt(AdtId(adt), ref substs) => {
@@ -366,7 +341,27 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
                         single(subst_ty)
                     } else {
                         let variant = Self::variant_id_for_adt(ctor, adt).unwrap();
-                        self.list_variant_nonhidden_fields(ty, variant).map(|(_, ty)| ty).collect()
+                        let (adt, _) = ty.as_adt().unwrap();
+
+                        let adt_is_local =
+                            variant.module(self.db.upcast()).krate() == self.module.krate();
+                        // Whether we must not match the fields of this variant exhaustively.
+                        let is_non_exhaustive =
+                            self.db.attrs(variant.into()).by_key("non_exhaustive").exists()
+                                && !adt_is_local;
+                        let visibilities = self.db.field_visibilities(variant);
+
+                        self.list_variant_fields(ty, variant)
+                            .map(move |(fid, ty)| {
+                                let is_visible = matches!(adt, hir_def::AdtId::EnumId(..))
+                                    || visibilities[fid]
+                                        .is_visible_from(self.db.upcast(), self.module);
+                                let is_uninhabited = self.is_uninhabited(&ty);
+                                let private_uninhabited =
+                                    is_uninhabited && (!is_visible || is_non_exhaustive);
+                                (ty, PrivateUninhabitedField(private_uninhabited))
+                            })
+                            .collect()
                     }
                 }
                 ty_kind => {
@@ -383,7 +378,7 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
             },
             Slice(_) => unreachable!("Found a `Slice` constructor in match checking"),
             Bool(..) | IntRange(..) | F32Range(..) | F64Range(..) | Str(..) | Opaque(..)
-            | NonExhaustive | Hidden | Missing | Wildcard => smallvec![],
+            | NonExhaustive | PrivateUninhabited | Hidden | Missing | Wildcard => smallvec![],
             Or => {
                 never!("called `Fields::wildcards` on an `Or` ctor");
                 smallvec![]
@@ -478,6 +473,11 @@ impl<'p> TypeCx for MatchCheckCtx<'p> {
     fn bug(&self, fmt: fmt::Arguments<'_>) {
         debug!("{}", fmt)
     }
+
+    fn complexity_exceeded(&self) -> Result<(), Self::Error> {
+        // FIXME(Nadrieril): make use of the complexity counter.
+        Err(())
+    }
 }
 
 impl<'p> fmt::Debug for MatchCheckCtx<'p> {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
index fe51ec3f821..20964f5acbd 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -63,6 +63,7 @@ pub struct HirFormatter<'a> {
     buf: String,
     curr_size: usize,
     pub(crate) max_size: Option<usize>,
+    pub entity_limit: Option<usize>,
     omit_verbose_types: bool,
     closure_style: ClosureStyle,
     display_target: DisplayTarget,
@@ -86,6 +87,7 @@ pub trait HirDisplay {
         &'a self,
         db: &'a dyn HirDatabase,
         max_size: Option<usize>,
+        limited_size: Option<usize>,
         omit_verbose_types: bool,
         display_target: DisplayTarget,
         closure_style: ClosureStyle,
@@ -101,6 +103,7 @@ pub trait HirDisplay {
             db,
             t: self,
             max_size,
+            limited_size,
             omit_verbose_types,
             display_target,
             closure_style,
@@ -117,6 +120,7 @@ pub trait HirDisplay {
             db,
             t: self,
             max_size: None,
+            limited_size: None,
             omit_verbose_types: false,
             closure_style: ClosureStyle::ImplFn,
             display_target: DisplayTarget::Diagnostics,
@@ -137,6 +141,28 @@ pub trait HirDisplay {
             db,
             t: self,
             max_size,
+            limited_size: None,
+            omit_verbose_types: true,
+            closure_style: ClosureStyle::ImplFn,
+            display_target: DisplayTarget::Diagnostics,
+        }
+    }
+
+    /// Returns a `Display`able type that is human-readable and tries to limit the number of items inside.
+    /// Use this for showing definitions which may contain too many items, like `trait`, `struct`, `enum`
+    fn display_limited<'a>(
+        &'a self,
+        db: &'a dyn HirDatabase,
+        limited_size: Option<usize>,
+    ) -> HirDisplayWrapper<'a, Self>
+    where
+        Self: Sized,
+    {
+        HirDisplayWrapper {
+            db,
+            t: self,
+            max_size: None,
+            limited_size,
             omit_verbose_types: true,
             closure_style: ClosureStyle::ImplFn,
             display_target: DisplayTarget::Diagnostics,
@@ -158,6 +184,7 @@ pub trait HirDisplay {
             buf: String::with_capacity(20),
             curr_size: 0,
             max_size: None,
+            entity_limit: None,
             omit_verbose_types: false,
             closure_style: ClosureStyle::ImplFn,
             display_target: DisplayTarget::SourceCode { module_id, allow_opaque },
@@ -178,6 +205,7 @@ pub trait HirDisplay {
             db,
             t: self,
             max_size: None,
+            limited_size: None,
             omit_verbose_types: false,
             closure_style: ClosureStyle::ImplFn,
             display_target: DisplayTarget::Test,
@@ -295,6 +323,7 @@ pub struct HirDisplayWrapper<'a, T> {
     db: &'a dyn HirDatabase,
     t: &'a T,
     max_size: Option<usize>,
+    limited_size: Option<usize>,
     omit_verbose_types: bool,
     closure_style: ClosureStyle,
     display_target: DisplayTarget,
@@ -323,6 +352,7 @@ impl<T: HirDisplay> HirDisplayWrapper<'_, T> {
             buf: String::with_capacity(20),
             curr_size: 0,
             max_size: self.max_size,
+            entity_limit: self.limited_size,
             omit_verbose_types: self.omit_verbose_types,
             display_target: self.display_target,
             closure_style: self.closure_style,
@@ -1751,10 +1781,7 @@ impl HirDisplay for TypeRef {
                 f.write_joined(bounds, " + ")?;
             }
             TypeRef::Macro(macro_call) => {
-                let ctx = hir_def::lower::LowerCtx::with_span_map(
-                    f.db.upcast(),
-                    f.db.span_map(macro_call.file_id),
-                );
+                let ctx = hir_def::lower::LowerCtx::new(f.db.upcast(), macro_call.file_id);
                 let macro_call = macro_call.to_node(f.db.upcast());
                 match macro_call.path() {
                     Some(path) => match Path::from_src(&ctx, path) {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
index a1be6018083..dea292711d8 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs
@@ -1,7 +1,6 @@
 //! Compute the binary representation of a type
 
-use std::borrow::Cow;
-use std::fmt;
+use std::{borrow::Cow, fmt};
 
 use base_db::salsa::Cycle;
 use chalk_ir::{AdtId, FloatTy, IntTy, TyKind, UintTy};
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
index 75ac3b0d66b..dac20f22597 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
@@ -995,12 +995,12 @@ impl<'a> TyLoweringContext<'a> {
 
     pub(crate) fn lower_type_bound(
         &'a self,
-        bound: &'a TypeBound,
+        bound: &'a Interned<TypeBound>,
         self_ty: Ty,
         ignore_bindings: bool,
     ) -> impl Iterator<Item = QuantifiedWhereClause> + 'a {
         let mut bindings = None;
-        let trait_ref = match bound {
+        let trait_ref = match bound.as_ref() {
             TypeBound::Path(path, TraitBoundModifier::None) => {
                 bindings = self.lower_trait_ref_from_path(path, Some(self_ty));
                 bindings
@@ -1055,10 +1055,10 @@ impl<'a> TyLoweringContext<'a> {
 
     fn assoc_type_bindings_from_type_bound(
         &'a self,
-        bound: &'a TypeBound,
+        bound: &'a Interned<TypeBound>,
         trait_ref: TraitRef,
     ) -> impl Iterator<Item = QuantifiedWhereClause> + 'a {
-        let last_segment = match bound {
+        let last_segment = match bound.as_ref() {
             TypeBound::Path(path, TraitBoundModifier::None) | TypeBound::ForLifetime(_, path) => {
                 path.segments().last()
             }
@@ -1121,7 +1121,63 @@ impl<'a> TyLoweringContext<'a> {
                             );
                         }
                     } else {
-                        let ty = self.lower_ty(type_ref);
+                        let ty = 'ty: {
+                            if matches!(
+                                self.impl_trait_mode,
+                                ImplTraitLoweringState::Param(_)
+                                    | ImplTraitLoweringState::Variable(_)
+                            ) {
+                                // Find the generic index for the target of our `bound`
+                                let target_param_idx = self
+                                    .resolver
+                                    .where_predicates_in_scope()
+                                    .find_map(|p| match p {
+                                        WherePredicate::TypeBound {
+                                            target: WherePredicateTypeTarget::TypeOrConstParam(idx),
+                                            bound: b,
+                                        } if b == bound => Some(idx),
+                                        _ => None,
+                                    });
+                                if let Some(target_param_idx) = target_param_idx {
+                                    let mut counter = 0;
+                                    for (idx, data) in self.generics().params.type_or_consts.iter()
+                                    {
+                                        // Count the number of `impl Trait` things that appear before
+                                        // the target of our `bound`.
+                                        // Our counter within `impl_trait_mode` should be that number
+                                        // to properly lower each types within `type_ref`
+                                        if data.type_param().is_some_and(|p| {
+                                            p.provenance == TypeParamProvenance::ArgumentImplTrait
+                                        }) {
+                                            counter += 1;
+                                        }
+                                        if idx == *target_param_idx {
+                                            break;
+                                        }
+                                    }
+                                    let mut ext = TyLoweringContext::new_maybe_unowned(
+                                        self.db,
+                                        self.resolver,
+                                        self.owner,
+                                    )
+                                    .with_type_param_mode(self.type_param_mode);
+                                    match &self.impl_trait_mode {
+                                        ImplTraitLoweringState::Param(_) => {
+                                            ext.impl_trait_mode =
+                                                ImplTraitLoweringState::Param(Cell::new(counter));
+                                        }
+                                        ImplTraitLoweringState::Variable(_) => {
+                                            ext.impl_trait_mode = ImplTraitLoweringState::Variable(
+                                                Cell::new(counter),
+                                            );
+                                        }
+                                        _ => unreachable!(),
+                                    }
+                                    break 'ty ext.lower_ty(type_ref);
+                                }
+                            }
+                            self.lower_ty(type_ref)
+                        };
                         let alias_eq =
                             AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty };
                         predicates.push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq)));
@@ -1403,8 +1459,14 @@ pub(crate) fn generic_predicates_for_param_query(
     assoc_name: Option<Name>,
 ) -> Arc<[Binders<QuantifiedWhereClause>]> {
     let resolver = def.resolver(db.upcast());
-    let ctx = TyLoweringContext::new(db, &resolver, def.into())
-        .with_type_param_mode(ParamLoweringMode::Variable);
+    let ctx = if let GenericDefId::FunctionId(_) = def {
+        TyLoweringContext::new(db, &resolver, def.into())
+            .with_impl_trait_mode(ImplTraitLoweringMode::Variable)
+            .with_type_param_mode(ParamLoweringMode::Variable)
+    } else {
+        TyLoweringContext::new(db, &resolver, def.into())
+            .with_type_param_mode(ParamLoweringMode::Variable)
+    };
     let generics = generics(db.upcast(), def);
 
     // we have to filter out all other predicates *first*, before attempting to lower them
@@ -1490,8 +1552,14 @@ pub(crate) fn trait_environment_query(
     def: GenericDefId,
 ) -> Arc<TraitEnvironment> {
     let resolver = def.resolver(db.upcast());
-    let ctx = TyLoweringContext::new(db, &resolver, def.into())
-        .with_type_param_mode(ParamLoweringMode::Placeholder);
+    let ctx = if let GenericDefId::FunctionId(_) = def {
+        TyLoweringContext::new(db, &resolver, def.into())
+            .with_impl_trait_mode(ImplTraitLoweringMode::Param)
+            .with_type_param_mode(ParamLoweringMode::Placeholder)
+    } else {
+        TyLoweringContext::new(db, &resolver, def.into())
+            .with_type_param_mode(ParamLoweringMode::Placeholder)
+    };
     let mut traits_in_scope = Vec::new();
     let mut clauses = Vec::new();
     for pred in resolver.where_predicates_in_scope() {
@@ -1549,8 +1617,14 @@ pub(crate) fn generic_predicates_query(
     def: GenericDefId,
 ) -> Arc<[Binders<QuantifiedWhereClause>]> {
     let resolver = def.resolver(db.upcast());
-    let ctx = TyLoweringContext::new(db, &resolver, def.into())
-        .with_type_param_mode(ParamLoweringMode::Variable);
+    let ctx = if let GenericDefId::FunctionId(_) = def {
+        TyLoweringContext::new(db, &resolver, def.into())
+            .with_impl_trait_mode(ImplTraitLoweringMode::Variable)
+            .with_type_param_mode(ParamLoweringMode::Variable)
+    } else {
+        TyLoweringContext::new(db, &resolver, def.into())
+            .with_type_param_mode(ParamLoweringMode::Variable)
+    };
     let generics = generics(db.upcast(), def);
 
     let mut predicates = resolver
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
index ed316f97268..d0f739e6ac6 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
@@ -1364,10 +1364,16 @@ impl<'ctx> MirLowerCtx<'ctx> {
         match loc {
             LiteralOrConst::Literal(l) => self.lower_literal_to_operand(ty, l),
             LiteralOrConst::Const(c) => {
-                let unresolved_name = || MirLowerError::unresolved_path(self.db, c);
+                let c = match &self.body.pats[*c] {
+                    Pat::Path(p) => p,
+                    _ => not_supported!(
+                        "only `char` and numeric types are allowed in range patterns"
+                    ),
+                };
+                let unresolved_name = || MirLowerError::unresolved_path(self.db, c.as_ref());
                 let resolver = self.owner.resolver(self.db.upcast());
                 let pr = resolver
-                    .resolve_path_in_value_ns(self.db.upcast(), c)
+                    .resolve_path_in_value_ns(self.db.upcast(), c.as_ref())
                     .ok_or_else(unresolved_name)?;
                 match pr {
                     ResolveValueResult::ValueNs(v, _) => {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
index 39c5547b8d0..b80cfe18e4c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/tests/traits.rs
@@ -1232,6 +1232,53 @@ fn test(x: impl Trait<u64>, y: &impl Trait<u64>) {
 }
 
 #[test]
+fn argument_impl_trait_with_projection() {
+    check_infer(
+        r#"
+trait X {
+    type Item;
+}
+
+impl<T> X for [T; 2] {
+    type Item = T;
+}
+
+trait Y {}
+
+impl<T> Y for T {}
+
+enum R<T, U> {
+    A(T),
+    B(U),
+}
+
+fn foo<T>(x: impl X<Item = R<impl Y, T>>) -> T { loop {} }
+
+fn bar() {
+    let a = foo([R::A(()), R::B(7)]);
+}
+"#,
+        expect![[r#"
+            153..154 'x': impl X<Item = R<impl Y + ?Sized, T>> + ?Sized
+            190..201 '{ loop {} }': T
+            192..199 'loop {}': !
+            197..199 '{}': ()
+            212..253 '{     ...)]); }': ()
+            222..223 'a': i32
+            226..229 'foo': fn foo<i32>([R<(), i32>; 2]) -> i32
+            226..250 'foo([R...B(7)])': i32
+            230..249 '[R::A(...:B(7)]': [R<(), i32>; 2]
+            231..235 'R::A': extern "rust-call" A<(), i32>(()) -> R<(), i32>
+            231..239 'R::A(())': R<(), i32>
+            236..238 '()': ()
+            241..245 'R::B': extern "rust-call" B<(), i32>(i32) -> R<(), i32>
+            241..248 'R::B(7)': R<(), i32>
+            246..247 '7': i32
+        "#]],
+    );
+}
+
+#[test]
 fn simple_return_pos_impl_trait() {
     cov_mark::check!(lower_rpit);
     check_infer(
diff --git a/src/tools/rust-analyzer/crates/hir/Cargo.toml b/src/tools/rust-analyzer/crates/hir/Cargo.toml
index 7fea8372876..190722075a2 100644
--- a/src/tools/rust-analyzer/crates/hir/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/hir/Cargo.toml
@@ -27,7 +27,6 @@ cfg.workspace = true
 hir-def.workspace = true
 hir-expand.workspace = true
 hir-ty.workspace = true
-profile.workspace = true
 stdx.workspace = true
 syntax.workspace = true
 tt.workspace = true
diff --git a/src/tools/rust-analyzer/crates/hir/src/db.rs b/src/tools/rust-analyzer/crates/hir/src/db.rs
index 557c8d29a17..1d74f9a4bb2 100644
--- a/src/tools/rust-analyzer/crates/hir/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/db.rs
@@ -4,20 +4,20 @@
 //!
 //! But we need this for at least LRU caching at the query level.
 pub use hir_def::db::{
-    AttrsQuery, BlockDefMapQuery, BlockItemTreeQueryQuery, BodyQuery, BodyWithSourceMapQuery,
-    ConstDataQuery, ConstVisibilityQuery, CrateDefMapQueryQuery, CrateLangItemsQuery,
-    CrateSupportsNoStdQuery, DefDatabase, DefDatabaseStorage, EnumDataQuery,
-    EnumVariantDataWithDiagnosticsQuery, ExprScopesQuery, ExternCrateDeclDataQuery,
-    FieldVisibilitiesQuery, FieldsAttrsQuery, FieldsAttrsSourceMapQuery, FileItemTreeQuery,
-    FunctionDataQuery, FunctionVisibilityQuery, GenericParamsQuery, ImplDataWithDiagnosticsQuery,
-    ImportMapQuery, InternAnonymousConstQuery, InternBlockQuery, InternConstQuery, InternDatabase,
-    InternDatabaseStorage, InternEnumQuery, InternExternBlockQuery, InternExternCrateQuery,
-    InternFunctionQuery, InternImplQuery, InternInTypeConstQuery, InternMacro2Query,
-    InternMacroRulesQuery, InternProcMacroQuery, InternStaticQuery, InternStructQuery,
-    InternTraitAliasQuery, InternTraitQuery, InternTypeAliasQuery, InternUnionQuery,
-    InternUseQuery, LangItemQuery, Macro2DataQuery, MacroRulesDataQuery, ProcMacroDataQuery,
-    StaticDataQuery, StructDataWithDiagnosticsQuery, TraitAliasDataQuery,
-    TraitDataWithDiagnosticsQuery, TypeAliasDataQuery, UnionDataWithDiagnosticsQuery,
+    AttrsQuery, BlockDefMapQuery, BodyQuery, BodyWithSourceMapQuery, ConstDataQuery,
+    ConstVisibilityQuery, CrateLangItemsQuery, CrateSupportsNoStdQuery, DefDatabase,
+    DefDatabaseStorage, EnumDataQuery, EnumVariantDataWithDiagnosticsQuery, ExprScopesQuery,
+    ExternCrateDeclDataQuery, FieldVisibilitiesQuery, FieldsAttrsQuery, FieldsAttrsSourceMapQuery,
+    FileItemTreeQuery, FunctionDataQuery, FunctionVisibilityQuery, GenericParamsQuery,
+    ImplDataWithDiagnosticsQuery, ImportMapQuery, InternAnonymousConstQuery, InternBlockQuery,
+    InternConstQuery, InternDatabase, InternDatabaseStorage, InternEnumQuery,
+    InternExternBlockQuery, InternExternCrateQuery, InternFunctionQuery, InternImplQuery,
+    InternInTypeConstQuery, InternMacro2Query, InternMacroRulesQuery, InternProcMacroQuery,
+    InternStaticQuery, InternStructQuery, InternTraitAliasQuery, InternTraitQuery,
+    InternTypeAliasQuery, InternUnionQuery, InternUseQuery, LangItemQuery, Macro2DataQuery,
+    MacroRulesDataQuery, ProcMacroDataQuery, StaticDataQuery, StructDataWithDiagnosticsQuery,
+    TraitAliasDataQuery, TraitDataWithDiagnosticsQuery, TypeAliasDataQuery,
+    UnionDataWithDiagnosticsQuery,
 };
 pub use hir_expand::db::{
     AstIdMapQuery, DeclMacroExpanderQuery, ExpandDatabase, ExpandDatabaseStorage,
diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs
index 30f402a79f3..cdc0db8653c 100644
--- a/src/tools/rust-analyzer/crates/hir/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/display.rs
@@ -17,10 +17,10 @@ use hir_ty::{
 };
 
 use crate::{
-    Adt, AsAssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl, Field,
-    Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, SelfParam,
-    Static, Struct, Trait, TraitAlias, TupleField, TyBuilder, Type, TypeAlias, TypeOrConstParam,
-    TypeParam, Union, Variant,
+    Adt, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl,
+    Field, Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module,
+    SelfParam, Static, Struct, Trait, TraitAlias, TupleField, TyBuilder, Type, TypeAlias,
+    TypeOrConstParam, TypeParam, Union, Variant,
 };
 
 impl HirDisplay for Function {
@@ -595,6 +595,35 @@ impl HirDisplay for Trait {
         let def_id = GenericDefId::TraitId(self.id);
         write_generic_params(def_id, f)?;
         write_where_clause(def_id, f)?;
+
+        if let Some(limit) = f.entity_limit {
+            let assoc_items = self.items(f.db);
+            let count = assoc_items.len().min(limit);
+            if count == 0 {
+                if assoc_items.is_empty() {
+                    f.write_str(" {}")?;
+                } else {
+                    f.write_str(" { /* … */ }")?;
+                }
+            } else {
+                f.write_str(" {\n")?;
+                for item in &assoc_items[..count] {
+                    f.write_str("    ")?;
+                    match item {
+                        AssocItem::Function(func) => func.hir_fmt(f),
+                        AssocItem::Const(cst) => cst.hir_fmt(f),
+                        AssocItem::TypeAlias(type_alias) => type_alias.hir_fmt(f),
+                    }?;
+                    f.write_str(";\n")?;
+                }
+
+                if assoc_items.len() > count {
+                    f.write_str("    /* … */\n")?;
+                }
+                f.write_str("}")?;
+            }
+        }
+
         Ok(())
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 5c607030167..5eed7ecd5b2 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -126,7 +126,7 @@ pub use {
     },
     hir_expand::{
         attrs::{Attr, AttrId},
-        change::Change,
+        change::ChangeWithProcMacros,
         hygiene::{marks_rev, SyntaxContextExt},
         name::{known, Name},
         proc_macro::ProcMacros,
@@ -365,7 +365,7 @@ impl ModuleDef {
         Some(name)
     }
 
-    pub fn diagnostics(self, db: &dyn HirDatabase) -> Vec<AnyDiagnostic> {
+    pub fn diagnostics(self, db: &dyn HirDatabase, style_lints: bool) -> Vec<AnyDiagnostic> {
         let id = match self {
             ModuleDef::Adt(it) => match it {
                 Adt::Struct(it) => it.id.into(),
@@ -387,7 +387,7 @@ impl ModuleDef {
 
         match self.as_def_with_body() {
             Some(def) => {
-                def.diagnostics(db, &mut acc);
+                def.diagnostics(db, &mut acc, style_lints);
             }
             None => {
                 for diag in hir_ty::diagnostics::incorrect_case(db, id) {
@@ -541,7 +541,12 @@ impl Module {
     }
 
     /// Fills `acc` with the module's diagnostics.
-    pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
+    pub fn diagnostics(
+        self,
+        db: &dyn HirDatabase,
+        acc: &mut Vec<AnyDiagnostic>,
+        style_lints: bool,
+    ) {
         let name = self.name(db);
         let _p = tracing::span!(tracing::Level::INFO, "Module::diagnostics", ?name);
         let def_map = self.id.def_map(db.upcast());
@@ -558,9 +563,9 @@ impl Module {
                 ModuleDef::Module(m) => {
                     // Only add diagnostics from inline modules
                     if def_map[m.id.local_id].origin.is_inline() {
-                        m.diagnostics(db, acc)
+                        m.diagnostics(db, acc, style_lints)
                     }
-                    acc.extend(def.diagnostics(db))
+                    acc.extend(def.diagnostics(db, style_lints))
                 }
                 ModuleDef::Trait(t) => {
                     for diag in db.trait_data_with_diagnostics(t.id).1.iter() {
@@ -568,10 +573,10 @@ impl Module {
                     }
 
                     for item in t.items(db) {
-                        item.diagnostics(db, acc);
+                        item.diagnostics(db, acc, style_lints);
                     }
 
-                    acc.extend(def.diagnostics(db))
+                    acc.extend(def.diagnostics(db, style_lints))
                 }
                 ModuleDef::Adt(adt) => {
                     match adt {
@@ -587,17 +592,17 @@ impl Module {
                         }
                         Adt::Enum(e) => {
                             for v in e.variants(db) {
-                                acc.extend(ModuleDef::Variant(v).diagnostics(db));
+                                acc.extend(ModuleDef::Variant(v).diagnostics(db, style_lints));
                                 for diag in db.enum_variant_data_with_diagnostics(v.id).1.iter() {
                                     emit_def_diagnostic(db, acc, diag);
                                 }
                             }
                         }
                     }
-                    acc.extend(def.diagnostics(db))
+                    acc.extend(def.diagnostics(db, style_lints))
                 }
                 ModuleDef::Macro(m) => emit_macro_def_diagnostics(db, acc, m),
-                _ => acc.extend(def.diagnostics(db)),
+                _ => acc.extend(def.diagnostics(db, style_lints)),
             }
         }
         self.legacy_macros(db).into_iter().for_each(|m| emit_macro_def_diagnostics(db, acc, m));
@@ -738,7 +743,7 @@ impl Module {
             }
 
             for &item in &db.impl_data(impl_def.id).items {
-                AssocItem::from(item).diagnostics(db, acc);
+                AssocItem::from(item).diagnostics(db, acc, style_lints);
             }
         }
     }
@@ -1616,14 +1621,19 @@ impl DefWithBody {
         }
     }
 
-    pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
+    pub fn diagnostics(
+        self,
+        db: &dyn HirDatabase,
+        acc: &mut Vec<AnyDiagnostic>,
+        style_lints: bool,
+    ) {
         db.unwind_if_cancelled();
         let krate = self.module(db).id.krate();
 
         let (body, source_map) = db.body_with_source_map(self.into());
 
         for (_, def_map) in body.blocks(db.upcast()) {
-            Module { id: def_map.module_id(DefMap::ROOT) }.diagnostics(db, acc);
+            Module { id: def_map.module_id(DefMap::ROOT) }.diagnostics(db, acc, style_lints);
         }
 
         for diag in source_map.diagnostics() {
@@ -1784,7 +1794,7 @@ impl DefWithBody {
             }
         }
 
-        for diagnostic in BodyValidationDiagnostic::collect(db, self.into()) {
+        for diagnostic in BodyValidationDiagnostic::collect(db, self.into(), style_lints) {
             acc.extend(AnyDiagnostic::body_validation_diagnostic(db, diagnostic, &source_map));
         }
 
@@ -2098,6 +2108,14 @@ pub struct Param {
 }
 
 impl Param {
+    pub fn parent_fn(&self) -> Function {
+        self.func
+    }
+
+    pub fn index(&self) -> usize {
+        self.idx
+    }
+
     pub fn ty(&self) -> &Type {
         &self.ty
     }
@@ -2162,6 +2180,10 @@ impl SelfParam {
             .map(|value| InFile { file_id, value })
     }
 
+    pub fn parent_fn(&self) -> Function {
+        Function::from(self.func)
+    }
+
     pub fn ty(&self, db: &dyn HirDatabase) -> Type {
         let substs = TyBuilder::placeholder_subst(db, self.func);
         let callable_sig =
@@ -2897,13 +2919,18 @@ impl AssocItem {
         }
     }
 
-    pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
+    pub fn diagnostics(
+        self,
+        db: &dyn HirDatabase,
+        acc: &mut Vec<AnyDiagnostic>,
+        style_lints: bool,
+    ) {
         match self {
             AssocItem::Function(func) => {
-                DefWithBody::from(func).diagnostics(db, acc);
+                DefWithBody::from(func).diagnostics(db, acc, style_lints);
             }
             AssocItem::Const(const_) => {
-                DefWithBody::from(const_).diagnostics(db, acc);
+                DefWithBody::from(const_).diagnostics(db, acc, style_lints);
             }
             AssocItem::TypeAlias(type_alias) => {
                 for diag in hir_ty::diagnostics::incorrect_case(db, type_alias.id.into()) {
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
index cfda8d4f937..99907ea15b5 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
@@ -38,10 +38,11 @@ use crate::{
     db::HirDatabase,
     semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
     source_analyzer::{resolve_hir_path, SourceAnalyzer},
-    Access, Adjust, Adjustment, AutoBorrow, BindingMode, BuiltinAttr, Callable, ConstParam, Crate,
-    DeriveHelper, Field, Function, HasSource, HirFileId, Impl, InFile, Label, LifetimeParam, Local,
-    Macro, Module, ModuleDef, Name, OverloadedDeref, Path, ScopeDef, Struct, ToolModule, Trait,
-    TupleField, Type, TypeAlias, TypeParam, VariantDef,
+    Access, Adjust, Adjustment, Adt, AutoBorrow, BindingMode, BuiltinAttr, Callable, Const,
+    ConstParam, Crate, DeriveHelper, Enum, Field, Function, HasSource, HirFileId, Impl, InFile,
+    Label, LifetimeParam, Local, Macro, Module, ModuleDef, Name, OverloadedDeref, Path, ScopeDef,
+    Static, Struct, ToolModule, Trait, TraitAlias, TupleField, Type, TypeAlias, TypeParam, Union,
+    Variant, VariantDef,
 };
 
 pub enum DescendPreference {
@@ -223,21 +224,69 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
         self.imp.resolve_variant(record_lit).map(VariantDef::from)
     }
 
-    pub fn to_module_def(&self, file: FileId) -> Option<Module> {
-        self.imp.to_module_def(file).next()
+    pub fn file_to_module_def(&self, file: FileId) -> Option<Module> {
+        self.imp.file_to_module_defs(file).next()
     }
 
-    pub fn to_module_defs(&self, file: FileId) -> impl Iterator<Item = Module> {
-        self.imp.to_module_def(file)
+    pub fn file_to_module_defs(&self, file: FileId) -> impl Iterator<Item = Module> {
+        self.imp.file_to_module_defs(file)
     }
 
-    pub fn to_struct_def(&self, s: &ast::Struct) -> Option<Struct> {
-        self.imp.to_def(s).map(Struct::from)
+    pub fn to_adt_def(&self, a: &ast::Adt) -> Option<Adt> {
+        self.imp.to_def(a).map(Adt::from)
+    }
+
+    pub fn to_const_def(&self, c: &ast::Const) -> Option<Const> {
+        self.imp.to_def(c).map(Const::from)
+    }
+
+    pub fn to_enum_def(&self, e: &ast::Enum) -> Option<Enum> {
+        self.imp.to_def(e).map(Enum::from)
+    }
+
+    pub fn to_enum_variant_def(&self, v: &ast::Variant) -> Option<Variant> {
+        self.imp.to_def(v).map(Variant::from)
+    }
+
+    pub fn to_fn_def(&self, f: &ast::Fn) -> Option<Function> {
+        self.imp.to_def(f).map(Function::from)
     }
 
     pub fn to_impl_def(&self, i: &ast::Impl) -> Option<Impl> {
         self.imp.to_def(i).map(Impl::from)
     }
+
+    pub fn to_macro_def(&self, m: &ast::Macro) -> Option<Macro> {
+        self.imp.to_def(m).map(Macro::from)
+    }
+
+    pub fn to_module_def(&self, m: &ast::Module) -> Option<Module> {
+        self.imp.to_def(m).map(Module::from)
+    }
+
+    pub fn to_static_def(&self, s: &ast::Static) -> Option<Static> {
+        self.imp.to_def(s).map(Static::from)
+    }
+
+    pub fn to_struct_def(&self, s: &ast::Struct) -> Option<Struct> {
+        self.imp.to_def(s).map(Struct::from)
+    }
+
+    pub fn to_trait_alias_def(&self, t: &ast::TraitAlias) -> Option<TraitAlias> {
+        self.imp.to_def(t).map(TraitAlias::from)
+    }
+
+    pub fn to_trait_def(&self, t: &ast::Trait) -> Option<Trait> {
+        self.imp.to_def(t).map(Trait::from)
+    }
+
+    pub fn to_type_alias_def(&self, t: &ast::TypeAlias) -> Option<TypeAlias> {
+        self.imp.to_def(t).map(TypeAlias::from)
+    }
+
+    pub fn to_union_def(&self, u: &ast::Union) -> Option<Union> {
+        self.imp.to_def(u).map(Union::from)
+    }
 }
 
 impl<'db> SemanticsImpl<'db> {
@@ -1024,7 +1073,7 @@ impl<'db> SemanticsImpl<'db> {
 
     pub fn resolve_type(&self, ty: &ast::Type) -> Option<Type> {
         let analyze = self.analyze(ty.syntax())?;
-        let ctx = LowerCtx::with_file_id(self.db.upcast(), analyze.file_id);
+        let ctx = LowerCtx::new(self.db.upcast(), analyze.file_id);
         let ty = hir_ty::TyLoweringContext::new_maybe_unowned(
             self.db,
             &analyze.resolver,
@@ -1036,8 +1085,7 @@ impl<'db> SemanticsImpl<'db> {
 
     pub fn resolve_trait(&self, path: &ast::Path) -> Option<Trait> {
         let analyze = self.analyze(path.syntax())?;
-        let span_map = self.db.span_map(analyze.file_id);
-        let ctx = LowerCtx::with_span_map(self.db.upcast(), span_map);
+        let ctx = LowerCtx::new(self.db.upcast(), analyze.file_id);
         let hir_path = Path::from_src(&ctx, path.clone())?;
         match analyze.resolver.resolve_path_in_type_ns_fully(self.db.upcast(), &hir_path)? {
             TypeNs::TraitId(id) => Some(Trait { id }),
@@ -1241,7 +1289,7 @@ impl<'db> SemanticsImpl<'db> {
         T::to_def(self, src)
     }
 
-    fn to_module_def(&self, file: FileId) -> impl Iterator<Item = Module> {
+    fn file_to_module_defs(&self, file: FileId) -> impl Iterator<Item = Module> {
         self.with_ctx(|ctx| ctx.file_to_def(file)).into_iter().map(Module::from)
     }
 
@@ -1645,7 +1693,7 @@ impl SemanticsScope<'_> {
     /// Resolve a path as-if it was written at the given scope. This is
     /// necessary a heuristic, as it doesn't take hygiene into account.
     pub fn speculative_resolve(&self, path: &ast::Path) -> Option<PathResolution> {
-        let ctx = LowerCtx::with_file_id(self.db.upcast(), self.file_id);
+        let ctx = LowerCtx::new(self.db.upcast(), self.file_id);
         let path = Path::from_src(&ctx, path.clone())?;
         resolve_hir_path(self.db, &self.resolver, &path)
     }
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
index ef4ed90ce35..4733ea5a35b 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs
@@ -118,7 +118,7 @@ pub(super) struct SourceToDefCtx<'a, 'b> {
 
 impl SourceToDefCtx<'_, '_> {
     pub(super) fn file_to_def(&self, file: FileId) -> SmallVec<[ModuleId; 1]> {
-        let _p = tracing::span!(tracing::Level::INFO, "SourceBinder::to_module_def");
+        let _p = tracing::span!(tracing::Level::INFO, "SourceBinder::file_to_module_def");
         let mut mods = SmallVec::new();
         for &crate_id in self.db.relevant_crates(file).iter() {
             // FIXME: inner items
diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
index a147102bcd8..f87e0a3897a 100644
--- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
@@ -549,7 +549,7 @@ impl SourceAnalyzer {
         db: &dyn HirDatabase,
         macro_call: InFile<&ast::MacroCall>,
     ) -> Option<Macro> {
-        let ctx = LowerCtx::with_file_id(db.upcast(), macro_call.file_id);
+        let ctx = LowerCtx::new(db.upcast(), macro_call.file_id);
         let path = macro_call.value.path().and_then(|ast| Path::from_src(&ctx, ast))?;
         self.resolver
             .resolve_path_as_macro(db.upcast(), path.mod_path()?, Some(MacroSubNs::Bang))
@@ -662,7 +662,7 @@ impl SourceAnalyzer {
         }
 
         // This must be a normal source file rather than macro file.
-        let ctx = LowerCtx::with_span_map(db.upcast(), db.span_map(self.file_id));
+        let ctx = LowerCtx::new(db.upcast(), self.file_id);
         let hir_path = Path::from_src(&ctx, path.clone())?;
 
         // Case where path is a qualifier of a use tree, e.g. foo::bar::{Baz, Qux} where we are
diff --git a/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml b/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml
index 98961a18de2..b1e7609afef 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-assists/Cargo.toml
@@ -23,7 +23,6 @@ tracing.workspace = true
 stdx.workspace = true
 syntax.workspace = true
 text-edit.workspace = true
-profile.workspace = true
 ide-db.workspace = true
 hir.workspace = true
 
@@ -33,10 +32,6 @@ expect-test = "1.4.0"
 # local deps
 test-utils.workspace = true
 test-fixture.workspace = true
-sourcegen.workspace = true
-
-[features]
-in-rust-tree = []
 
 [lints]
 workspace = true
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs
index 4edc52b614a..c1a3f930265 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/destructure_struct_binding.rs
@@ -107,6 +107,10 @@ fn collect_data(ident_pat: ast::IdentPat, ctx: &AssistContext<'_>) -> Option<Str
     let visible_fields =
         fields.into_iter().filter(|field| field.is_visible_from(ctx.db(), module)).collect_vec();
 
+    if visible_fields.is_empty() {
+        return None;
+    }
+
     let has_private_members =
         (is_non_exhaustive && is_foreign_crate) || visible_fields.len() < n_fields;
 
@@ -413,7 +417,7 @@ mod tests {
 
     #[test]
     fn unit_struct() {
-        check_assist(
+        check_assist_not_applicable(
             destructure_struct_binding,
             r#"
             struct Foo;
@@ -422,13 +426,6 @@ mod tests {
                 let $0foo = Foo;
             }
             "#,
-            r#"
-            struct Foo;
-
-            fn main() {
-                let Foo = Foo;
-            }
-            "#,
         )
     }
 
@@ -739,4 +736,18 @@ mod tests {
             "#,
         )
     }
+
+    #[test]
+    fn record_struct_no_public_members() {
+        check_assist_not_applicable(
+            destructure_struct_binding,
+            r#"
+            //- /lib.rs crate:dep
+            pub struct Foo { bar: i32, baz: i32 };
+
+            //- /main.rs crate:main deps:dep
+            fn main($0foo: dep::Foo) {}
+            "#,
+        )
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs
index 9d72d3af096..2725a97de8e 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs
@@ -274,4 +274,22 @@ fn main() {
 "#,
         );
     }
+
+    #[test]
+    fn escaped_literals() {
+        check_assist(
+            extract_expressions_from_format_string,
+            r#"
+//- minicore: fmt
+fn main() {
+    print!("\n$ {x + 1}$0");
+}
+            "#,
+            r#"
+fn main() {
+    print!("\n$ {}"$0, x + 1);
+}
+            "#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs
index 7a60287f923..748acb46efb 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_trait.rs
@@ -16,7 +16,8 @@ use syntax::{
     ast::{
         self,
         edit::{self, AstNodeEdit},
-        make, AssocItem, GenericArgList, GenericParamList, HasGenericParams, HasName,
+        edit_in_place::AttrsOwnerEdit,
+        make, AssocItem, GenericArgList, GenericParamList, HasAttrs, HasGenericParams, HasName,
         HasTypeBounds, HasVisibility as astHasVisibility, Path, WherePred,
     },
     ted::{self, Position},
@@ -116,7 +117,7 @@ impl Field {
     ) -> Option<Field> {
         let db = ctx.sema.db;
 
-        let module = ctx.sema.to_module_def(ctx.file_id())?;
+        let module = ctx.sema.file_to_module_def(ctx.file_id())?;
 
         let (name, range, ty) = match f {
             Either::Left(f) => {
@@ -619,7 +620,8 @@ fn process_assoc_item(
     qual_path_ty: ast::Path,
     base_name: &str,
 ) -> Option<ast::AssocItem> {
-    match item {
+    let attrs = item.attrs();
+    let assoc = match item {
         AssocItem::Const(c) => const_assoc_item(c, qual_path_ty),
         AssocItem::Fn(f) => func_assoc_item(f, qual_path_ty, base_name),
         AssocItem::MacroCall(_) => {
@@ -628,7 +630,18 @@ fn process_assoc_item(
             None
         }
         AssocItem::TypeAlias(ta) => ty_assoc_item(ta, qual_path_ty),
+    };
+    if let Some(assoc) = &assoc {
+        attrs.for_each(|attr| {
+            assoc.add_attr(attr.clone());
+            // fix indentations
+            if let Some(tok) = attr.syntax().next_sibling_or_token() {
+                let pos = Position::after(tok);
+                ted::insert(pos, make::tokens::whitespace("    "));
+            }
+        })
     }
+    assoc
 }
 
 fn const_assoc_item(item: syntax::ast::Const, qual_path_ty: ast::Path) -> Option<AssocItem> {
@@ -1703,4 +1716,65 @@ impl some_module::SomeTrait for B {
 }"#,
         )
     }
+
+    #[test]
+    fn test_fn_with_attrs() {
+        check_assist(
+            generate_delegate_trait,
+            r#"
+struct A;
+
+trait T {
+    #[cfg(test)]
+    fn f(&self, a: u32);
+    #[cfg(not(test))]
+    fn f(&self, a: bool);
+}
+
+impl T for A {
+    #[cfg(test)]
+    fn f(&self, a: u32) {}
+    #[cfg(not(test))]
+    fn f(&self, a: bool) {}
+}
+
+struct B {
+    a$0: A,
+}
+"#,
+            r#"
+struct A;
+
+trait T {
+    #[cfg(test)]
+    fn f(&self, a: u32);
+    #[cfg(not(test))]
+    fn f(&self, a: bool);
+}
+
+impl T for A {
+    #[cfg(test)]
+    fn f(&self, a: u32) {}
+    #[cfg(not(test))]
+    fn f(&self, a: bool) {}
+}
+
+struct B {
+    a: A,
+}
+
+impl T for B {
+    #[cfg(test)]
+    fn f(&self, a: u32) {
+        <A as T>::f(&self.a, a)
+    }
+
+    #[cfg(not(test))]
+    fn f(&self, a: bool) {
+        <A as T>::f(&self.a, a)
+    }
+}
+"#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs
index 2b9ed86e41b..50ec4347dc2 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs
@@ -418,24 +418,15 @@ fn inline(
         let expr: &ast::Expr = expr;
 
         let mut insert_let_stmt = || {
-            let param_ty = match param_ty {
-                None => None,
-                Some(param_ty) => {
-                    if sema.hir_file_for(param_ty.syntax()).is_macro() {
-                        if let Some(param_ty) =
-                            ast::Type::cast(insert_ws_into(param_ty.syntax().clone()))
-                        {
-                            Some(param_ty)
-                        } else {
-                            Some(param_ty.clone_for_update())
-                        }
-                    } else {
-                        Some(param_ty.clone_for_update())
-                    }
+            let param_ty = param_ty.clone().map(|param_ty| {
+                if sema.hir_file_for(param_ty.syntax()).is_macro() {
+                    ast::Type::cast(insert_ws_into(param_ty.syntax().clone())).unwrap_or(param_ty)
+                } else {
+                    param_ty
                 }
-            };
-            let ty: Option<syntax::ast::Type> =
-                sema.type_of_expr(expr).filter(TypeInfo::has_adjustment).and(param_ty);
+            });
+
+            let ty = sema.type_of_expr(expr).filter(TypeInfo::has_adjustment).and(param_ty);
 
             let is_self = param
                 .name(sema.db)
@@ -1359,8 +1350,8 @@ macro_rules! define_foo {
 define_foo!();
 fn bar() -> u32 {
     {
-      let x = 0;
-      x
+        let x = 0;
+        x
     }
 }
 "#,
@@ -1673,7 +1664,7 @@ fn main() {
     let a: A = A{};
     let b = {
         let a = a;
-      a as A
+        a as A
     };
 }
 "#,
@@ -1792,7 +1783,7 @@ fn _hash2(self_: &u64, state: &mut u64) {
     {
         let inner_self_: &u64 = &self_;
         let state: &mut u64 = state;
-      _write_u64(state, *inner_self_)
+        _write_u64(state, *inner_self_)
     };
 }
 "#,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_macro.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_macro.rs
index 0c9e971dd23..4708be61696 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_macro.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_macro.rs
@@ -288,11 +288,11 @@ macro_rules! foo {
 }
 fn main() {
     cfg_if!{
-  if #[cfg(test)]{
-    1;
-  }else {
-    1;
-  }
+    if #[cfg(test)]{
+        1;
+    }else {
+        1;
+    }
 };
 }
 "#,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_from_mod_rs.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_from_mod_rs.rs
index 917d0b3671e..a256f60c421 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_from_mod_rs.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_from_mod_rs.rs
@@ -25,7 +25,7 @@ use crate::{
 // ```
 pub(crate) fn move_from_mod_rs(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
     let source_file = ctx.find_node_at_offset::<ast::SourceFile>()?;
-    let module = ctx.sema.to_module_def(ctx.file_id())?;
+    let module = ctx.sema.file_to_module_def(ctx.file_id())?;
     // Enable this assist if the user select all "meaningful" content in the source file
     let trimmed_selected_range = trimmed_text_range(&source_file, ctx.selection_trimmed());
     let trimmed_file_range = trimmed_text_range(&source_file, source_file.syntax().text_range());
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_to_mod_rs.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_to_mod_rs.rs
index b73270cd05f..a8a124eebb6 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_to_mod_rs.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/move_to_mod_rs.rs
@@ -25,7 +25,7 @@ use crate::{
 // ```
 pub(crate) fn move_to_mod_rs(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
     let source_file = ctx.find_node_at_offset::<ast::SourceFile>()?;
-    let module = ctx.sema.to_module_def(ctx.file_id())?;
+    let module = ctx.sema.file_to_module_def(ctx.file_id())?;
     // Enable this assist if the user select all "meaningful" content in the source file
     let trimmed_selected_range = trimmed_text_range(&source_file, ctx.selection_trimmed());
     let trimmed_file_range = trimmed_text_range(&source_file, source_file.syntax().text_range());
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs
index 9b6f7d018ee..32d69841020 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/tests.rs
@@ -1,6 +1,4 @@
 mod generated;
-#[cfg(not(feature = "in-rust-tree"))]
-mod sourcegen;
 
 use expect_test::expect;
 use hir::Semantics;
diff --git a/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml b/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml
index f2a11276ba2..6a4c70d460f 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-completion/Cargo.toml
@@ -23,7 +23,6 @@ smallvec.workspace = true
 # local deps
 base-db.workspace = true
 ide-db.workspace = true
-profile.workspace = true
 stdx.workspace = true
 syntax.workspace = true
 text-edit.workspace = true
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/format_string.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/format_string.rs
index cecbe75391d..5512ac21534 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/format_string.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/format_string.rs
@@ -1,6 +1,7 @@
 //! Completes identifiers in format string literals.
 
-use ide_db::syntax_helpers::format_string::is_format_string;
+use hir::{ModuleDef, ScopeDef};
+use ide_db::{syntax_helpers::format_string::is_format_string, SymbolKind};
 use itertools::Itertools;
 use syntax::{ast, AstToken, TextRange, TextSize};
 
@@ -33,7 +34,23 @@ pub(crate) fn format_string(
     ctx.locals.iter().for_each(|(name, _)| {
         CompletionItem::new(CompletionItemKind::Binding, source_range, name.to_smol_str())
             .add_to(acc, ctx.db);
-    })
+    });
+    ctx.scope.process_all_names(&mut |name, scope| {
+        if let ScopeDef::ModuleDef(module_def) = scope {
+            let symbol_kind = match module_def {
+                ModuleDef::Const(..) => SymbolKind::Const,
+                ModuleDef::Static(..) => SymbolKind::Static,
+                _ => return,
+            };
+
+            CompletionItem::new(
+                CompletionItemKind::SymbolKind(symbol_kind),
+                source_range,
+                name.to_smol_str(),
+            )
+            .add_to(acc, ctx.db);
+        }
+    });
 }
 
 #[cfg(test)]
@@ -113,4 +130,78 @@ fn main() {
 "#,
         );
     }
+
+    #[test]
+    fn completes_constants() {
+        check_edit(
+            "FOOBAR",
+            r#"
+//- minicore: fmt
+fn main() {
+    const FOOBAR: usize = 42;
+    format_args!("{f$0");
+}
+"#,
+            r#"
+fn main() {
+    const FOOBAR: usize = 42;
+    format_args!("{FOOBAR");
+}
+"#,
+        );
+
+        check_edit(
+            "FOOBAR",
+            r#"
+//- minicore: fmt
+fn main() {
+    const FOOBAR: usize = 42;
+    format_args!("{$0");
+}
+"#,
+            r#"
+fn main() {
+    const FOOBAR: usize = 42;
+    format_args!("{FOOBAR");
+}
+"#,
+        );
+    }
+
+    #[test]
+    fn completes_static_constants() {
+        check_edit(
+            "FOOBAR",
+            r#"
+//- minicore: fmt
+fn main() {
+    static FOOBAR: usize = 42;
+    format_args!("{f$0");
+}
+"#,
+            r#"
+fn main() {
+    static FOOBAR: usize = 42;
+    format_args!("{FOOBAR");
+}
+"#,
+        );
+
+        check_edit(
+            "FOOBAR",
+            r#"
+//- minicore: fmt
+fn main() {
+    static FOOBAR: usize = 42;
+    format_args!("{$0");
+}
+"#,
+            r#"
+fn main() {
+    static FOOBAR: usize = 42;
+    format_args!("{FOOBAR");
+}
+"#,
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs
index 72c0885e92f..361ad821f4a 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix.rs
@@ -258,7 +258,7 @@ pub(crate) fn complete_postfix(
 }
 
 fn get_receiver_text(receiver: &ast::Expr, receiver_is_ambiguous_float_literal: bool) -> String {
-    let text = if receiver_is_ambiguous_float_literal {
+    let mut text = if receiver_is_ambiguous_float_literal {
         let text = receiver.syntax().text();
         let without_dot = ..text.len() - TextSize::of('.');
         text.slice(without_dot).to_string()
@@ -267,12 +267,18 @@ fn get_receiver_text(receiver: &ast::Expr, receiver_is_ambiguous_float_literal:
     };
 
     // The receiver texts should be interpreted as-is, as they are expected to be
-    // normal Rust expressions. We escape '\' and '$' so they don't get treated as
-    // snippet-specific constructs.
-    //
-    // Note that we don't need to escape the other characters that can be escaped,
-    // because they wouldn't be treated as snippet-specific constructs without '$'.
-    text.replace('\\', "\\\\").replace('$', "\\$")
+    // normal Rust expressions.
+    escape_snippet_bits(&mut text);
+    text
+}
+
+/// Escapes `\` and `$` so that they don't get interpreted as snippet-specific constructs.
+///
+/// Note that we don't need to escape the other characters that can be escaped,
+/// because they wouldn't be treated as snippet-specific constructs without '$'.
+fn escape_snippet_bits(text: &mut String) {
+    stdx::replace(text, '\\', "\\\\");
+    stdx::replace(text, '$', "\\$");
 }
 
 fn include_references(initial_element: &ast::Expr) -> (ast::Expr, ast::Expr) {
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix/format_like.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix/format_like.rs
index cb242e4aa68..fd50fd4e8c5 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix/format_like.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/postfix/format_like.rs
@@ -17,13 +17,15 @@
 // image::https://user-images.githubusercontent.com/48062697/113020656-b560f500-917a-11eb-87de-02991f61beb8.gif[]
 
 use ide_db::{
-    syntax_helpers::format_string_exprs::{parse_format_exprs, with_placeholders},
+    syntax_helpers::format_string_exprs::{parse_format_exprs, with_placeholders, Arg},
     SnippetCap,
 };
 use syntax::{ast, AstToken};
 
 use crate::{
-    completions::postfix::build_postfix_snippet_builder, context::CompletionContext, Completions,
+    completions::postfix::{build_postfix_snippet_builder, escape_snippet_bits},
+    context::CompletionContext,
+    Completions,
 };
 
 /// Mapping ("postfix completion item" => "macro to use")
@@ -51,7 +53,15 @@ pub(crate) fn add_format_like_completions(
         None => return,
     };
 
-    if let Ok((out, exprs)) = parse_format_exprs(receiver_text.text()) {
+    if let Ok((mut out, mut exprs)) = parse_format_exprs(receiver_text.text()) {
+        // Escape any snippet bits in the out text and any of the exprs.
+        escape_snippet_bits(&mut out);
+        for arg in &mut exprs {
+            if let Arg::Ident(text) | Arg::Expr(text) = arg {
+                escape_snippet_bits(text)
+            }
+        }
+
         let exprs = with_placeholders(exprs);
         for (label, macro_name) in KINDS {
             let snippet = if exprs.is_empty() {
diff --git a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml
index b487b138fc0..071e1b47179 100644
--- a/src/tools/rust-analyzer/crates/ide-db/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-db/Cargo.toml
@@ -44,13 +44,10 @@ line-index.workspace = true
 
 [dev-dependencies]
 expect-test = "1.4.0"
-oorandom = "11.1.3"
-xshell.workspace = true
 
 # local deps
 test-utils.workspace = true
 test-fixture.workspace = true
-sourcegen.workspace = true
 
 [lints]
 workspace = true
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs b/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs
index 2b2df144d6d..017635d88e7 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/apply_change.rs
@@ -11,7 +11,7 @@ use profile::{memory_usage, Bytes};
 use rustc_hash::FxHashSet;
 use triomphe::Arc;
 
-use crate::{symbol_index::SymbolsDatabase, Change, RootDatabase};
+use crate::{symbol_index::SymbolsDatabase, ChangeWithProcMacros, RootDatabase};
 
 impl RootDatabase {
     pub fn request_cancellation(&mut self) {
@@ -20,7 +20,7 @@ impl RootDatabase {
         self.synthetic_write(Durability::LOW);
     }
 
-    pub fn apply_change(&mut self, change: Change) {
+    pub fn apply_change(&mut self, change: ChangeWithProcMacros) {
         let _p = tracing::span!(tracing::Level::INFO, "RootDatabase::apply_change").entered();
         self.request_cancellation();
         tracing::trace!("apply_change {:?}", change);
@@ -91,7 +91,6 @@ impl RootDatabase {
             crate::symbol_index::LocalRootsQuery
             crate::symbol_index::LibraryRootsQuery
             // HirDatabase
-            hir::db::InferQueryQuery
             hir::db::MirBodyQuery
             hir::db::BorrowckQuery
             hir::db::TyQuery
@@ -130,12 +129,10 @@ impl RootDatabase {
             hir::db::FnDefVarianceQuery
             hir::db::AdtVarianceQuery
             hir::db::AssociatedTyValueQuery
-            hir::db::TraitSolveQueryQuery
             hir::db::ProgramClausesForChalkEnvQuery
 
             // DefDatabase
             hir::db::FileItemTreeQuery
-            hir::db::CrateDefMapQueryQuery
             hir::db::BlockDefMapQuery
             hir::db::StructDataWithDiagnosticsQuery
             hir::db::UnionDataWithDiagnosticsQuery
@@ -165,7 +162,6 @@ impl RootDatabase {
             hir::db::FunctionVisibilityQuery
             hir::db::ConstVisibilityQuery
             hir::db::CrateSupportsNoStdQuery
-            hir::db::BlockItemTreeQueryQuery
             hir::db::ExternCrateDeclDataQuery
             hir::db::InternAnonymousConstQuery
             hir::db::InternExternCrateQuery
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs
index 3329909e9da..d50088e6cf1 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/generated/lints.rs
@@ -22,6 +22,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[
         description: r##"detects certain glob imports that require reporting an ambiguity error"##,
     },
     Lint { label: "ambiguous_glob_reexports", description: r##"ambiguous glob re-exports"## },
+    Lint {
+        label: "ambiguous_wide_pointer_comparisons",
+        description: r##"detects ambiguous wide pointer comparisons"##,
+    },
     Lint { label: "anonymous_parameters", description: r##"detects anonymous parameters"## },
     Lint { label: "arithmetic_overflow", description: r##"arithmetic operation overflows"## },
     Lint {
@@ -67,10 +71,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[
         description: r##"distinct impls distinguished only by the leak-check code"##,
     },
     Lint {
-        label: "coinductive_overlap_in_coherence",
-        description: r##"impls that are not considered to overlap may be considered to overlap in the future"##,
-    },
-    Lint {
         label: "conflicting_repr_hints",
         description: r##"conflicts between `#[repr(..)]` hints that were previously accepted and used in practice"##,
     },
@@ -86,10 +86,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[
         label: "const_item_mutation",
         description: r##"detects attempts to mutate a `const` item"##,
     },
-    Lint {
-        label: "const_patterns_without_partial_eq",
-        description: r##"constant in pattern does not implement `PartialEq`"##,
-    },
     Lint { label: "dead_code", description: r##"detect unused, unexported items"## },
     Lint { label: "deprecated", description: r##"detects use of deprecated items"## },
     Lint {
@@ -176,7 +172,7 @@ pub const DEFAULT_LINTS: &[Lint] = &[
     },
     Lint {
         label: "future_incompatible",
-        description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, const-patterns-without-partial-eq, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, implied-bounds-entailment, indirect-structural-match, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety"##,
+        description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, conflicting-repr-hints, const-evaluatable-unchecked, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, indirect-structural-match, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety, writes-through-immutable-pointer"##,
     },
     Lint {
         label: "fuzzy_provenance_casts",
@@ -191,14 +187,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[
         description: r##"ill-formed attribute inputs that were previously accepted and used in practice"##,
     },
     Lint {
-        label: "illegal_floating_point_literal_pattern",
-        description: r##"floating-point literals cannot be used in patterns"##,
-    },
-    Lint {
-        label: "implied_bounds_entailment",
-        description: r##"impl method assumes more implied bounds than its corresponding trait method"##,
-    },
-    Lint {
         label: "improper_ctypes",
         description: r##"proper use of libc types in foreign modules"##,
     },
@@ -372,6 +360,7 @@ pub const DEFAULT_LINTS: &[Lint] = &[
         label: "non_fmt_panics",
         description: r##"detect single-argument panic!() invocations in which the argument is not a format string"##,
     },
+    Lint { label: "non_local_definitions", description: r##"checks for non-local definitions"## },
     Lint {
         label: "non_shorthand_field_patterns",
         description: r##"using `Struct { x: x }` instead of `Struct { x }` in a pattern"##,
@@ -389,10 +378,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[
         description: r##"lint group for: non-camel-case-types, non-snake-case, non-upper-case-globals"##,
     },
     Lint {
-        label: "nontrivial_structural_match",
-        description: r##"constant used in pattern of non-structural-match type and the constant's initializer expression contains values of non-structural-match types"##,
-    },
-    Lint {
         label: "noop_method_call",
         description: r##"detects the use of well-known noop methods"##,
     },
@@ -483,6 +468,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[
         description: r##"detects the usage of trait methods which are ambiguous with traits added to the prelude in future editions"##,
     },
     Lint {
+        label: "rust_2024_compatibility",
+        description: r##"lint group for: static-mut-refs, unsafe-op-in-unsafe-fn"##,
+    },
+    Lint {
         label: "semicolon_in_expressions_from_macros",
         description: r##"trailing semicolon in macro body used as expression"##,
     },
@@ -503,6 +492,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[
         description: r##"stable features found in `#[feature]` directive"##,
     },
     Lint {
+        label: "static_mut_refs",
+        description: r##"shared references or mutable references of mutable static is discouraged"##,
+    },
+    Lint {
         label: "suspicious_double_ref_op",
         description: r##"suspicious call of trait method on `&&T`"##,
     },
@@ -576,6 +569,10 @@ pub const DEFAULT_LINTS: &[Lint] = &[
     },
     Lint { label: "uninhabited_static", description: r##"uninhabited static"## },
     Lint {
+        label: "unit_bindings",
+        description: r##"binding is useless because it has the unit `()` type"##,
+    },
+    Lint {
         label: "unknown_crate_types",
         description: r##"unknown crate type found in `#[crate_type]` directive"##,
     },
@@ -606,10 +603,7 @@ pub const DEFAULT_LINTS: &[Lint] = &[
         label: "unsafe_op_in_unsafe_fn",
         description: r##"unsafe operations in unsafe functions without an explicit unsafe block are deprecated"##,
     },
-    Lint {
-        label: "unstable_features",
-        description: r##"enabling unstable features (deprecated. do not use)"##,
-    },
+    Lint { label: "unstable_features", description: r##"enabling unstable features"## },
     Lint {
         label: "unstable_name_collisions",
         description: r##"detects name collision with an existing but unstable method"##,
@@ -695,10 +689,6 @@ pub const DEFAULT_LINTS: &[Lint] = &[
         label: "unused_results",
         description: r##"unused result of an expression in a statement"##,
     },
-    Lint {
-        label: "unused_tuple_struct_fields",
-        description: r##"detects tuple struct fields that are never read"##,
-    },
     Lint { label: "unused_unsafe", description: r##"unnecessary use of an `unsafe` block"## },
     Lint {
         label: "unused_variables",
@@ -732,13 +722,17 @@ pub const DEFAULT_LINTS: &[Lint] = &[
         label: "while_true",
         description: r##"suggest using `loop { }` instead of `while true { }`"##,
     },
+    Lint {
+        label: "writes_through_immutable_pointer",
+        description: r##"shared references are immutable, and pointers derived from them must not be written to"##,
+    },
 ];
 
 pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[
     LintGroup {
         lint: Lint {
             label: "future_incompatible",
-            description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, coinductive-overlap-in-coherence, conflicting-repr-hints, const-evaluatable-unchecked, const-patterns-without-partial-eq, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, illegal-floating-point-literal-pattern, implied-bounds-entailment, indirect-structural-match, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, nontrivial-structural-match, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, suspicious-auto-trait-impls, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety"##,
+            description: r##"lint group for: deref-into-dyn-supertrait, ambiguous-associated-items, ambiguous-glob-imports, byte-slice-in-packed-struct-with-derive, cenum-impl-drop-cast, coherence-leak-check, conflicting-repr-hints, const-evaluatable-unchecked, deprecated-cfg-attr-crate-type-name, elided-lifetimes-in-associated-constant, forbidden-lint-groups, ill-formed-attribute-input, indirect-structural-match, invalid-doc-attributes, invalid-type-param-default, late-bound-lifetime-arguments, legacy-derive-helpers, macro-expanded-macro-exports-accessed-by-absolute-paths, missing-fragment-specifier, order-dependent-trait-objects, patterns-in-fns-without-body, pointer-structural-match, proc-macro-back-compat, proc-macro-derive-resolution-fallback, pub-use-of-private-extern-crate, repr-transparent-external-private-fields, semicolon-in-expressions-from-macros, soft-unstable, uninhabited-static, unstable-name-collisions, unstable-syntax-pre-expansion, unsupported-calling-conventions, where-clauses-object-safety, writes-through-immutable-pointer"##,
         },
         children: &[
             "deref_into_dyn_supertrait",
@@ -747,16 +741,12 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[
             "byte_slice_in_packed_struct_with_derive",
             "cenum_impl_drop_cast",
             "coherence_leak_check",
-            "coinductive_overlap_in_coherence",
             "conflicting_repr_hints",
             "const_evaluatable_unchecked",
-            "const_patterns_without_partial_eq",
             "deprecated_cfg_attr_crate_type_name",
             "elided_lifetimes_in_associated_constant",
             "forbidden_lint_groups",
             "ill_formed_attribute_input",
-            "illegal_floating_point_literal_pattern",
-            "implied_bounds_entailment",
             "indirect_structural_match",
             "invalid_doc_attributes",
             "invalid_type_param_default",
@@ -764,7 +754,6 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[
             "legacy_derive_helpers",
             "macro_expanded_macro_exports_accessed_by_absolute_paths",
             "missing_fragment_specifier",
-            "nontrivial_structural_match",
             "order_dependent_trait_objects",
             "patterns_in_fns_without_body",
             "pointer_structural_match",
@@ -779,6 +768,7 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[
             "unstable_syntax_pre_expansion",
             "unsupported_calling_conventions",
             "where_clauses_object_safety",
+            "writes_through_immutable_pointer",
         ],
     },
     LintGroup {
@@ -838,6 +828,13 @@ pub const DEFAULT_LINT_GROUPS: &[LintGroup] = &[
     },
     LintGroup {
         lint: Lint {
+            label: "rust_2024_compatibility",
+            description: r##"lint group for: static-mut-refs, unsafe-op-in-unsafe-fn"##,
+        },
+        children: &["static_mut_refs", "unsafe_op_in_unsafe_fn"],
+    },
+    LintGroup {
+        lint: Lint {
             label: "unused",
             description: r##"lint group for: unused-imports, unused-variables, unused-assignments, dead-code, unused-mut, unreachable-code, unreachable-patterns, unused-must-use, unused-unsafe, path-statements, unused-attributes, unused-macros, unused-macro-rules, unused-allocation, unused-doc-comments, unused-extern-crates, unused-features, unused-labels, unused-parens, unused-braces, redundant-semicolons, map-unit-fn"##,
         },
@@ -1730,9 +1727,17 @@ The tracking issue for this feature is: [#110011]
         label: "async_fn_traits",
         description: r##"# `async_fn_traits`
 
-This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use.
+See Also: [`fn_traits`](../library-features/fn-traits.md)
 
-------------------------
+----
+
+The `async_fn_traits` feature allows for implementation of the [`AsyncFn*`] traits
+for creating custom closure-like types that return futures.
+
+[`AsyncFn*`]: ../../std/ops/trait.AsyncFn.html
+
+The main difference to the `Fn*` family of traits is that `AsyncFn` can return a future
+that borrows from itself (`FnOnce::Output` has no lifetime parameters, while `AsyncFn::CallFuture` does).
 "##,
     },
     Lint {
@@ -2376,17 +2381,6 @@ The tracking issue for this feature is: [#89653]
 "##,
     },
     Lint {
-        label: "cfg_target_abi",
-        description: r##"# `cfg_target_abi`
-
-The tracking issue for this feature is: [#80970]
-
-[#80970]: https://github.com/rust-lang/rust/issues/80970
-
-------------------------
-"##,
-    },
-    Lint {
         label: "cfg_target_compact",
         description: r##"# `cfg_target_compact`
 
@@ -3132,6 +3126,17 @@ This feature has no tracking issue, and is therefore likely internal to the comp
 "##,
     },
     Lint {
+        label: "const_intrinsic_copy",
+        description: r##"# `const_intrinsic_copy`
+
+The tracking issue for this feature is: [#80697]
+
+[#80697]: https://github.com/rust-lang/rust/issues/80697
+
+------------------------
+"##,
+    },
+    Lint {
         label: "const_intrinsic_forget",
         description: r##"# `const_intrinsic_forget`
 
@@ -3300,6 +3305,17 @@ The tracking issue for this feature is: [#110840]
 "##,
     },
     Lint {
+        label: "const_ops",
+        description: r##"# `const_ops`
+
+The tracking issue for this feature is: [#90080]
+
+[#90080]: https://github.com/rust-lang/rust/issues/90080
+
+------------------------
+"##,
+    },
+    Lint {
         label: "const_option",
         description: r##"# `const_option`
 
@@ -3443,6 +3459,17 @@ The tracking issue for this feature is: [#80384]
 "##,
     },
     Lint {
+        label: "const_refs_to_static",
+        description: r##"# `const_refs_to_static`
+
+The tracking issue for this feature is: [#119618]
+
+[#119618]: https://github.com/rust-lang/rust/issues/119618
+
+------------------------
+"##,
+    },
+    Lint {
         label: "const_replace",
         description: r##"# `const_replace`
 
@@ -4255,6 +4282,15 @@ The tracking issue for this feature is: [#27336]
 "##,
     },
     Lint {
+        label: "delayed_debug_assertions",
+        description: r##"# `delayed_debug_assertions`
+
+This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use.
+
+------------------------
+"##,
+    },
+    Lint {
         label: "deprecated_safe",
         description: r##"# `deprecated_safe`
 
@@ -4635,6 +4671,19 @@ The tracking issue for this feature is: [#57391]
 "##,
     },
     Lint {
+        label: "duration_constructors",
+        description: r##"# `duration_constructors`
+
+The tracking issue for this feature is: [#120301]
+
+[#120301]: https://github.com/rust-lang/rust/issues/120301
+
+------------------------
+
+Add the methods `from_mins`, `from_hours` and `from_days` to `Duration`.
+"##,
+    },
+    Lint {
         label: "duration_consts_float",
         description: r##"# `duration_consts_float`
 
@@ -4646,6 +4695,17 @@ The tracking issue for this feature is: [#72440]
 "##,
     },
     Lint {
+        label: "duration_units",
+        description: r##"# `duration_units`
+
+The tracking issue for this feature is: [#120301]
+
+[#120301]: https://github.com/rust-lang/rust/issues/120301
+
+------------------------
+"##,
+    },
+    Lint {
         label: "dyn_star",
         description: r##"# `dyn_star`
 
@@ -5654,13 +5714,62 @@ raw pointers in intra-doc links are unstable until it does.
 
 The tracking issue for this feature is: None.
 
-Intrinsics are never intended to be stable directly, but intrinsics are often
+Intrinsics are rarely intended to be stable directly, but are usually
 exported in some sort of stable manner. Prefer using the stable interfaces to
 the intrinsic directly when you can.
 
 ------------------------
 
 
+## Intrinsics with fallback logic
+
+Many intrinsics can be written in pure rust, albeit inefficiently or without supporting
+some features that only exist on some backends. Backends can simply not implement those
+intrinsics without causing any code miscompilations or failures to compile.
+All intrinsic fallback bodies are automatically made cross-crate inlineable (like `#[inline]`)
+by the codegen backend, but not the MIR inliner.
+
+```rust
+#![feature(rustc_attrs, effects)]
+#![allow(internal_features)]
+
+#[rustc_intrinsic]
+const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {}
+```
+
+Since these are just regular functions, it is perfectly ok to create the intrinsic twice:
+
+```rust
+#![feature(rustc_attrs, effects)]
+#![allow(internal_features)]
+
+#[rustc_intrinsic]
+const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {}
+
+mod foo {
+    #[rustc_intrinsic]
+    const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {
+        panic!("noisy const dealloc")
+    }
+}
+
+```
+
+The behaviour on backends that override the intrinsic is exactly the same. On other
+backends, the intrinsic behaviour depends on which implementation is called, just like
+with any regular function.
+
+## Intrinsics lowered to MIR instructions
+
+Various intrinsics have native MIR operations that they correspond to. Instead of requiring
+backends to implement both the intrinsic and the MIR operation, the `lower_intrinsics` pass
+will convert the calls to the MIR operation. Backends do not need to know about these intrinsics
+at all.
+
+## Intrinsics without fallback logic
+
+These must be implemented by all backends.
+
 These are imported as if they were FFI functions, with the special
 `rust-intrinsic` ABI. For example, if one was in a freestanding
 context, but wished to be able to `transmute` between types, and
@@ -5679,7 +5788,8 @@ extern "rust-intrinsic" {
 }
 ```
 
-As with any other FFI functions, these are always `unsafe` to call.
+As with any other FFI functions, these are by default always `unsafe` to call.
+You can add `#[rustc_safe_intrinsic]` to the intrinsic to make it safe to call.
 "##,
     },
     Lint {
@@ -5758,6 +5868,17 @@ The tracking issue for this feature is: [#101288]
 "##,
     },
     Lint {
+        label: "is_riscv_feature_detected",
+        description: r##"# `is_riscv_feature_detected`
+
+The tracking issue for this feature is: [#111192]
+
+[#111192]: https://github.com/rust-lang/rust/issues/111192
+
+------------------------
+"##,
+    },
+    Lint {
         label: "is_sorted",
         description: r##"# `is_sorted`
 
@@ -5936,6 +6057,17 @@ The tracking issue for this feature is: [#87053]
 "##,
     },
     Lint {
+        label: "lahfsahf_target_feature",
+        description: r##"# `lahfsahf_target_feature`
+
+The tracking issue for this feature is: [#44839]
+
+[#44839]: https://github.com/rust-lang/rust/issues/44839
+
+------------------------
+"##,
+    },
+    Lint {
         label: "lang_items",
         description: r##"# `lang_items`
 
@@ -6259,6 +6391,17 @@ The tracking issue for this feature is: [#82971]
 "##,
     },
     Lint {
+        label: "local_waker",
+        description: r##"# `local_waker`
+
+The tracking issue for this feature is: [#118959]
+
+[#118959]: https://github.com/rust-lang/rust/issues/118959
+
+------------------------
+"##,
+    },
+    Lint {
         label: "log_syntax",
         description: r##"# `log_syntax`
 
@@ -6325,6 +6468,17 @@ The tracking issue for this feature is: [#82766]
 "##,
     },
     Lint {
+        label: "mapped_lock_guards",
+        description: r##"# `mapped_lock_guards`
+
+The tracking issue for this feature is: [#117108]
+
+[#117108]: https://github.com/rust-lang/rust/issues/117108
+
+------------------------
+"##,
+    },
+    Lint {
         label: "marker_trait_attr",
         description: r##"# `marker_trait_attr`
 
@@ -6538,17 +6692,6 @@ The tracking issue for this feature is: [#83310]
 "##,
     },
     Lint {
-        label: "mutex_unlock",
-        description: r##"# `mutex_unlock`
-
-The tracking issue for this feature is: [#81872]
-
-[#81872]: https://github.com/rust-lang/rust/issues/81872
-
-------------------------
-"##,
-    },
-    Lint {
         label: "naked_functions",
         description: r##"# `naked_functions`
 
@@ -6976,6 +7119,17 @@ The tracking issue for this feature is: [#70086]
 "##,
     },
     Lint {
+        label: "os_str_display",
+        description: r##"# `os_str_display`
+
+The tracking issue for this feature is: [#120048]
+
+[#120048]: https://github.com/rust-lang/rust/issues/120048
+
+------------------------
+"##,
+    },
+    Lint {
         label: "os_str_slice",
         description: r##"# `os_str_slice`
 
@@ -7106,6 +7260,15 @@ The tracking issue for this feature is: [#27721]
 "##,
     },
     Lint {
+        label: "pattern_complexity",
+        description: r##"# `pattern_complexity`
+
+This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use.
+
+------------------------
+"##,
+    },
+    Lint {
         label: "peer_credentials_unix_socket",
         description: r##"# `peer_credentials_unix_socket`
 
@@ -7128,17 +7291,6 @@ The tracking issue for this feature is: [#86918]
 "##,
     },
     Lint {
-        label: "platform_intrinsics",
-        description: r##"# `platform_intrinsics`
-
-The tracking issue for this feature is: [#27731]
-
-[#27731]: https://github.com/rust-lang/rust/issues/27731
-
-------------------------
-"##,
-    },
-    Lint {
         label: "pointer_is_aligned",
         description: r##"# `pointer_is_aligned`
 
@@ -7184,7 +7336,9 @@ The tracking issue for this feature is: [#44839]
         label: "prelude_2024",
         description: r##"# `prelude_2024`
 
-This feature has no tracking issue, and is therefore likely internal to the compiler, not being intended for general use.
+The tracking issue for this feature is: [#121042]
+
+[#121042]: https://github.com/rust-lang/rust/issues/121042
 
 ------------------------
 "##,
@@ -7199,6 +7353,17 @@ This feature has no tracking issue, and is therefore likely internal to the comp
 "##,
     },
     Lint {
+        label: "prfchw_target_feature",
+        description: r##"# `prfchw_target_feature`
+
+The tracking issue for this feature is: [#44839]
+
+[#44839]: https://github.com/rust-lang/rust/issues/44839
+
+------------------------
+"##,
+    },
+    Lint {
         label: "print_internals",
         description: r##"# `print_internals`
 
@@ -7511,6 +7676,17 @@ This feature has no tracking issue, and is therefore likely internal to the comp
 "##,
     },
     Lint {
+        label: "reentrant_lock",
+        description: r##"# `reentrant_lock`
+
+The tracking issue for this feature is: [#121440]
+
+[#121440]: https://github.com/rust-lang/rust/issues/121440
+
+------------------------
+"##,
+    },
+    Lint {
         label: "register_tool",
         description: r##"# `register_tool`
 
@@ -8181,23 +8357,45 @@ This feature has no tracking issue, and is therefore likely internal to the comp
 "##,
     },
     Lint {
-        label: "stdio_makes_pipe",
-        description: r##"# `stdio_makes_pipe`
+        label: "stdarch_arm_feature_detection",
+        description: r##"# `stdarch_arm_feature_detection`
 
-The tracking issue for this feature is: [#98288]
+The tracking issue for this feature is: [#111190]
 
-[#98288]: https://github.com/rust-lang/rust/issues/98288
+[#111190]: https://github.com/rust-lang/rust/issues/111190
+
+------------------------
+"##,
+    },
+    Lint {
+        label: "stdarch_mips_feature_detection",
+        description: r##"# `stdarch_mips_feature_detection`
+
+The tracking issue for this feature is: [#111188]
+
+[#111188]: https://github.com/rust-lang/rust/issues/111188
+
+------------------------
+"##,
+    },
+    Lint {
+        label: "stdarch_powerpc_feature_detection",
+        description: r##"# `stdarch_powerpc_feature_detection`
+
+The tracking issue for this feature is: [#111191]
+
+[#111191]: https://github.com/rust-lang/rust/issues/111191
 
 ------------------------
 "##,
     },
     Lint {
-        label: "stdsimd",
-        description: r##"# `stdsimd`
+        label: "stdio_makes_pipe",
+        description: r##"# `stdio_makes_pipe`
 
-The tracking issue for this feature is: [#48556]
+The tracking issue for this feature is: [#98288]
 
-[#48556]: https://github.com/rust-lang/rust/issues/48556
+[#98288]: https://github.com/rust-lang/rust/issues/98288
 
 ------------------------
 "##,
@@ -8463,6 +8661,17 @@ The tracking issue for this feature is: [#44839]
 "##,
     },
     Lint {
+        label: "tcp_deferaccept",
+        description: r##"# `tcp_deferaccept`
+
+The tracking issue for this feature is: [#119639]
+
+[#119639]: https://github.com/rust-lang/rust/issues/119639
+
+------------------------
+"##,
+    },
+    Lint {
         label: "tcp_linger",
         description: r##"# `tcp_linger`
 
@@ -10151,7 +10360,7 @@ table:
     },
     Lint {
         label: "clippy::blocks_in_conditions",
-        description: r##"Checks for `if` conditions that use blocks containing an
+        description: r##"Checks for `if` and `match` conditions that use blocks containing an
 expression, statements or conditions that use closures with blocks."##,
     },
     Lint {
@@ -10455,6 +10664,12 @@ See [RFC0212](https://github.com/rust-lang/rfcs/blob/master/text/0212-restore-in
 with `#[rustfmt::skip]`."##,
     },
     Lint {
+        label: "clippy::deprecated_clippy_cfg_attr",
+        description: r##"Checks for `#[cfg_attr(feature = cargo-clippy, ...)]` and for
+`#[cfg(feature = cargo-clippy)]` and suggests to replace it with
+`#[cfg_attr(clippy, ...)]` or `#[cfg(clippy)]`."##,
+    },
+    Lint {
         label: "clippy::deprecated_semver",
         description: r##"Checks for `#[deprecated]` annotations with a `since`
 field that is not a valid semantic version. Also allows TBD to signal
@@ -10596,6 +10811,7 @@ eagerly (e.g. using `bool::then_some`)."##,
         description: r##"Checks for usage of if expressions with an `else if` branch,
 but without a final `else` branch."##,
     },
+    Lint { label: "clippy::empty_docs", description: r##"Detects documentation that is empty."## },
     Lint {
         label: "clippy::empty_drop",
         description: r##"Checks for empty `Drop` implementations."##,
@@ -11352,6 +11568,7 @@ cannot be represented as the underlying type without loss."##,
         description: r##"Checks for usage of `std::mem::size_of::<T>() * 8` when
 `T::BITS` is available."##,
     },
+    Lint { label: "clippy::manual_c_str_literals", description: r##""## },
     Lint {
         label: "clippy::manual_clamp",
         description: r##"Identifies good opportunities for a clamp function from std or core, and suggests using it."##,
@@ -11727,6 +11944,10 @@ rather than globally."##,
         description: r##"Warns for mistyped suffix in literals"##,
     },
     Lint {
+        label: "clippy::mixed_attributes_style",
+        description: r##"Checks that an item has only one kind of attributes."##,
+    },
+    Lint {
         label: "clippy::mixed_case_hex_literals",
         description: r##"Warns on hexadecimal literals with mixed-case letter
 digits."##,
@@ -11759,6 +11980,10 @@ one."##,
     },
     Lint { label: "clippy::multi_assignments", description: r##"Checks for nested assignments."## },
     Lint {
+        label: "clippy::multiple_bound_locations",
+        description: r##"Check if a generic is defined both in the bound predicate and in the `where` clause."##,
+    },
+    Lint {
         label: "clippy::multiple_crate_versions",
         description: r##"Checks to see if multiple versions of a crate are being
 used."##,
@@ -12331,8 +12556,8 @@ in `vec![elem; len]`"##,
     Lint {
         label: "clippy::read_line_without_trim",
         description: r##"Looks for calls to [`Stdin::read_line`] to read a line from the standard input
-into a string, then later attempting to parse this string into a type without first trimming it, which will
-always fail because the string has a trailing newline in it."##,
+into a string, then later attempting to use that string for an operation that will never
+work for strings with a trailing newline character in it (e.g. parsing into a `i32`)."##,
     },
     Lint {
         label: "clippy::read_zero_byte_vec",
@@ -12440,6 +12665,11 @@ do not change the type."##,
         description: r##"Warns about needless / redundant type annotations."##,
     },
     Lint {
+        label: "clippy::ref_as_ptr",
+        description: r##"Checks for casts of references to pointer using `as`
+and suggests `std::ptr::from_ref` and `std::ptr::from_mut` instead."##,
+    },
+    Lint {
         label: "clippy::ref_binding_to_reference",
         description: r##"Checks for `ref` bindings which create a reference to a reference."##,
     },
@@ -13092,6 +13322,11 @@ as returning a large `T` directly may be detrimental to performance."##,
 literals to float types and casts between raw pointers without changing type or constness."##,
     },
     Lint {
+        label: "clippy::unnecessary_clippy_cfg",
+        description: r##"Checks for `#[cfg_attr(clippy, allow(clippy::lint))]`
+and suggests to replace it with `#[allow(clippy::lint)]`."##,
+    },
+    Lint {
         label: "clippy::unnecessary_fallible_conversions",
         description: r##"Checks for calls to `TryInto::try_into` and `TryFrom::try_from` when their infallible counterparts
 could be used."##,
@@ -13115,6 +13350,10 @@ Specifically, this checks for `fold`s which could be replaced by `any`, `all`,
 `sum` or `product`."##,
     },
     Lint {
+        label: "clippy::unnecessary_get_then_check",
+        description: r##"Checks the usage of `.get().is_some()` or `.get().is_none()` on std map types."##,
+    },
+    Lint {
         label: "clippy::unnecessary_join",
         description: r##"Checks for usage of `.collect::<Vec<String>>().join()` on iterators."##,
     },
@@ -13825,7 +14064,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[
     LintGroup {
         lint: Lint {
             label: "clippy::pedantic",
-            description: r##"lint group for: clippy::bool_to_int_with_if, clippy::borrow_as_ptr, clippy::case_sensitive_file_extension_comparisons, clippy::cast_lossless, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_precision_loss, clippy::cast_ptr_alignment, clippy::cast_sign_loss, clippy::checked_conversions, clippy::cloned_instead_of_copied, clippy::copy_iterator, clippy::default_trait_access, clippy::doc_link_with_quotes, clippy::doc_markdown, clippy::empty_enum, clippy::enum_glob_use, clippy::expl_impl_clone_on_copy, clippy::explicit_deref_methods, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::flat_map_option, clippy::float_cmp, clippy::fn_params_excessive_bools, clippy::from_iter_instead_of_collect, clippy::if_not_else, clippy::ignored_unit_patterns, clippy::implicit_clone, clippy::implicit_hasher, clippy::inconsistent_struct_constructor, clippy::index_refutable_slice, clippy::inefficient_to_string, clippy::inline_always, clippy::into_iter_without_iter, clippy::invalid_upcast_comparisons, clippy::items_after_statements, clippy::iter_filter_is_ok, clippy::iter_filter_is_some, clippy::iter_not_returning_iterator, clippy::iter_without_into_iter, clippy::large_digit_groups, clippy::large_futures, clippy::large_stack_arrays, clippy::large_types_passed_by_value, clippy::linkedlist, clippy::macro_use_imports, clippy::manual_assert, clippy::manual_instant_elapsed, clippy::manual_is_variant_and, clippy::manual_let_else, clippy::manual_ok_or, clippy::manual_string_new, clippy::many_single_char_names, clippy::map_unwrap_or, clippy::match_bool, clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wild_err_arm, clippy::match_wildcard_for_single_variants, clippy::maybe_infinite_iter, clippy::mismatching_type_param_order, clippy::missing_errors_doc, clippy::missing_fields_in_debug, clippy::missing_panics_doc, clippy::module_name_repetitions, clippy::must_use_candidate, clippy::mut_mut, clippy::naive_bytecount, clippy::needless_bitwise_bool, clippy::needless_continue, clippy::needless_for_each, clippy::needless_pass_by_value, clippy::needless_raw_string_hashes, clippy::no_effect_underscore_binding, clippy::no_mangle_with_rust_abi, clippy::option_as_ref_cloned, clippy::option_option, clippy::ptr_as_ptr, clippy::ptr_cast_constness, clippy::pub_underscore_fields, clippy::range_minus_one, clippy::range_plus_one, clippy::redundant_closure_for_method_calls, clippy::redundant_else, clippy::ref_binding_to_reference, clippy::ref_option_ref, clippy::return_self_not_must_use, clippy::same_functions_in_if_condition, clippy::semicolon_if_nothing_returned, clippy::should_panic_without_expect, clippy::similar_names, clippy::single_match_else, clippy::stable_sort_primitive, clippy::str_split_at_newline, clippy::string_add_assign, clippy::struct_excessive_bools, clippy::struct_field_names, clippy::too_many_lines, clippy::transmute_ptr_to_ptr, clippy::trivially_copy_pass_by_ref, clippy::unchecked_duration_subtraction, clippy::unicode_not_nfc, clippy::uninlined_format_args, clippy::unnecessary_box_returns, clippy::unnecessary_join, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::unreadable_literal, clippy::unsafe_derive_deserialize, clippy::unused_async, clippy::unused_self, clippy::used_underscore_binding, clippy::verbose_bit_mask, clippy::wildcard_imports, clippy::zero_sized_map_values"##,
+            description: r##"lint group for: clippy::bool_to_int_with_if, clippy::borrow_as_ptr, clippy::case_sensitive_file_extension_comparisons, clippy::cast_lossless, clippy::cast_possible_truncation, clippy::cast_possible_wrap, clippy::cast_precision_loss, clippy::cast_ptr_alignment, clippy::cast_sign_loss, clippy::checked_conversions, clippy::cloned_instead_of_copied, clippy::copy_iterator, clippy::default_trait_access, clippy::doc_link_with_quotes, clippy::doc_markdown, clippy::empty_enum, clippy::enum_glob_use, clippy::expl_impl_clone_on_copy, clippy::explicit_deref_methods, clippy::explicit_into_iter_loop, clippy::explicit_iter_loop, clippy::filter_map_next, clippy::flat_map_option, clippy::float_cmp, clippy::fn_params_excessive_bools, clippy::from_iter_instead_of_collect, clippy::if_not_else, clippy::ignored_unit_patterns, clippy::implicit_clone, clippy::implicit_hasher, clippy::inconsistent_struct_constructor, clippy::index_refutable_slice, clippy::inefficient_to_string, clippy::inline_always, clippy::into_iter_without_iter, clippy::invalid_upcast_comparisons, clippy::items_after_statements, clippy::iter_filter_is_ok, clippy::iter_filter_is_some, clippy::iter_not_returning_iterator, clippy::iter_without_into_iter, clippy::large_digit_groups, clippy::large_futures, clippy::large_stack_arrays, clippy::large_types_passed_by_value, clippy::linkedlist, clippy::macro_use_imports, clippy::manual_assert, clippy::manual_c_str_literals, clippy::manual_instant_elapsed, clippy::manual_is_variant_and, clippy::manual_let_else, clippy::manual_ok_or, clippy::manual_string_new, clippy::many_single_char_names, clippy::map_unwrap_or, clippy::match_bool, clippy::match_on_vec_items, clippy::match_same_arms, clippy::match_wild_err_arm, clippy::match_wildcard_for_single_variants, clippy::maybe_infinite_iter, clippy::mismatching_type_param_order, clippy::missing_errors_doc, clippy::missing_fields_in_debug, clippy::missing_panics_doc, clippy::module_name_repetitions, clippy::must_use_candidate, clippy::mut_mut, clippy::naive_bytecount, clippy::needless_bitwise_bool, clippy::needless_continue, clippy::needless_for_each, clippy::needless_pass_by_value, clippy::needless_raw_string_hashes, clippy::no_effect_underscore_binding, clippy::no_mangle_with_rust_abi, clippy::option_as_ref_cloned, clippy::option_option, clippy::ptr_as_ptr, clippy::ptr_cast_constness, clippy::pub_underscore_fields, clippy::range_minus_one, clippy::range_plus_one, clippy::redundant_closure_for_method_calls, clippy::redundant_else, clippy::ref_as_ptr, clippy::ref_binding_to_reference, clippy::ref_option_ref, clippy::return_self_not_must_use, clippy::same_functions_in_if_condition, clippy::semicolon_if_nothing_returned, clippy::should_panic_without_expect, clippy::similar_names, clippy::single_match_else, clippy::stable_sort_primitive, clippy::str_split_at_newline, clippy::string_add_assign, clippy::struct_excessive_bools, clippy::struct_field_names, clippy::too_many_lines, clippy::transmute_ptr_to_ptr, clippy::trivially_copy_pass_by_ref, clippy::unchecked_duration_subtraction, clippy::unicode_not_nfc, clippy::uninlined_format_args, clippy::unnecessary_box_returns, clippy::unnecessary_join, clippy::unnecessary_wraps, clippy::unnested_or_patterns, clippy::unreadable_literal, clippy::unsafe_derive_deserialize, clippy::unused_async, clippy::unused_self, clippy::used_underscore_binding, clippy::verbose_bit_mask, clippy::wildcard_imports, clippy::zero_sized_map_values"##,
         },
         children: &[
             "clippy::bool_to_int_with_if",
@@ -13876,6 +14115,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[
             "clippy::linkedlist",
             "clippy::macro_use_imports",
             "clippy::manual_assert",
+            "clippy::manual_c_str_literals",
             "clippy::manual_instant_elapsed",
             "clippy::manual_is_variant_and",
             "clippy::manual_let_else",
@@ -13913,6 +14153,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[
             "clippy::range_plus_one",
             "clippy::redundant_closure_for_method_calls",
             "clippy::redundant_else",
+            "clippy::ref_as_ptr",
             "clippy::ref_binding_to_reference",
             "clippy::ref_option_ref",
             "clippy::return_self_not_must_use",
@@ -14257,7 +14498,7 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[
     LintGroup {
         lint: Lint {
             label: "clippy::suspicious",
-            description: r##"lint group for: clippy::almost_complete_range, clippy::arc_with_non_send_sync, clippy::await_holding_invalid_type, clippy::await_holding_lock, clippy::await_holding_refcell_ref, clippy::blanket_clippy_restriction_lints, clippy::cast_abs_to_unsigned, clippy::cast_enum_constructor, clippy::cast_enum_truncation, clippy::cast_nan_to_int, clippy::cast_slice_from_raw_parts, clippy::crate_in_macro_def, clippy::drop_non_drop, clippy::duplicate_mod, clippy::empty_loop, clippy::float_equality_without_abs, clippy::forget_non_drop, clippy::four_forward_slashes, clippy::from_raw_with_void_ptr, clippy::incompatible_msrv, clippy::ineffective_open_options, clippy::iter_out_of_bounds, clippy::join_absolute_paths, clippy::let_underscore_future, clippy::lines_filter_map_ok, clippy::maybe_misused_cfg, clippy::misnamed_getters, clippy::misrefactored_assign_op, clippy::multi_assignments, clippy::mut_range_bound, clippy::mutable_key_type, clippy::no_effect_replace, clippy::non_canonical_clone_impl, clippy::non_canonical_partial_ord_impl, clippy::octal_escapes, clippy::path_ends_with_ext, clippy::permissions_set_readonly_false, clippy::print_in_format_impl, clippy::rc_clone_in_vec_init, clippy::repeat_vec_with_capacity, clippy::single_range_in_vec_init, clippy::size_of_ref, clippy::suspicious_arithmetic_impl, clippy::suspicious_assignment_formatting, clippy::suspicious_command_arg_space, clippy::suspicious_doc_comments, clippy::suspicious_else_formatting, clippy::suspicious_map, clippy::suspicious_op_assign_impl, clippy::suspicious_open_options, clippy::suspicious_to_owned, clippy::suspicious_unary_op_formatting, clippy::swap_ptr_to_ref, clippy::test_attr_in_doctest, clippy::type_id_on_box, clippy::unconditional_recursion, clippy::unnecessary_result_map_or_else"##,
+            description: r##"lint group for: clippy::almost_complete_range, clippy::arc_with_non_send_sync, clippy::await_holding_invalid_type, clippy::await_holding_lock, clippy::await_holding_refcell_ref, clippy::blanket_clippy_restriction_lints, clippy::cast_abs_to_unsigned, clippy::cast_enum_constructor, clippy::cast_enum_truncation, clippy::cast_nan_to_int, clippy::cast_slice_from_raw_parts, clippy::crate_in_macro_def, clippy::deprecated_clippy_cfg_attr, clippy::drop_non_drop, clippy::duplicate_mod, clippy::empty_docs, clippy::empty_loop, clippy::float_equality_without_abs, clippy::forget_non_drop, clippy::four_forward_slashes, clippy::from_raw_with_void_ptr, clippy::incompatible_msrv, clippy::ineffective_open_options, clippy::iter_out_of_bounds, clippy::join_absolute_paths, clippy::let_underscore_future, clippy::lines_filter_map_ok, clippy::maybe_misused_cfg, clippy::misnamed_getters, clippy::misrefactored_assign_op, clippy::mixed_attributes_style, clippy::multi_assignments, clippy::multiple_bound_locations, clippy::mut_range_bound, clippy::mutable_key_type, clippy::no_effect_replace, clippy::non_canonical_clone_impl, clippy::non_canonical_partial_ord_impl, clippy::octal_escapes, clippy::path_ends_with_ext, clippy::permissions_set_readonly_false, clippy::print_in_format_impl, clippy::rc_clone_in_vec_init, clippy::repeat_vec_with_capacity, clippy::single_range_in_vec_init, clippy::size_of_ref, clippy::suspicious_arithmetic_impl, clippy::suspicious_assignment_formatting, clippy::suspicious_command_arg_space, clippy::suspicious_doc_comments, clippy::suspicious_else_formatting, clippy::suspicious_map, clippy::suspicious_op_assign_impl, clippy::suspicious_open_options, clippy::suspicious_to_owned, clippy::suspicious_unary_op_formatting, clippy::swap_ptr_to_ref, clippy::test_attr_in_doctest, clippy::type_id_on_box, clippy::unconditional_recursion, clippy::unnecessary_clippy_cfg, clippy::unnecessary_get_then_check, clippy::unnecessary_result_map_or_else"##,
         },
         children: &[
             "clippy::almost_complete_range",
@@ -14272,8 +14513,10 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[
             "clippy::cast_nan_to_int",
             "clippy::cast_slice_from_raw_parts",
             "clippy::crate_in_macro_def",
+            "clippy::deprecated_clippy_cfg_attr",
             "clippy::drop_non_drop",
             "clippy::duplicate_mod",
+            "clippy::empty_docs",
             "clippy::empty_loop",
             "clippy::float_equality_without_abs",
             "clippy::forget_non_drop",
@@ -14288,7 +14531,9 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[
             "clippy::maybe_misused_cfg",
             "clippy::misnamed_getters",
             "clippy::misrefactored_assign_op",
+            "clippy::mixed_attributes_style",
             "clippy::multi_assignments",
+            "clippy::multiple_bound_locations",
             "clippy::mut_range_bound",
             "clippy::mutable_key_type",
             "clippy::no_effect_replace",
@@ -14316,6 +14561,8 @@ pub const CLIPPY_LINT_GROUPS: &[LintGroup] = &[
             "clippy::test_attr_in_doctest",
             "clippy::type_id_on_box",
             "clippy::unconditional_recursion",
+            "clippy::unnecessary_clippy_cfg",
+            "clippy::unnecessary_get_then_check",
             "clippy::unnecessary_result_map_or_else",
         ],
     },
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/helpers.rs b/src/tools/rust-analyzer/crates/ide-db/src/helpers.rs
index 0b5ad7060e0..4ac8a7c4c4a 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/helpers.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/helpers.rs
@@ -64,7 +64,7 @@ pub fn visit_file_defs(
     cb: &mut dyn FnMut(Definition),
 ) {
     let db = sema.db;
-    let module = match sema.to_module_def(file_id) {
+    let module = match sema.file_to_module_def(file_id) {
         Some(it) => it,
         None => return,
     };
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
index 3e6cb7476bb..be08b37bac3 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
@@ -44,7 +44,7 @@ pub mod syntax_helpers {
     pub use parser::LexedStr;
 }
 
-pub use hir::Change;
+pub use hir::ChangeWithProcMacros;
 
 use std::{fmt, mem::ManuallyDrop};
 
@@ -216,7 +216,6 @@ impl RootDatabase {
 
             // DefDatabase
             hir_db::FileItemTreeQuery
-            hir_db::CrateDefMapQueryQuery
             hir_db::BlockDefMapQuery
             hir_db::StructDataWithDiagnosticsQuery
             hir_db::UnionDataWithDiagnosticsQuery
@@ -248,7 +247,6 @@ impl RootDatabase {
             hir_db::CrateSupportsNoStdQuery
 
             // HirDatabase
-            hir_db::InferQueryQuery
             hir_db::MirBodyQuery
             hir_db::BorrowckQuery
             hir_db::TyQuery
@@ -287,7 +285,6 @@ impl RootDatabase {
             hir_db::FnDefVarianceQuery
             hir_db::AdtVarianceQuery
             hir_db::AssociatedTyValueQuery
-            hir_db::TraitSolveQueryQuery
             hir_db::ProgramClausesForChalkEnvQuery
 
             // SymbolsDatabase
@@ -412,9 +409,3 @@ impl SnippetCap {
         }
     }
 }
-
-#[cfg(test)]
-mod tests {
-    mod line_index;
-    mod sourcegen_lints;
-}
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs b/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs
index ef15f585fa2..024e8f6ae39 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/prime_caches.rs
@@ -129,7 +129,7 @@ pub fn parallel_prime_caches(
                 crates_currently_indexing.insert(crate_id, crate_name);
             }
             ParallelPrimeCacheWorkerProgress::EndCrate { crate_id } => {
-                crates_currently_indexing.remove(&crate_id);
+                crates_currently_indexing.swap_remove(&crate_id);
                 crates_to_prime.mark_done(crate_id);
                 crates_done += 1;
             }
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string_exprs.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string_exprs.rs
index 49594aee9f3..8ab5a6ede3b 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string_exprs.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/format_string_exprs.rs
@@ -11,15 +11,12 @@ pub enum Arg {
     Expr(String),
 }
 
-/**
- Add placeholders like `$1` and `$2` in place of [`Arg::Placeholder`],
- and unwraps the [`Arg::Ident`] and [`Arg::Expr`] enums.
- ```rust
- # use ide_db::syntax_helpers::format_string_exprs::*;
- assert_eq!(with_placeholders(vec![Arg::Ident("ident".to_owned()), Arg::Placeholder, Arg::Expr("expr + 2".to_owned())]), vec!["ident".to_owned(), "$1".to_owned(), "expr + 2".to_owned()])
- ```
-*/
-
+/// Add placeholders like `$1` and `$2` in place of [`Arg::Placeholder`],
+/// and unwraps the [`Arg::Ident`] and [`Arg::Expr`] enums.
+/// ```rust
+/// # use ide_db::syntax_helpers::format_string_exprs::*;
+/// assert_eq!(with_placeholders(vec![Arg::Ident("ident".to_owned()), Arg::Placeholder, Arg::Expr("expr + 2".to_owned())]), vec!["ident".to_owned(), "$1".to_owned(), "expr + 2".to_owned()])
+/// ```
 pub fn with_placeholders(args: Vec<Arg>) -> Vec<String> {
     let mut placeholder_id = 1;
     args.into_iter()
@@ -34,18 +31,15 @@ pub fn with_placeholders(args: Vec<Arg>) -> Vec<String> {
         .collect()
 }
 
-/**
- Parser for a format-like string. It is more allowing in terms of string contents,
- as we expect variable placeholders to be filled with expressions.
-
- Built for completions and assists, and escapes `\` and `$` in output.
- (See the comments on `get_receiver_text()` for detail.)
- Splits a format string that may contain expressions
- like
- ```rust
- assert_eq!(parse("{ident} {} {expr + 42} ").unwrap(), ("{} {} {}", vec![Arg::Ident("ident"), Arg::Placeholder, Arg::Expr("expr + 42")]));
- ```
-*/
+/// Parser for a format-like string. It is more allowing in terms of string contents,
+/// as we expect variable placeholders to be filled with expressions.
+///
+/// Splits a format string that may contain expressions
+/// like
+/// ```rust
+/// # use ide_db::syntax_helpers::format_string_exprs::*;
+/// assert_eq!(parse_format_exprs("{ident} {} {expr + 42} ").unwrap(), ("{ident} {} {} ".to_owned(), vec![Arg::Placeholder, Arg::Expr("expr + 42".to_owned())]));
+/// ```
 pub fn parse_format_exprs(input: &str) -> Result<(String, Vec<Arg>), ()> {
     #[derive(Debug, Clone, Copy, PartialEq)]
     enum State {
@@ -79,9 +73,6 @@ pub fn parse_format_exprs(input: &str) -> Result<(String, Vec<Arg>), ()> {
                 state = State::MaybeIncorrect;
             }
             (State::NotArg, _) => {
-                if matches!(chr, '\\' | '$') {
-                    output.push('\\');
-                }
                 output.push(chr);
             }
             (State::MaybeIncorrect, '}') => {
@@ -110,9 +101,6 @@ pub fn parse_format_exprs(input: &str) -> Result<(String, Vec<Arg>), ()> {
                 state = State::FormatOpts;
             }
             (State::MaybeArg, _) => {
-                if matches!(chr, '\\' | '$') {
-                    current_expr.push('\\');
-                }
                 current_expr.push(chr);
 
                 // While Rust uses the unicode sets of XID_start and XID_continue for Identifiers
@@ -172,9 +160,6 @@ pub fn parse_format_exprs(input: &str) -> Result<(String, Vec<Arg>), ()> {
                     state = State::Expr;
                 }
 
-                if matches!(chr, '\\' | '$') {
-                    current_expr.push('\\');
-                }
                 current_expr.push(chr);
             }
             (State::FormatOpts, '}') => {
@@ -182,9 +167,6 @@ pub fn parse_format_exprs(input: &str) -> Result<(String, Vec<Arg>), ()> {
                 state = State::NotArg;
             }
             (State::FormatOpts, _) => {
-                if matches!(chr, '\\' | '$') {
-                    output.push('\\');
-                }
                 output.push(chr);
             }
         }
@@ -217,15 +199,15 @@ mod tests {
     fn format_str_parser() {
         let test_vector = &[
             ("no expressions", expect![["no expressions"]]),
-            (r"no expressions with \$0$1", expect![r"no expressions with \\\$0\$1"]),
+            (r"no expressions with \$0$1", expect![r"no expressions with \$0$1"]),
             ("{expr} is {2 + 2}", expect![["{expr} is {}; 2 + 2"]]),
             ("{expr:?}", expect![["{expr:?}"]]),
-            ("{expr:1$}", expect![[r"{expr:1\$}"]]),
-            ("{:1$}", expect![[r"{:1\$}; $1"]]),
-            ("{:>padding$}", expect![[r"{:>padding\$}; $1"]]),
+            ("{expr:1$}", expect![[r"{expr:1$}"]]),
+            ("{:1$}", expect![[r"{:1$}; $1"]]),
+            ("{:>padding$}", expect![[r"{:>padding$}; $1"]]),
             ("{}, {}, {0}", expect![[r"{}, {}, {0}; $1, $2"]]),
             ("{}, {}, {0:b}", expect![[r"{}, {}, {0:b}; $1, $2"]]),
-            ("{$0}", expect![[r"{}; \$0"]]),
+            ("{$0}", expect![[r"{}; $0"]]),
             ("{malformed", expect![["-"]]),
             ("malformed}", expect![["-"]]),
             ("{{correct", expect![["{{correct"]]),
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs
index 0b0fc669352..97b6d4a572a 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/syntax_helpers/insert_whitespace_into_node.rs
@@ -20,7 +20,7 @@ pub fn insert_ws_into(syn: SyntaxNode) -> SyntaxNode {
     let after = Position::after;
 
     let do_indent = |pos: fn(_) -> Position, token: &SyntaxToken, indent| {
-        (pos(token.clone()), make::tokens::whitespace(&" ".repeat(2 * indent)))
+        (pos(token.clone()), make::tokens::whitespace(&" ".repeat(4 * indent)))
     };
     let do_ws = |pos: fn(_) -> Position, token: &SyntaxToken| {
         (pos(token.clone()), make::tokens::single_space())
@@ -41,7 +41,7 @@ pub fn insert_ws_into(syn: SyntaxNode) -> SyntaxNode {
                 if indent > 0 {
                     mods.push((
                         Position::after(node.clone()),
-                        make::tokens::whitespace(&" ".repeat(2 * indent)),
+                        make::tokens::whitespace(&" ".repeat(4 * indent)),
                     ));
                 }
                 if node.parent().is_some() {
@@ -91,10 +91,7 @@ pub fn insert_ws_into(syn: SyntaxNode) -> SyntaxNode {
             LIFETIME_IDENT if is_next(is_text, true) => {
                 mods.push(do_ws(after, tok));
             }
-            MUT_KW if is_next(|it| it == SELF_KW, false) => {
-                mods.push(do_ws(after, tok));
-            }
-            AS_KW | DYN_KW | IMPL_KW | CONST_KW => {
+            AS_KW | DYN_KW | IMPL_KW | CONST_KW | MUT_KW => {
                 mods.push(do_ws(after, tok));
             }
             T![;] if is_next(|it| it != R_CURLY, true) => {
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/tests/line_index.rs b/src/tools/rust-analyzer/crates/ide-db/src/tests/line_index.rs
deleted file mode 100644
index 6b49bb2631c..00000000000
--- a/src/tools/rust-analyzer/crates/ide-db/src/tests/line_index.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-use line_index::{LineCol, LineIndex, WideEncoding};
-use test_utils::skip_slow_tests;
-
-#[test]
-fn test_every_chars() {
-    if skip_slow_tests() {
-        return;
-    }
-
-    let text: String = {
-        let mut chars: Vec<char> = ((0 as char)..char::MAX).collect(); // Neat!
-        chars.extend("\n".repeat(chars.len() / 16).chars());
-        let mut rng = oorandom::Rand32::new(stdx::rand::seed());
-        stdx::rand::shuffle(&mut chars, |i| rng.rand_range(0..i as u32) as usize);
-        chars.into_iter().collect()
-    };
-    assert!(text.contains('💩')); // Sanity check.
-
-    let line_index = LineIndex::new(&text);
-
-    let mut lin_col = LineCol { line: 0, col: 0 };
-    let mut col_utf16 = 0;
-    let mut col_utf32 = 0;
-    for (offset, c) in text.char_indices() {
-        let got_offset = line_index.offset(lin_col).unwrap();
-        assert_eq!(usize::from(got_offset), offset);
-
-        let got_lin_col = line_index.line_col(got_offset);
-        assert_eq!(got_lin_col, lin_col);
-
-        for (enc, col) in [(WideEncoding::Utf16, col_utf16), (WideEncoding::Utf32, col_utf32)] {
-            let wide_lin_col = line_index.to_wide(enc, lin_col).unwrap();
-            let got_lin_col = line_index.to_utf8(enc, wide_lin_col).unwrap();
-            assert_eq!(got_lin_col, lin_col);
-            assert_eq!(wide_lin_col.col, col)
-        }
-
-        if c == '\n' {
-            lin_col.line += 1;
-            lin_col.col = 0;
-            col_utf16 = 0;
-            col_utf32 = 0;
-        } else {
-            lin_col.col += c.len_utf8() as u32;
-            col_utf16 += c.len_utf16() as u32;
-            col_utf32 += 1;
-        }
-    }
-}
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml b/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml
index 69768041389..8ccea99e9e1 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/Cargo.toml
@@ -20,7 +20,6 @@ tracing.workspace = true
 once_cell = "1.17.0"
 
 # local deps
-profile.workspace = true
 stdx.workspace = true
 syntax.workspace = true
 text-edit.workspace = true
@@ -34,10 +33,6 @@ expect-test = "1.4.0"
 # local deps
 test-utils.workspace = true
 test-fixture.workspace = true
-sourcegen.workspace = true
-
-[features]
-in-rust-tree = []
 
 [lints]
 workspace = true
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs
index 09daefd084d..f92ba576d3a 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_fields.rs
@@ -200,7 +200,7 @@ fn get_default_constructor(
         }
     }
 
-    let krate = ctx.sema.to_module_def(d.file.original_file(ctx.sema.db))?.krate();
+    let krate = ctx.sema.file_to_module_def(d.file.original_file(ctx.sema.db))?.krate();
     let module = krate.root_module();
 
     // Look for a ::new() associated function
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs
index 8596f5792e0..67daa172b27 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/missing_match_arms.rs
@@ -597,21 +597,19 @@ fn bang(never: !) {
 
     #[test]
     fn unknown_type() {
-        cov_mark::check_count!(validate_match_bailed_out, 1);
-
-        check_diagnostics(
+        check_diagnostics_no_bails(
             r#"
 enum Option<T> { Some(T), None }
 
 #[allow(unused)]
 fn main() {
     // `Never` is deliberately not defined so that it's an uninferred type.
+    // We ignore these to avoid triggering bugs in the analysis.
     match Option::<Never>::None {
         None => (),
         Some(never) => match never {},
     }
     match Option::<Never>::None {
-        //^^^^^^^^^^^^^^^^^^^^^ error: missing match arm: `None` not covered
         Option::Some(_never) => {},
     }
 }
@@ -620,6 +618,18 @@ fn main() {
     }
 
     #[test]
+    fn arity_mismatch_issue_16746() {
+        check_diagnostics_with_disabled(
+            r#"
+fn main() {
+    let (a, ) = (0, 0);
+}
+"#,
+            &["E0308"],
+        );
+    }
+
+    #[test]
     fn tuple_of_bools_with_ellipsis_at_end_missing_arm() {
         check_diagnostics_no_bails(
             r#"
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs
index 47844876dc5..f68e6982385 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/handlers/remove_unnecessary_else.rs
@@ -30,6 +30,7 @@ pub(crate) fn remove_unnecessary_else(
         "remove unnecessary else block",
         display_range,
     )
+    .experimental()
     .with_fixes(fixes(ctx, d))
 }
 
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
index 9f4368b04e7..0df6f0e0373 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/lib.rs
@@ -227,6 +227,7 @@ pub struct DiagnosticsConfig {
     pub disable_experimental: bool,
     pub disabled: FxHashSet<String>,
     pub expr_fill_default: ExprFillDefaultMode,
+    pub style_lints: bool,
     // FIXME: We may want to include a whole `AssistConfig` here
     pub insert_use: InsertUseConfig,
     pub prefer_no_std: bool,
@@ -245,6 +246,7 @@ impl DiagnosticsConfig {
             disable_experimental: Default::default(),
             disabled: Default::default(),
             expr_fill_default: Default::default(),
+            style_lints: true,
             insert_use: InsertUseConfig {
                 granularity: ImportGranularity::Preserve,
                 enforce_granularity: false,
@@ -299,7 +301,7 @@ pub fn diagnostics(
     let mut res = Vec::new();
 
     // [#34344] Only take first 128 errors to prevent slowing down editor/ide, the number 128 is chosen arbitrarily.
-    res.extend(parse.errors().iter().take(128).map(|err| {
+    res.extend(parse.errors().into_iter().take(128).map(|err| {
         Diagnostic::new(
             DiagnosticCode::RustcHardError("syntax-error"),
             format!("Syntax Error: {err}"),
@@ -315,7 +317,7 @@ pub fn diagnostics(
         handlers::json_is_not_rust::json_in_items(&sema, &mut res, file_id, &node, config);
     }
 
-    let module = sema.to_module_def(file_id);
+    let module = sema.file_to_module_def(file_id);
 
     let ctx = DiagnosticsContext { config, sema, resolve };
     if module.is_none() {
@@ -324,7 +326,7 @@ pub fn diagnostics(
 
     let mut diags = Vec::new();
     if let Some(m) = module {
-        m.diagnostics(db, &mut diags);
+        m.diagnostics(db, &mut diags, config.style_lints);
     }
 
     for diag in diags {
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs b/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs
index 901ceffbb26..dcaa2120892 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests.rs
@@ -1,6 +1,4 @@
 #![allow(clippy::print_stderr)]
-#[cfg(not(feature = "in-rust-tree"))]
-mod sourcegen;
 
 use ide_db::{
     assists::AssistResolveStrategy, base_db::SourceDatabaseExt, LineIndexDatabase, RootDatabase,
diff --git a/src/tools/rust-analyzer/crates/ide/Cargo.toml b/src/tools/rust-analyzer/crates/ide/Cargo.toml
index bb06d614450..aca7d613e11 100644
--- a/src/tools/rust-analyzer/crates/ide/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/ide/Cargo.toml
@@ -17,11 +17,11 @@ arrayvec.workspace = true
 either.workspace = true
 itertools.workspace = true
 tracing.workspace = true
-oorandom = "11.1.3"
-pulldown-cmark-to-cmark = "10.0.4"
-pulldown-cmark = { version = "0.9.1", default-features = false }
-url = "2.3.1"
-dot = "0.1.4"
+oorandom.workspace = true
+pulldown-cmark-to-cmark.workspace = true
+pulldown-cmark.workspace = true
+url.workspace = true
+dot.workspace = true
 smallvec.workspace = true
 triomphe.workspace = true
 nohash-hasher.workspace = true
@@ -52,7 +52,7 @@ test-utils.workspace = true
 test-fixture.workspace = true
 
 [features]
-in-rust-tree = ["ide-assists/in-rust-tree", "ide-diagnostics/in-rust-tree"]
+in-rust-tree = []
 
 [lints]
 workspace = true
diff --git a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs
index 17c701ad035..4b0961cbbeb 100644
--- a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs
@@ -189,7 +189,7 @@ fn _format(
     let &crate_id = db.relevant_crates(file_id).iter().next()?;
     let edition = db.crate_graph()[crate_id].edition;
 
-    let mut cmd = std::process::Command::new(toolchain::rustfmt());
+    let mut cmd = std::process::Command::new(toolchain::Tool::Rustfmt.path());
     cmd.arg("--edition");
     cmd.arg(edition.to_string());
 
@@ -308,8 +308,8 @@ f$0oo!();
             expect![[r#"
                 foo!
                 fn some_thing() -> u32 {
-                  let a = 0;
-                  a+10
+                    let a = 0;
+                    a+10
                 }"#]],
         );
     }
@@ -342,13 +342,13 @@ fn main() {
             expect![[r#"
                 match_ast!
                 {
-                  if let Some(it) = ast::TraitDef::cast(container.clone()){}
-                  else if let Some(it) = ast::ImplDef::cast(container.clone()){}
-                  else {
-                    {
-                      continue
+                    if let Some(it) = ast::TraitDef::cast(container.clone()){}
+                    else if let Some(it) = ast::ImplDef::cast(container.clone()){}
+                    else {
+                        {
+                            continue
+                        }
                     }
-                  }
                 }"#]],
         );
     }
@@ -397,12 +397,12 @@ fn main() {
             expect![[r#"
                 foo!
                 {
-                  macro_rules! bar {
-                    () => {
-                      42
+                    macro_rules! bar {
+                        () => {
+                            42
+                        }
                     }
-                  }
-                  42
+                    42
                 }"#]],
         );
     }
@@ -482,16 +482,16 @@ struct Foo {}
             expect![[r#"
                 Clone
                 impl < >$crate::clone::Clone for Foo< >where {
-                  fn clone(&self) -> Self {
-                    match self {
-                      Foo{}
-                       => Foo{}
-                      ,
+                    fn clone(&self) -> Self {
+                        match self {
+                            Foo{}
+                             => Foo{}
+                            ,
 
-                      }
-                  }
+                            }
+                    }
 
-                  }"#]],
+                    }"#]],
         );
     }
 
@@ -534,16 +534,16 @@ struct Foo {}
             expect![[r#"
                 Clone
                 impl < >$crate::clone::Clone for Foo< >where {
-                  fn clone(&self) -> Self {
-                    match self {
-                      Foo{}
-                       => Foo{}
-                      ,
+                    fn clone(&self) -> Self {
+                        match self {
+                            Foo{}
+                             => Foo{}
+                            ,
 
-                      }
-                  }
+                            }
+                    }
 
-                  }"#]],
+                    }"#]],
         );
     }
 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
index 41148db6146..1bda15255dc 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
@@ -537,6 +537,24 @@ fn bar() {
     }
 
     #[test]
+    fn goto_definition_works_for_consts_inside_range_pattern() {
+        check(
+            r#"
+//- /lib.rs
+const A: u32 = 0;
+    //^
+
+fn bar(v: u32) {
+    match v {
+        0..=$0A => {}
+        _ => {}
+    }
+}
+"#,
+        );
+    }
+
+    #[test]
     fn goto_def_for_use_alias() {
         check(
             r#"
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs
index 4a7350feb38..8f4c629b581 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs
@@ -32,6 +32,7 @@ pub struct HoverConfig {
     pub documentation: bool,
     pub keywords: bool,
     pub format: HoverDocFormat,
+    pub max_trait_assoc_items_count: Option<usize>,
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
index 563e78253a8..d1d039534d5 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/render.rs
@@ -406,7 +406,12 @@ pub(super) fn definition(
     config: &HoverConfig,
 ) -> Markup {
     let mod_path = definition_mod_path(db, &def);
-    let label = def.label(db);
+    let label = match def {
+        Definition::Trait(trait_) => {
+            trait_.display_limited(db, config.max_trait_assoc_items_count).to_string()
+        }
+        _ => def.label(db),
+    };
     let docs = def.docs(db, famous_defs);
     let value = (|| match def {
         Definition::Variant(it) => {
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
index b9ae89cc18d..c3cd6513dc6 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
@@ -17,6 +17,7 @@ const HOVER_BASE_CONFIG: HoverConfig = HoverConfig {
     documentation: true,
     format: HoverDocFormat::Markdown,
     keywords: true,
+    max_trait_assoc_items_count: None,
 };
 
 fn check_hover_no_result(ra_fixture: &str) {
@@ -48,6 +49,28 @@ fn check(ra_fixture: &str, expect: Expect) {
     expect.assert_eq(&actual)
 }
 
+#[track_caller]
+fn check_assoc_count(count: usize, ra_fixture: &str, expect: Expect) {
+    let (analysis, position) = fixture::position(ra_fixture);
+    let hover = analysis
+        .hover(
+            &HoverConfig {
+                links_in_hover: true,
+                max_trait_assoc_items_count: Some(count),
+                ..HOVER_BASE_CONFIG
+            },
+            FileRange { file_id: position.file_id, range: TextRange::empty(position.offset) },
+        )
+        .unwrap()
+        .unwrap();
+
+    let content = analysis.db.file_text(position.file_id);
+    let hovered_element = &content[hover.range];
+
+    let actual = format!("*{hovered_element}*\n{}\n", hover.info.markup);
+    expect.assert_eq(&actual)
+}
+
 fn check_hover_no_links(ra_fixture: &str, expect: Expect) {
     let (analysis, position) = fixture::position(ra_fixture);
     let hover = analysis
@@ -2672,26 +2695,26 @@ fn foo() -> impl Foo {}
 fn main() { let s$0t = foo(); }
 "#,
         expect![[r#"
-                [
-                    GoToType(
-                        [
-                            HoverGotoTypeData {
-                                mod_path: "test::Foo",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 0..12,
-                                    focus_range: 6..9,
-                                    name: "Foo",
-                                    kind: Trait,
-                                    description: "trait Foo",
-                                },
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "test::Foo",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 0..12,
+                                focus_range: 6..9,
+                                name: "Foo",
+                                kind: Trait,
+                                description: "trait Foo",
                             },
-                        ],
-                    ),
-                ]
-            "#]],
+                        },
+                    ],
+                ),
+            ]
+        "#]],
     );
 }
 
@@ -2706,39 +2729,39 @@ fn foo() -> impl Foo<S> {}
 fn main() { let s$0t = foo(); }
 "#,
         expect![[r#"
-                [
-                    GoToType(
-                        [
-                            HoverGotoTypeData {
-                                mod_path: "test::Foo",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 0..15,
-                                    focus_range: 6..9,
-                                    name: "Foo",
-                                    kind: Trait,
-                                    description: "trait Foo<T>",
-                                },
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "test::Foo",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 0..15,
+                                focus_range: 6..9,
+                                name: "Foo",
+                                kind: Trait,
+                                description: "trait Foo<T>",
                             },
-                            HoverGotoTypeData {
-                                mod_path: "test::S",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 16..25,
-                                    focus_range: 23..24,
-                                    name: "S",
-                                    kind: Struct,
-                                    description: "struct S",
-                                },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "test::S",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 16..25,
+                                focus_range: 23..24,
+                                name: "S",
+                                kind: Struct,
+                                description: "struct S",
                             },
-                        ],
-                    ),
-                ]
-            "#]],
+                        },
+                    ],
+                ),
+            ]
+        "#]],
     );
 }
 
@@ -2873,26 +2896,26 @@ trait Foo {}
 fn foo(ar$0g: &impl Foo) {}
 "#,
         expect![[r#"
-                [
-                    GoToType(
-                        [
-                            HoverGotoTypeData {
-                                mod_path: "test::Foo",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 0..12,
-                                    focus_range: 6..9,
-                                    name: "Foo",
-                                    kind: Trait,
-                                    description: "trait Foo",
-                                },
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "test::Foo",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 0..12,
+                                focus_range: 6..9,
+                                name: "Foo",
+                                kind: Trait,
+                                description: "trait Foo",
                             },
-                        ],
-                    ),
-                ]
-            "#]],
+                        },
+                    ],
+                ),
+            ]
+        "#]],
     );
 }
 
@@ -3020,39 +3043,39 @@ struct S {}
 fn foo(ar$0g: &impl Foo<S>) {}
 "#,
         expect![[r#"
-                [
-                    GoToType(
-                        [
-                            HoverGotoTypeData {
-                                mod_path: "test::Foo",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 0..15,
-                                    focus_range: 6..9,
-                                    name: "Foo",
-                                    kind: Trait,
-                                    description: "trait Foo<T>",
-                                },
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "test::Foo",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 0..15,
+                                focus_range: 6..9,
+                                name: "Foo",
+                                kind: Trait,
+                                description: "trait Foo<T>",
                             },
-                            HoverGotoTypeData {
-                                mod_path: "test::S",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 16..27,
-                                    focus_range: 23..24,
-                                    name: "S",
-                                    kind: Struct,
-                                    description: "struct S {}",
-                                },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "test::S",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 16..27,
+                                focus_range: 23..24,
+                                name: "S",
+                                kind: Struct,
+                                description: "struct S {}",
                             },
-                        ],
-                    ),
-                ]
-            "#]],
+                        },
+                    ],
+                ),
+            ]
+        "#]],
     );
 }
 
@@ -3070,39 +3093,39 @@ fn foo() -> B<dyn Foo> {}
 fn main() { let s$0t = foo(); }
 "#,
         expect![[r#"
-                [
-                    GoToType(
-                        [
-                            HoverGotoTypeData {
-                                mod_path: "test::B",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 42..55,
-                                    focus_range: 49..50,
-                                    name: "B",
-                                    kind: Struct,
-                                    description: "struct B<T> {}",
-                                },
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "test::B",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 42..55,
+                                focus_range: 49..50,
+                                name: "B",
+                                kind: Struct,
+                                description: "struct B<T> {}",
                             },
-                            HoverGotoTypeData {
-                                mod_path: "test::Foo",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 0..12,
-                                    focus_range: 6..9,
-                                    name: "Foo",
-                                    kind: Trait,
-                                    description: "trait Foo",
-                                },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "test::Foo",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 0..12,
+                                focus_range: 6..9,
+                                name: "Foo",
+                                kind: Trait,
+                                description: "trait Foo",
                             },
-                        ],
-                    ),
-                ]
-            "#]],
+                        },
+                    ],
+                ),
+            ]
+        "#]],
     );
 }
 
@@ -3114,26 +3137,26 @@ trait Foo {}
 fn foo(ar$0g: &dyn Foo) {}
 "#,
         expect![[r#"
-                [
-                    GoToType(
-                        [
-                            HoverGotoTypeData {
-                                mod_path: "test::Foo",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 0..12,
-                                    focus_range: 6..9,
-                                    name: "Foo",
-                                    kind: Trait,
-                                    description: "trait Foo",
-                                },
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "test::Foo",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 0..12,
+                                focus_range: 6..9,
+                                name: "Foo",
+                                kind: Trait,
+                                description: "trait Foo",
                             },
-                        ],
-                    ),
-                ]
-            "#]],
+                        },
+                    ],
+                ),
+            ]
+        "#]],
     );
 }
 
@@ -3146,39 +3169,39 @@ struct S {}
 fn foo(ar$0g: &dyn Foo<S>) {}
 "#,
         expect![[r#"
-                [
-                    GoToType(
-                        [
-                            HoverGotoTypeData {
-                                mod_path: "test::Foo",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 0..15,
-                                    focus_range: 6..9,
-                                    name: "Foo",
-                                    kind: Trait,
-                                    description: "trait Foo<T>",
-                                },
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "test::Foo",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 0..15,
+                                focus_range: 6..9,
+                                name: "Foo",
+                                kind: Trait,
+                                description: "trait Foo<T>",
                             },
-                            HoverGotoTypeData {
-                                mod_path: "test::S",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 16..27,
-                                    focus_range: 23..24,
-                                    name: "S",
-                                    kind: Struct,
-                                    description: "struct S {}",
-                                },
+                        },
+                        HoverGotoTypeData {
+                            mod_path: "test::S",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 16..27,
+                                focus_range: 23..24,
+                                name: "S",
+                                kind: Struct,
+                                description: "struct S {}",
                             },
-                        ],
-                    ),
-                ]
-            "#]],
+                        },
+                    ],
+                ),
+            ]
+        "#]],
     );
 }
 
@@ -3275,26 +3298,26 @@ fn test() -> impl Foo { S {} }
 fn main() { let s$0t = test().get(); }
 "#,
         expect![[r#"
-                [
-                    GoToType(
-                        [
-                            HoverGotoTypeData {
-                                mod_path: "test::Foo",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 0..62,
-                                    focus_range: 6..9,
-                                    name: "Foo",
-                                    kind: Trait,
-                                    description: "trait Foo",
-                                },
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "test::Foo",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 0..62,
+                                focus_range: 6..9,
+                                name: "Foo",
+                                kind: Trait,
+                                description: "trait Foo",
                             },
-                        ],
-                    ),
-                ]
-            "#]],
+                        },
+                    ],
+                ),
+            ]
+        "#]],
     );
 }
 
@@ -3340,26 +3363,26 @@ trait Foo {}
 fn foo<T: Foo>(t: T$0){}
 "#,
         expect![[r#"
-                [
-                    GoToType(
-                        [
-                            HoverGotoTypeData {
-                                mod_path: "test::Foo",
-                                nav: NavigationTarget {
-                                    file_id: FileId(
-                                        0,
-                                    ),
-                                    full_range: 0..12,
-                                    focus_range: 6..9,
-                                    name: "Foo",
-                                    kind: Trait,
-                                    description: "trait Foo",
-                                },
+            [
+                GoToType(
+                    [
+                        HoverGotoTypeData {
+                            mod_path: "test::Foo",
+                            nav: NavigationTarget {
+                                file_id: FileId(
+                                    0,
+                                ),
+                                full_range: 0..12,
+                                focus_range: 6..9,
+                                name: "Foo",
+                                kind: Trait,
+                                description: "trait Foo",
                             },
-                        ],
-                    ),
-                ]
-            "#]],
+                        },
+                    ],
+                ),
+            ]
+        "#]],
     );
 }
 
@@ -5434,13 +5457,62 @@ fn hover_feature() {
 
             The tracking issue for this feature is: None.
 
-            Intrinsics are never intended to be stable directly, but intrinsics are often
+            Intrinsics are rarely intended to be stable directly, but are usually
             exported in some sort of stable manner. Prefer using the stable interfaces to
             the intrinsic directly when you can.
 
             ------------------------
 
 
+            ## Intrinsics with fallback logic
+
+            Many intrinsics can be written in pure rust, albeit inefficiently or without supporting
+            some features that only exist on some backends. Backends can simply not implement those
+            intrinsics without causing any code miscompilations or failures to compile.
+            All intrinsic fallback bodies are automatically made cross-crate inlineable (like `#[inline]`)
+            by the codegen backend, but not the MIR inliner.
+
+            ```rust
+            #![feature(rustc_attrs, effects)]
+            #![allow(internal_features)]
+
+            #[rustc_intrinsic]
+            const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {}
+            ```
+
+            Since these are just regular functions, it is perfectly ok to create the intrinsic twice:
+
+            ```rust
+            #![feature(rustc_attrs, effects)]
+            #![allow(internal_features)]
+
+            #[rustc_intrinsic]
+            const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {}
+
+            mod foo {
+                #[rustc_intrinsic]
+                const unsafe fn const_deallocate(_ptr: *mut u8, _size: usize, _align: usize) {
+                    panic!("noisy const dealloc")
+                }
+            }
+
+            ```
+
+            The behaviour on backends that override the intrinsic is exactly the same. On other
+            backends, the intrinsic behaviour depends on which implementation is called, just like
+            with any regular function.
+
+            ## Intrinsics lowered to MIR instructions
+
+            Various intrinsics have native MIR operations that they correspond to. Instead of requiring
+            backends to implement both the intrinsic and the MIR operation, the `lower_intrinsics` pass
+            will convert the calls to the MIR operation. Backends do not need to know about these intrinsics
+            at all.
+
+            ## Intrinsics without fallback logic
+
+            These must be implemented by all backends.
+
             These are imported as if they were FFI functions, with the special
             `rust-intrinsic` ABI. For example, if one was in a freestanding
             context, but wished to be able to `transmute` between types, and
@@ -5459,7 +5531,8 @@ fn hover_feature() {
             }
             ```
 
-            As with any other FFI functions, these are always `unsafe` to call.
+            As with any other FFI functions, these are by default always `unsafe` to call.
+            You can add `#[rustc_safe_intrinsic]` to the intrinsic to make it safe to call.
 
         "#]],
     )
@@ -6278,6 +6351,151 @@ impl T for () {
 }
 
 #[test]
+fn hover_trait_show_assoc_items() {
+    check_assoc_count(
+        0,
+        r#"
+trait T {}
+impl T$0 for () {}
+"#,
+        expect![[r#"
+            *T*
+
+            ```rust
+            test
+            ```
+
+            ```rust
+            trait T {}
+            ```
+        "#]],
+    );
+
+    check_assoc_count(
+        1,
+        r#"
+trait T {}
+impl T$0 for () {}
+"#,
+        expect![[r#"
+            *T*
+
+            ```rust
+            test
+            ```
+
+            ```rust
+            trait T {}
+            ```
+        "#]],
+    );
+
+    check_assoc_count(
+        0,
+        r#"
+trait T {
+    fn func() {}
+    const FLAG: i32 = 34;
+    type Bar;
+}
+impl T$0 for () {}
+"#,
+        expect![[r#"
+            *T*
+
+            ```rust
+            test
+            ```
+
+            ```rust
+            trait T { /* … */ }
+            ```
+        "#]],
+    );
+
+    check_assoc_count(
+        2,
+        r#"
+trait T {
+    fn func() {}
+    const FLAG: i32 = 34;
+    type Bar;
+}
+impl T$0 for () {}
+"#,
+        expect![[r#"
+            *T*
+
+            ```rust
+            test
+            ```
+
+            ```rust
+            trait T {
+                fn func();
+                const FLAG: i32;
+                /* … */
+            }
+            ```
+        "#]],
+    );
+
+    check_assoc_count(
+        3,
+        r#"
+trait T {
+    fn func() {}
+    const FLAG: i32 = 34;
+    type Bar;
+}
+impl T$0 for () {}
+"#,
+        expect![[r#"
+            *T*
+
+            ```rust
+            test
+            ```
+
+            ```rust
+            trait T {
+                fn func();
+                const FLAG: i32;
+                type Bar;
+            }
+            ```
+        "#]],
+    );
+
+    check_assoc_count(
+        4,
+        r#"
+trait T {
+    fn func() {}
+    const FLAG: i32 = 34;
+    type Bar;
+}
+impl T$0 for () {}
+"#,
+        expect![[r#"
+            *T*
+
+            ```rust
+            test
+            ```
+
+            ```rust
+            trait T {
+                fn func();
+                const FLAG: i32;
+                type Bar;
+            }
+            ```
+        "#]],
+    );
+}
+
+#[test]
 fn hover_ranged_macro_call() {
     check_hover_range(
         r#"
@@ -6366,8 +6584,8 @@ fn main() { $0V; }
 
             ```rust
             pub const V: i8 = {
-              let e = 123;
-              f(e)
+                let e = 123;
+                f(e)
             }
             ```
         "#]],
@@ -6393,7 +6611,7 @@ fn main() { $0V; }
 
             ```rust
             pub static V: i8 = {
-              let e = 123;
+                let e = 123;
             }
             ```
         "#]],
diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs
index a076c7ca9fa..59a7df14fd5 100644
--- a/src/tools/rust-analyzer/crates/ide/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs
@@ -50,6 +50,7 @@ mod static_index;
 mod status;
 mod syntax_highlighting;
 mod syntax_tree;
+mod test_explorer;
 mod typing;
 mod view_crate_graph;
 mod view_hir;
@@ -61,7 +62,7 @@ use std::ffi::OsStr;
 
 use cfg::CfgOptions;
 use fetch_crates::CrateInfo;
-use hir::Change;
+use hir::ChangeWithProcMacros;
 use ide_db::{
     base_db::{
         salsa::{self, ParallelDatabase},
@@ -108,6 +109,7 @@ pub use crate::{
         tags::{Highlight, HlMod, HlMods, HlOperator, HlPunct, HlTag},
         HighlightConfig, HlRange,
     },
+    test_explorer::{TestItem, TestItemKind},
 };
 pub use hir::Semantics;
 pub use ide_assists::{
@@ -184,7 +186,7 @@ impl AnalysisHost {
 
     /// Applies changes to the current state of the world. If there are
     /// outstanding snapshots, they will be canceled.
-    pub fn apply_change(&mut self, change: Change) {
+    pub fn apply_change(&mut self, change: ChangeWithProcMacros) {
         self.db.apply_change(change);
     }
 
@@ -239,7 +241,7 @@ impl Analysis {
         file_set.insert(file_id, VfsPath::new_virtual_path("/main.rs".to_owned()));
         let source_root = SourceRoot::new_local(file_set);
 
-        let mut change = Change::new();
+        let mut change = ChangeWithProcMacros::new();
         change.set_roots(vec![source_root]);
         let mut crate_graph = CrateGraph::default();
         // FIXME: cfg options
@@ -340,6 +342,18 @@ impl Analysis {
         self.with_db(|db| view_item_tree::view_item_tree(db, file_id))
     }
 
+    pub fn discover_test_roots(&self) -> Cancellable<Vec<TestItem>> {
+        self.with_db(test_explorer::discover_test_roots)
+    }
+
+    pub fn discover_tests_in_crate_by_test_id(&self, crate_id: &str) -> Cancellable<Vec<TestItem>> {
+        self.with_db(|db| test_explorer::discover_tests_in_crate_by_test_id(db, crate_id))
+    }
+
+    pub fn discover_tests_in_crate(&self, crate_id: CrateId) -> Cancellable<Vec<TestItem>> {
+        self.with_db(|db| test_explorer::discover_tests_in_crate(db, crate_id))
+    }
+
     /// Renders the crate graph to GraphViz "dot" syntax.
     pub fn view_crate_graph(&self, full: bool) -> Cancellable<Result<String, String>> {
         self.with_db(|db| view_crate_graph::view_crate_graph(db, full))
diff --git a/src/tools/rust-analyzer/crates/ide/src/parent_module.rs b/src/tools/rust-analyzer/crates/ide/src/parent_module.rs
index f67aea2d5b9..ce7a6779e27 100644
--- a/src/tools/rust-analyzer/crates/ide/src/parent_module.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/parent_module.rs
@@ -48,7 +48,7 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<Na
             .flat_map(|module| NavigationTarget::from_module_to_decl(db, module))
             .collect(),
         None => sema
-            .to_module_defs(position.file_id)
+            .file_to_module_defs(position.file_id)
             .flat_map(|module| NavigationTarget::from_module_to_decl(db, module))
             .collect(),
     }
diff --git a/src/tools/rust-analyzer/crates/ide/src/rename.rs b/src/tools/rust-analyzer/crates/ide/src/rename.rs
index f78153df38b..8c2ae327c7f 100644
--- a/src/tools/rust-analyzer/crates/ide/src/rename.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/rename.rs
@@ -156,7 +156,7 @@ pub(crate) fn will_rename_file(
     new_name_stem: &str,
 ) -> Option<SourceChange> {
     let sema = Semantics::new(db);
-    let module = sema.to_module_def(file_id)?;
+    let module = sema.file_to_module_def(file_id)?;
     let def = Definition::Module(module);
     let mut change = if is_raw_identifier(new_name_stem) {
         def.rename(&sema, &SmolStr::from_iter(["r#", new_name_stem])).ok()?
diff --git a/src/tools/rust-analyzer/crates/ide/src/runnables.rs b/src/tools/rust-analyzer/crates/ide/src/runnables.rs
index ae107a96040..5fe46444ff4 100644
--- a/src/tools/rust-analyzer/crates/ide/src/runnables.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/runnables.rs
@@ -178,7 +178,7 @@ pub(crate) fn runnables(db: &RootDatabase, file_id: FileId) -> Vec<Runnable> {
         }
     });
 
-    sema.to_module_defs(file_id)
+    sema.file_to_module_defs(file_id)
         .map(|it| runnable_mod_outline_definition(&sema, it))
         .for_each(|it| add_opt(it, None));
 
diff --git a/src/tools/rust-analyzer/crates/ide/src/static_index.rs b/src/tools/rust-analyzer/crates/ide/src/static_index.rs
index 2929a7522e5..fe063081f79 100644
--- a/src/tools/rust-analyzer/crates/ide/src/static_index.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/static_index.rs
@@ -166,6 +166,7 @@ impl StaticIndex<'_> {
             documentation: true,
             keywords: true,
             format: crate::HoverDocFormat::Markdown,
+            max_trait_assoc_items_count: None,
         };
         let tokens = tokens.filter(|token| {
             matches!(
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
index dfcbaf54d4f..d2bd3bab14e 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
@@ -223,7 +223,7 @@ fn traverse(
     krate: hir::Crate,
     range_to_highlight: TextRange,
 ) {
-    let is_unlinked = sema.to_module_def(file_id).is_none();
+    let is_unlinked = sema.file_to_module_def(file_id).is_none();
     let mut bindings_shadow_count: FxHashMap<Name, u32> = FxHashMap::default();
 
     enum AttrOrDerive {
diff --git a/src/tools/rust-analyzer/crates/ide/src/test_explorer.rs b/src/tools/rust-analyzer/crates/ide/src/test_explorer.rs
new file mode 100644
index 00000000000..2e741021ea8
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide/src/test_explorer.rs
@@ -0,0 +1,135 @@
+//! Discovers tests
+
+use hir::{Crate, Module, ModuleDef, Semantics};
+use ide_db::{
+    base_db::{CrateGraph, CrateId, FileId, SourceDatabase},
+    RootDatabase,
+};
+use syntax::TextRange;
+
+use crate::{navigation_target::ToNav, runnables::runnable_fn, Runnable, TryToNav};
+
+#[derive(Debug)]
+pub enum TestItemKind {
+    Crate,
+    Module,
+    Function,
+}
+
+#[derive(Debug)]
+pub struct TestItem {
+    pub id: String,
+    pub kind: TestItemKind,
+    pub label: String,
+    pub parent: Option<String>,
+    pub file: Option<FileId>,
+    pub text_range: Option<TextRange>,
+    pub runnable: Option<Runnable>,
+}
+
+pub(crate) fn discover_test_roots(db: &RootDatabase) -> Vec<TestItem> {
+    let crate_graph = db.crate_graph();
+    crate_graph
+        .iter()
+        .filter(|&id| crate_graph[id].origin.is_local())
+        .filter_map(|id| Some(crate_graph[id].display_name.as_ref()?.to_string()))
+        .map(|id| TestItem {
+            kind: TestItemKind::Crate,
+            label: id.clone(),
+            id,
+            parent: None,
+            file: None,
+            text_range: None,
+            runnable: None,
+        })
+        .collect()
+}
+
+fn find_crate_by_id(crate_graph: &CrateGraph, crate_id: &str) -> Option<CrateId> {
+    // here, we use display_name as the crate id. This is not super ideal, but it works since we
+    // only show tests for the local crates.
+    crate_graph.iter().find(|&id| {
+        crate_graph[id].origin.is_local()
+            && crate_graph[id].display_name.as_ref().is_some_and(|x| x.to_string() == crate_id)
+    })
+}
+
+fn discover_tests_in_module(db: &RootDatabase, module: Module, prefix_id: String) -> Vec<TestItem> {
+    let sema = Semantics::new(db);
+
+    let mut r = vec![];
+    for c in module.children(db) {
+        let module_name =
+            c.name(db).as_ref().and_then(|n| n.as_str()).unwrap_or("[mod without name]").to_owned();
+        let module_id = format!("{prefix_id}::{module_name}");
+        let module_children = discover_tests_in_module(db, c, module_id.clone());
+        if !module_children.is_empty() {
+            let nav = c.to_nav(db).call_site;
+            r.push(TestItem {
+                id: module_id,
+                kind: TestItemKind::Module,
+                label: module_name,
+                parent: Some(prefix_id.clone()),
+                file: Some(nav.file_id),
+                text_range: Some(nav.focus_or_full_range()),
+                runnable: None,
+            });
+            r.extend(module_children);
+        }
+    }
+    for def in module.declarations(db) {
+        let ModuleDef::Function(f) = def else {
+            continue;
+        };
+        if !f.is_test(db) {
+            continue;
+        }
+        let nav = f.try_to_nav(db).map(|r| r.call_site);
+        let fn_name = f.name(db).as_str().unwrap_or("[function without name]").to_owned();
+        r.push(TestItem {
+            id: format!("{prefix_id}::{fn_name}"),
+            kind: TestItemKind::Function,
+            label: fn_name,
+            parent: Some(prefix_id.clone()),
+            file: nav.as_ref().map(|n| n.file_id),
+            text_range: nav.as_ref().map(|n| n.focus_or_full_range()),
+            runnable: runnable_fn(&sema, f),
+        });
+    }
+    r
+}
+
+pub(crate) fn discover_tests_in_crate_by_test_id(
+    db: &RootDatabase,
+    crate_test_id: &str,
+) -> Vec<TestItem> {
+    let crate_graph = db.crate_graph();
+    let Some(crate_id) = find_crate_by_id(&crate_graph, crate_test_id) else {
+        return vec![];
+    };
+    discover_tests_in_crate(db, crate_id)
+}
+
+pub(crate) fn discover_tests_in_crate(db: &RootDatabase, crate_id: CrateId) -> Vec<TestItem> {
+    let crate_graph = db.crate_graph();
+    if !crate_graph[crate_id].origin.is_local() {
+        return vec![];
+    }
+    let Some(crate_test_id) = &crate_graph[crate_id].display_name else {
+        return vec![];
+    };
+    let crate_test_id = crate_test_id.to_string();
+    let crate_id: Crate = crate_id.into();
+    let module = crate_id.root_module();
+    let mut r = vec![TestItem {
+        id: crate_test_id.clone(),
+        kind: TestItemKind::Crate,
+        label: crate_test_id.clone(),
+        parent: None,
+        file: None,
+        text_range: None,
+        runnable: None,
+    }];
+    r.extend(discover_tests_in_module(db, module, crate_test_id));
+    r
+}
diff --git a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
index 2b5f515c3ad..a1c089520da 100644
--- a/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/load-cargo/src/lib.rs
@@ -10,8 +10,8 @@ use hir_expand::proc_macro::{
     ProcMacros,
 };
 use ide_db::{
-    base_db::{CrateGraph, Env, SourceRoot},
-    prime_caches, Change, FxHashMap, RootDatabase,
+    base_db::{CrateGraph, Env, SourceRoot, SourceRootId},
+    prime_caches, ChangeWithProcMacros, FxHashMap, RootDatabase,
 };
 use itertools::Itertools;
 use proc_macro_api::{MacroDylib, ProcMacroServer};
@@ -231,7 +231,7 @@ impl ProjectFolders {
             res.load.push(entry);
 
             if root.is_local {
-                local_filesets.push(fsc.len());
+                local_filesets.push(fsc.len() as u64);
             }
             fsc.add_file_set(file_set_roots)
         }
@@ -246,7 +246,7 @@ impl ProjectFolders {
 #[derive(Default, Debug)]
 pub struct SourceRootConfig {
     pub fsc: FileSetConfig,
-    pub local_filesets: Vec<usize>,
+    pub local_filesets: Vec<u64>,
 }
 
 impl SourceRootConfig {
@@ -256,7 +256,7 @@ impl SourceRootConfig {
             .into_iter()
             .enumerate()
             .map(|(idx, file_set)| {
-                let is_local = self.local_filesets.contains(&idx);
+                let is_local = self.local_filesets.contains(&(idx as u64));
                 if is_local {
                     SourceRoot::new_local(file_set)
                 } else {
@@ -265,6 +265,31 @@ impl SourceRootConfig {
             })
             .collect()
     }
+
+    /// Maps local source roots to their parent source roots by bytewise comparing of root paths .
+    /// If a `SourceRoot` doesn't have a parent and is local then it is not contained in this mapping but it can be asserted that it is a root `SourceRoot`.
+    pub fn source_root_parent_map(&self) -> FxHashMap<SourceRootId, SourceRootId> {
+        let roots = self.fsc.roots();
+        let mut map = FxHashMap::<SourceRootId, SourceRootId>::default();
+        roots
+            .iter()
+            .enumerate()
+            .filter(|(_, (_, id))| self.local_filesets.contains(id))
+            .filter_map(|(idx, (root, root_id))| {
+                // We are interested in parents if they are also local source roots.
+                // So instead of a non-local parent we may take a local ancestor as a parent to a node.
+                roots.iter().take(idx).find_map(|(root2, root2_id)| {
+                    if self.local_filesets.contains(root2_id) && root.starts_with(root2) {
+                        return Some((root_id, root2_id));
+                    }
+                    None
+                })
+            })
+            .for_each(|(child, parent)| {
+                map.insert(SourceRootId(*child as u32), SourceRootId(*parent as u32));
+            });
+        map
+    }
 }
 
 /// Load the proc-macros for the given lib path, replacing all expanders whose names are in `dummy_replace`
@@ -314,7 +339,7 @@ fn load_crate_graph(
 
     let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok());
     let mut db = RootDatabase::new(lru_cap);
-    let mut analysis_change = Change::new();
+    let mut analysis_change = ChangeWithProcMacros::new();
 
     db.enable_proc_attr_macros();
 
@@ -397,6 +422,11 @@ mod tests {
 
     use super::*;
 
+    use ide_db::base_db::SourceRootId;
+    use vfs::{file_set::FileSetConfigBuilder, VfsPath};
+
+    use crate::SourceRootConfig;
+
     #[test]
     fn test_loading_rust_analyzer() {
         let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap();
@@ -413,4 +443,124 @@ mod tests {
         // RA has quite a few crates, but the exact count doesn't matter
         assert!(n_crates > 20);
     }
+
+    #[test]
+    fn unrelated_sources() {
+        let mut builder = FileSetConfigBuilder::default();
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/abc".to_owned())]);
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/def".to_owned())]);
+        let fsc = builder.build();
+        let src = SourceRootConfig { fsc, local_filesets: vec![0, 1] };
+        let vc = src.source_root_parent_map().into_iter().collect::<Vec<_>>();
+
+        assert_eq!(vc, vec![])
+    }
+
+    #[test]
+    fn unrelated_source_sharing_dirname() {
+        let mut builder = FileSetConfigBuilder::default();
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/abc".to_owned())]);
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/def/abc".to_owned())]);
+        let fsc = builder.build();
+        let src = SourceRootConfig { fsc, local_filesets: vec![0, 1] };
+        let vc = src.source_root_parent_map().into_iter().collect::<Vec<_>>();
+
+        assert_eq!(vc, vec![])
+    }
+
+    #[test]
+    fn basic_child_parent() {
+        let mut builder = FileSetConfigBuilder::default();
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/abc".to_owned())]);
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/abc/def".to_owned())]);
+        let fsc = builder.build();
+        let src = SourceRootConfig { fsc, local_filesets: vec![0, 1] };
+        let vc = src.source_root_parent_map().into_iter().collect::<Vec<_>>();
+
+        assert_eq!(vc, vec![(SourceRootId(1), SourceRootId(0))])
+    }
+
+    #[test]
+    fn basic_child_parent_with_unrelated_parents_sib() {
+        let mut builder = FileSetConfigBuilder::default();
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/abc".to_owned())]);
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/def".to_owned())]);
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/def/abc".to_owned())]);
+        let fsc = builder.build();
+        let src = SourceRootConfig { fsc, local_filesets: vec![0, 1, 2] };
+        let vc = src.source_root_parent_map().into_iter().collect::<Vec<_>>();
+
+        assert_eq!(vc, vec![(SourceRootId(2), SourceRootId(1))])
+    }
+
+    #[test]
+    fn deep_sources_with_parent_missing() {
+        let mut builder = FileSetConfigBuilder::default();
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/abc".to_owned())]);
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/ghi".to_owned())]);
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/def/abc".to_owned())]);
+        let fsc = builder.build();
+        let src = SourceRootConfig { fsc, local_filesets: vec![0, 1, 2] };
+        let vc = src.source_root_parent_map().into_iter().collect::<Vec<_>>();
+
+        assert_eq!(vc, vec![])
+    }
+
+    #[test]
+    fn ancestor_can_be_parent() {
+        let mut builder = FileSetConfigBuilder::default();
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/abc".to_owned())]);
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/def".to_owned())]);
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/def/ghi/jkl".to_owned())]);
+        let fsc = builder.build();
+        let src = SourceRootConfig { fsc, local_filesets: vec![0, 1, 2] };
+        let vc = src.source_root_parent_map().into_iter().collect::<Vec<_>>();
+
+        assert_eq!(vc, vec![(SourceRootId(2), SourceRootId(1))])
+    }
+
+    #[test]
+    fn ancestor_can_be_parent_2() {
+        let mut builder = FileSetConfigBuilder::default();
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/abc".to_owned())]);
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/def".to_owned())]);
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/def/ghi/jkl".to_owned())]);
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/def/ghi/klm".to_owned())]);
+        let fsc = builder.build();
+        let src = SourceRootConfig { fsc, local_filesets: vec![0, 1, 2, 3] };
+        let mut vc = src.source_root_parent_map().into_iter().collect::<Vec<_>>();
+        vc.sort_by(|x, y| x.0 .0.cmp(&y.0 .0));
+
+        assert_eq!(vc, vec![(SourceRootId(2), SourceRootId(1)), (SourceRootId(3), SourceRootId(1))])
+    }
+
+    #[test]
+    fn non_locals_are_skipped() {
+        let mut builder = FileSetConfigBuilder::default();
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/abc".to_owned())]);
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/def".to_owned())]);
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/def/ghi/jkl".to_owned())]);
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/def/klm".to_owned())]);
+        let fsc = builder.build();
+        let src = SourceRootConfig { fsc, local_filesets: vec![0, 1, 3] };
+        let mut vc = src.source_root_parent_map().into_iter().collect::<Vec<_>>();
+        vc.sort_by(|x, y| x.0 .0.cmp(&y.0 .0));
+
+        assert_eq!(vc, vec![(SourceRootId(3), SourceRootId(1)),])
+    }
+
+    #[test]
+    fn child_binds_ancestor_if_parent_nonlocal() {
+        let mut builder = FileSetConfigBuilder::default();
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/abc".to_owned())]);
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/def".to_owned())]);
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/def/klm".to_owned())]);
+        builder.add_file_set(vec![VfsPath::new_virtual_path("/ROOT/def/klm/jkl".to_owned())]);
+        let fsc = builder.build();
+        let src = SourceRootConfig { fsc, local_filesets: vec![0, 1, 3] };
+        let mut vc = src.source_root_parent_map().into_iter().collect::<Vec<_>>();
+        vc.sort_by(|x, y| x.0 .0.cmp(&y.0 .0));
+
+        assert_eq!(vc, vec![(SourceRootId(3), SourceRootId(1)),])
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/parser/Cargo.toml b/src/tools/rust-analyzer/crates/parser/Cargo.toml
index e74b340126c..1f84e3f3af3 100644
--- a/src/tools/rust-analyzer/crates/parser/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/parser/Cargo.toml
@@ -15,6 +15,7 @@ doctest = false
 drop_bomb = "0.1.5"
 ra-ap-rustc_lexer.workspace = true
 limit.workspace = true
+tracing = { workspace = true, optional = true }
 
 [dev-dependencies]
 expect-test = "1.4.0"
@@ -23,6 +24,7 @@ stdx.workspace = true
 sourcegen.workspace = true
 
 [features]
+default = ["tracing"]
 in-rust-tree = []
 
 [lints]
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar.rs b/src/tools/rust-analyzer/crates/parser/src/grammar.rs
index 34715628f18..4e5837312fe 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar.rs
@@ -244,7 +244,7 @@ impl BlockLike {
     }
 }
 
-const VISIBILITY_FIRST: TokenSet = TokenSet::new(&[T![pub], T![crate]]);
+const VISIBILITY_FIRST: TokenSet = TokenSet::new(&[T![pub]]);
 
 fn opt_visibility(p: &mut Parser<'_>, in_tuple_field: bool) -> bool {
     if !p.at(T![pub]) {
@@ -416,14 +416,12 @@ fn delimited(
         if !parser(p) {
             break;
         }
-        if !p.at(delim) {
+        if !p.eat(delim) {
             if p.at_ts(first_set) {
                 p.error(format!("expected {:?}", delim));
             } else {
                 break;
             }
-        } else {
-            p.bump(delim);
         }
     }
     p.expect(ket);
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
index 6b660180f82..861fcedda2a 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions.rs
@@ -211,9 +211,8 @@ fn current_op(p: &Parser<'_>) -> (u8, SyntaxKind, Associativity) {
         T![>] if p.at(T![>>])  => (9,  T![>>],  Left),
         T![>] if p.at(T![>=])  => (5,  T![>=],  Left),
         T![>]                  => (5,  T![>],   Left),
-        T![=] if p.at(T![=>])  => NOT_AN_OP,
         T![=] if p.at(T![==])  => (5,  T![==],  Left),
-        T![=]                  => (1,  T![=],   Right),
+        T![=] if !p.at(T![=>]) => (1,  T![=],   Right),
         T![<] if p.at(T![<=])  => (5,  T![<=],  Left),
         T![<] if p.at(T![<<=]) => (1,  T![<<=], Right),
         T![<] if p.at(T![<<])  => (9,  T![<<],  Left),
@@ -247,7 +246,7 @@ fn current_op(p: &Parser<'_>) -> (u8, SyntaxKind, Associativity) {
 fn expr_bp(
     p: &mut Parser<'_>,
     m: Option<Marker>,
-    mut r: Restrictions,
+    r: Restrictions,
     bp: u8,
 ) -> Option<(CompletedMarker, BlockLike)> {
     let m = m.unwrap_or_else(|| {
@@ -295,10 +294,6 @@ fn expr_bp(
         let m = lhs.precede(p);
         p.bump(op);
 
-        // test binop_resets_statementness
-        // fn f() { v = {1}&2; }
-        r = Restrictions { prefer_stmt: false, ..r };
-
         if is_range {
             // test postfix_range
             // fn foo() {
@@ -319,6 +314,9 @@ fn expr_bp(
             Associativity::Left => op_bp + 1,
             Associativity::Right => op_bp,
         };
+
+        // test binop_resets_statementness
+        // fn f() { v = {1}&2; }
         expr_bp(p, None, Restrictions { prefer_stmt: false, ..r }, op_bp);
         lhs = m.complete(p, if is_range { RANGE_EXPR } else { BIN_EXPR });
     }
@@ -345,7 +343,7 @@ fn lhs(p: &mut Parser<'_>, r: Restrictions) -> Option<(CompletedMarker, BlockLik
         T![&] => {
             m = p.start();
             p.bump(T![&]);
-            if p.at_contextual_kw(T![raw]) && (p.nth_at(1, T![mut]) || p.nth_at(1, T![const])) {
+            if p.at_contextual_kw(T![raw]) && [T![mut], T![const]].contains(&p.nth(1)) {
                 p.bump_remap(T![raw]);
                 p.bump_any();
             } else {
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs
index 48600641ad0..72848a1f2b7 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/expressions/atom.rs
@@ -147,7 +147,7 @@ pub(super) fn atom_expr(
         T![async] if la == T![move] && p.nth(2) == T!['{'] => {
             let m = p.start();
             p.bump(T![async]);
-            p.eat(T![move]);
+            p.bump(T![move]);
             stmt_list(p);
             m.complete(p, BLOCK_EXPR)
         }
@@ -390,8 +390,7 @@ fn if_expr(p: &mut Parser<'_>) -> CompletedMarker {
     p.bump(T![if]);
     expr_no_struct(p);
     block_expr(p);
-    if p.at(T![else]) {
-        p.bump(T![else]);
+    if p.eat(T![else]) {
         if p.at(T![if]) {
             if_expr(p);
         } else {
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs
index 4498daf21a3..6c05abc0238 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs
@@ -170,7 +170,7 @@ fn type_bound(p: &mut Parser<'_>) -> bool {
                 _ => (),
             }
             if paths::is_use_path_start(p) {
-                types::path_type_(p, false);
+                types::path_type_bounds(p, false);
             } else {
                 m.abandon(p);
                 return false;
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs
index 243a219525a..25c00ccf5f3 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/items.rs
@@ -70,8 +70,7 @@ pub(super) fn item_or_macro(p: &mut Parser<'_>, stop_on_r_curly: bool) {
     // macro_rules! {};
     // macro_rules! ()
     // macro_rules! []
-    let no_ident = p.at_contextual_kw(T![macro_rules]) && p.nth_at(1, BANG) && !p.nth_at(2, IDENT);
-    if paths::is_use_path_start(p) || no_ident {
+    if paths::is_use_path_start(p) {
         macro_call(p, m);
         return;
     }
@@ -156,27 +155,19 @@ pub(super) fn opt_item(p: &mut Parser<'_>, m: Marker) -> Result<(), Marker> {
             // impl T for Foo {
             //     default async fn foo() {}
             // }
-            T![async] => {
-                let mut maybe_fn = p.nth(2);
-                let is_unsafe = if matches!(maybe_fn, T![unsafe]) {
-                    // test default_async_unsafe_fn
-                    // impl T for Foo {
-                    //     default async unsafe fn foo() {}
-                    // }
-                    maybe_fn = p.nth(3);
-                    true
-                } else {
-                    false
-                };
-
-                if matches!(maybe_fn, T![fn]) {
-                    p.bump_remap(T![default]);
-                    p.bump(T![async]);
-                    if is_unsafe {
-                        p.bump(T![unsafe]);
-                    }
-                    has_mods = true;
-                }
+            T![async]
+                if p.nth_at(2, T![fn]) || (p.nth_at(2, T![unsafe]) && p.nth_at(3, T![fn])) =>
+            {
+                p.bump_remap(T![default]);
+                p.bump(T![async]);
+
+                // test default_async_unsafe_fn
+                // impl T for Foo {
+                //     default async unsafe fn foo() {}
+                // }
+                p.eat(T![unsafe]);
+
+                has_mods = true;
             }
             _ => (),
         }
@@ -419,11 +410,9 @@ fn fn_(p: &mut Parser<'_>, m: Marker) {
     // fn foo<T>() where T: Copy {}
     generic_params::opt_where_clause(p);
 
-    if p.at(T![;]) {
-        // test fn_decl
-        // trait T { fn foo(); }
-        p.bump(T![;]);
-    } else {
+    // test fn_decl
+    // trait T { fn foo(); }
+    if !p.eat(T![;]) {
         expressions::block_expr(p);
     }
     m.complete(p, FN);
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/items/traits.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/items/traits.rs
index a8a1ccb15e6..c215185d632 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/items/traits.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/items/traits.rs
@@ -119,11 +119,11 @@ fn not_a_qualified_path(p: &Parser<'_>) -> bool {
     // we disambiguate it in favor of generics (`impl<T> ::absolute::Path<T> { ... }`)
     // because this is what almost always expected in practice, qualified paths in impls
     // (`impl <Type>::AssocTy { ... }`) aren't even allowed by type checker at the moment.
-    if p.nth(1) == T![#] || p.nth(1) == T![>] || p.nth(1) == T![const] {
+    if [T![#], T![>], T![const]].contains(&p.nth(1)) {
         return true;
     }
-    (p.nth(1) == LIFETIME_IDENT || p.nth(1) == IDENT)
-        && (p.nth(2) == T![>] || p.nth(2) == T![,] || p.nth(2) == T![:] || p.nth(2) == T![=])
+    ([LIFETIME_IDENT, IDENT].contains(&p.nth(1)))
+        && ([T![>], T![,], T![:], T![=]].contains(&p.nth(2)))
 }
 
 // test_err impl_type
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/params.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/params.rs
index 846da28cb01..c535267c165 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/params.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/params.rs
@@ -76,19 +76,16 @@ fn list_(p: &mut Parser<'_>, flavor: Flavor) {
             m.abandon(p);
             if p.eat(T![,]) {
                 continue;
-            } else {
-                break;
             }
+            break;
         }
         param(p, m, flavor);
-        if !p.at(T![,]) {
+        if !p.eat(T![,]) {
             if p.at_ts(PARAM_FIRST.union(ATTRIBUTE_FIRST)) {
                 p.error("expected `,`");
             } else {
                 break;
             }
-        } else {
-            p.bump(T![,]);
         }
     }
 
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs
index 50367423379..eff6b664049 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/patterns.rs
@@ -255,9 +255,7 @@ fn is_literal_pat_start(p: &Parser<'_>) -> bool {
 fn literal_pat(p: &mut Parser<'_>) -> CompletedMarker {
     assert!(is_literal_pat_start(p));
     let m = p.start();
-    if p.at(T![-]) {
-        p.bump(T![-]);
-    }
+    p.eat(T![-]);
     expressions::literal(p);
     m.complete(p, LITERAL_PAT)
 }
@@ -468,14 +466,12 @@ fn slice_pat(p: &mut Parser<'_>) -> CompletedMarker {
 fn pat_list(p: &mut Parser<'_>, ket: SyntaxKind) {
     while !p.at(EOF) && !p.at(ket) {
         pattern_top(p);
-        if !p.at(T![,]) {
+        if !p.eat(T![,]) {
             if p.at_ts(PAT_TOP_FIRST) {
                 p.error(format!("expected {:?}, got {:?}", T![,], p.current()));
             } else {
                 break;
             }
-        } else {
-            p.bump(T![,]);
         }
     }
 }
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs
index 96a6cdeaaff..18ec570cd56 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/types.rs
@@ -48,7 +48,7 @@ fn type_with_bounds_cond(p: &mut Parser<'_>, allow_bounds: bool) {
         T![impl] => impl_trait_type(p),
         T![dyn] => dyn_trait_type(p),
         // Some path types are not allowed to have bounds (no plus)
-        T![<] => path_type_(p, allow_bounds),
+        T![<] => path_type_bounds(p, allow_bounds),
         _ if paths::is_path_start(p) => path_or_macro_type_(p, allow_bounds),
         LIFETIME_IDENT if p.nth_at(1, T![+]) => bare_dyn_trait_type(p),
         _ => {
@@ -294,7 +294,7 @@ fn bare_dyn_trait_type(p: &mut Parser<'_>) {
 // type C = self::Foo;
 // type D = super::Foo;
 pub(super) fn path_type(p: &mut Parser<'_>) {
-    path_type_(p, true);
+    path_type_bounds(p, true);
 }
 
 // test macro_call_type
@@ -323,7 +323,7 @@ fn path_or_macro_type_(p: &mut Parser<'_>, allow_bounds: bool) {
     }
 }
 
-pub(super) fn path_type_(p: &mut Parser<'_>, allow_bounds: bool) {
+pub(super) fn path_type_bounds(p: &mut Parser<'_>, allow_bounds: bool) {
     assert!(paths::is_path_start(p));
     let m = p.start();
     paths::type_path(p);
diff --git a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs
index 2da9184693d..48e4c8a6225 100644
--- a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs
@@ -31,6 +31,7 @@ struct LexError {
 
 impl<'a> LexedStr<'a> {
     pub fn new(text: &'a str) -> LexedStr<'a> {
+        let _p = tracing::span!(tracing::Level::INFO, "LexedStr::new").entered();
         let mut conv = Converter::new(text);
         if let Some(shebang_len) = rustc_lexer::strip_shebang(text) {
             conv.res.push(SHEBANG, conv.offset);
diff --git a/src/tools/rust-analyzer/crates/parser/src/lib.rs b/src/tools/rust-analyzer/crates/parser/src/lib.rs
index 3ca285e787e..86c771c0008 100644
--- a/src/tools/rust-analyzer/crates/parser/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/lib.rs
@@ -87,6 +87,7 @@ pub enum TopEntryPoint {
 
 impl TopEntryPoint {
     pub fn parse(&self, input: &Input) -> Output {
+        let _p = tracing::span!(tracing::Level::INFO, "TopEntryPoint::parse", ?self).entered();
         let entry_point: fn(&'_ mut parser::Parser<'_>) = match self {
             TopEntryPoint::SourceFile => grammar::entry::top::source_file,
             TopEntryPoint::MacroStmts => grammar::entry::top::macro_stmts,
diff --git a/src/tools/rust-analyzer/crates/parser/src/parser.rs b/src/tools/rust-analyzer/crates/parser/src/parser.rs
index ef413c63754..051461243af 100644
--- a/src/tools/rust-analyzer/crates/parser/src/parser.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/parser.rs
@@ -250,12 +250,9 @@ impl<'t> Parser<'t> {
 
     /// Create an error node and consume the next token.
     pub(crate) fn err_recover(&mut self, message: &str, recovery: TokenSet) {
-        match self.current() {
-            T!['{'] | T!['}'] => {
-                self.error(message);
-                return;
-            }
-            _ => (),
+        if matches!(self.current(), T!['{'] | T!['}']) {
+            self.error(message);
+            return;
         }
 
         if self.at_ts(recovery) {
diff --git a/src/tools/rust-analyzer/crates/parser/src/shortcuts.rs b/src/tools/rust-analyzer/crates/parser/src/shortcuts.rs
index 57005a6834c..cc2b63d1e66 100644
--- a/src/tools/rust-analyzer/crates/parser/src/shortcuts.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/shortcuts.rs
@@ -26,6 +26,7 @@ pub enum StrStep<'a> {
 
 impl LexedStr<'_> {
     pub fn to_input(&self) -> crate::Input {
+        let _p = tracing::span!(tracing::Level::INFO, "LexedStr::to_input").entered();
         let mut res = crate::Input::default();
         let mut was_joint = false;
         for i in 0..self.len() {
@@ -189,7 +190,7 @@ impl Builder<'_, '_> {
 
     fn do_float_split(&mut self, has_pseudo_dot: bool) {
         let text = &self.lexed.range_text(self.pos..self.pos + 1);
-        self.pos += 1;
+
         match text.split_once('.') {
             Some((left, right)) => {
                 assert!(!left.is_empty());
@@ -215,8 +216,22 @@ impl Builder<'_, '_> {
                     self.state = State::PendingExit;
                 }
             }
-            None => unreachable!(),
+            None => {
+                // illegal float literal which doesn't have dot in form (like 1e0)
+                // we should emit an error node here
+                (self.sink)(StrStep::Error { msg: "illegal float literal", pos: self.pos });
+                (self.sink)(StrStep::Enter { kind: SyntaxKind::ERROR });
+                (self.sink)(StrStep::Token { kind: SyntaxKind::FLOAT_NUMBER, text });
+                (self.sink)(StrStep::Exit);
+
+                // move up
+                (self.sink)(StrStep::Exit);
+
+                self.state = if has_pseudo_dot { State::Normal } else { State::PendingExit };
+            }
         }
+
+        self.pos += 1;
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0054_float_split_scientific_notation.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0054_float_split_scientific_notation.rast
new file mode 100644
index 00000000000..d6ad7334839
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0054_float_split_scientific_notation.rast
@@ -0,0 +1,88 @@
+SOURCE_FILE
+  STRUCT
+    STRUCT_KW "struct"
+    WHITESPACE " "
+    NAME
+      IDENT "S"
+    TUPLE_FIELD_LIST
+      L_PAREN "("
+      TUPLE_FIELD
+        PATH_TYPE
+          PATH
+            PATH_SEGMENT
+              NAME_REF
+                IDENT "i32"
+      COMMA ","
+      WHITESPACE " "
+      TUPLE_FIELD
+        PATH_TYPE
+          PATH
+            PATH_SEGMENT
+              NAME_REF
+                IDENT "i32"
+      R_PAREN ")"
+    SEMICOLON ";"
+  WHITESPACE "\n"
+  FN
+    FN_KW "fn"
+    WHITESPACE " "
+    NAME
+      IDENT "f"
+    PARAM_LIST
+      L_PAREN "("
+      R_PAREN ")"
+    WHITESPACE " "
+    BLOCK_EXPR
+      STMT_LIST
+        L_CURLY "{"
+        WHITESPACE "\n    "
+        LET_STMT
+          LET_KW "let"
+          WHITESPACE " "
+          IDENT_PAT
+            NAME
+              IDENT "s"
+          WHITESPACE " "
+          EQ "="
+          WHITESPACE " "
+          CALL_EXPR
+            PATH_EXPR
+              PATH
+                PATH_SEGMENT
+                  NAME_REF
+                    IDENT "S"
+            ARG_LIST
+              L_PAREN "("
+              LITERAL
+                INT_NUMBER "1"
+              COMMA ","
+              WHITESPACE " "
+              LITERAL
+                INT_NUMBER "2"
+              R_PAREN ")"
+          SEMICOLON ";"
+        WHITESPACE "\n    "
+        LET_STMT
+          LET_KW "let"
+          WHITESPACE " "
+          IDENT_PAT
+            NAME
+              IDENT "a"
+          WHITESPACE " "
+          EQ "="
+          WHITESPACE " "
+          FIELD_EXPR
+            FIELD_EXPR
+              PATH_EXPR
+                PATH
+                  PATH_SEGMENT
+                    NAME_REF
+                      IDENT "s"
+              DOT "."
+              ERROR
+                FLOAT_NUMBER "1e0"
+          SEMICOLON ";"
+        WHITESPACE "\n"
+        R_CURLY "}"
+  WHITESPACE "\n"
+error 42: illegal float literal
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0054_float_split_scientific_notation.rs b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0054_float_split_scientific_notation.rs
new file mode 100644
index 00000000000..648ef5e0430
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/err/0054_float_split_scientific_notation.rs
@@ -0,0 +1,5 @@
+struct S(i32, i32);
+fn f() {
+    let s = S(1, 2);
+    let a = s.1e0;
+}
diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml
index cf01b94c0a2..978ad155609 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-api/Cargo.toml
@@ -12,13 +12,7 @@ rust-version.workspace = true
 doctest = false
 
 [dependencies]
-object = { version = "0.32.0", default-features = false, features = [
-    "std",
-    "read_core",
-    "elf",
-    "macho",
-    "pe",
-] }
+object.workspace = true
 serde.workspace = true
 serde_json = { workspace = true, features = ["unbounded_depth"] }
 tracing.workspace = true
@@ -32,7 +26,6 @@ indexmap = "2.1.0"
 paths.workspace = true
 tt.workspace = true
 stdx.workspace = true
-profile.workspace = true
 text-size.workspace = true
 span.workspace = true
 # Ideally this crate would not depend on salsa things, but we need span information here which wraps
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml
index bd7a3165458..f8db1c6a30b 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml
@@ -12,13 +12,7 @@ rust-version.workspace = true
 doctest = false
 
 [dependencies]
-object = { version = "0.32.0", default-features = false, features = [
-    "std",
-    "read_core",
-    "elf",
-    "macho",
-    "pe",
-] }
+object.workspace = true
 libloading = "0.8.0"
 memmap2 = "0.5.4"
 
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml
index 7977afb1cbd..7c6a1ba46b5 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml
@@ -11,6 +11,3 @@ doctest = false
 
 [build-dependencies]
 cargo_metadata = "0.18.1"
-
-# local deps
-toolchain.workspace = true
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs
index ff62980e4ff..c76c201d69e 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/build.rs
@@ -18,12 +18,12 @@ use cargo_metadata::Message;
 fn main() {
     println!("cargo:rerun-if-changed=imp");
 
+    let cargo = env::var_os("CARGO").unwrap_or_else(|| "cargo".into());
+
     let has_features = env::var_os("RUSTC_BOOTSTRAP").is_some()
-        || String::from_utf8(
-            Command::new(toolchain::cargo()).arg("--version").output().unwrap().stdout,
-        )
-        .unwrap()
-        .contains("nightly");
+        || String::from_utf8(Command::new(&cargo).arg("--version").output().unwrap().stdout)
+            .unwrap()
+            .contains("nightly");
 
     let out_dir = env::var_os("OUT_DIR").unwrap();
     let out_dir = Path::new(&out_dir);
@@ -66,7 +66,7 @@ fn main() {
 
     let target_dir = out_dir.join("target");
 
-    let mut cmd = Command::new(toolchain::cargo());
+    let mut cmd = Command::new(&cargo);
     cmd.current_dir(&staging_dir)
         .args(["build", "-p", "proc-macro-test-impl", "--message-format", "json"])
         // Explicit override the target directory to avoid using the same one which the parent
@@ -96,7 +96,7 @@ fn main() {
     let repr = format!("{name} {version}");
     // New Package Id Spec since rust-lang/cargo#13311
     let pkgid = String::from_utf8(
-        Command::new(toolchain::cargo())
+        Command::new(cargo)
             .current_dir(&staging_dir)
             .args(["pkgid", name])
             .output()
diff --git a/src/tools/rust-analyzer/crates/profile/src/lib.rs b/src/tools/rust-analyzer/crates/profile/src/lib.rs
index 36399815606..a3fdb72a6d1 100644
--- a/src/tools/rust-analyzer/crates/profile/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/profile/src/lib.rs
@@ -23,29 +23,6 @@ pub use countme::Count;
 
 thread_local!(static IN_SCOPE: RefCell<bool> = const { RefCell::new(false) });
 
-/// Allows to check if the current code is within some dynamic scope, can be
-/// useful during debugging to figure out why a function is called.
-pub struct Scope {
-    prev: bool,
-}
-
-impl Scope {
-    #[must_use]
-    pub fn enter() -> Scope {
-        let prev = IN_SCOPE.with(|slot| std::mem::replace(&mut *slot.borrow_mut(), true));
-        Scope { prev }
-    }
-    pub fn is_active() -> bool {
-        IN_SCOPE.with(|slot| *slot.borrow())
-    }
-}
-
-impl Drop for Scope {
-    fn drop(&mut self) {
-        IN_SCOPE.with(|slot| *slot.borrow_mut() = self.prev);
-    }
-}
-
 /// A wrapper around google_cpu_profiler.
 ///
 /// Usage:
diff --git a/src/tools/rust-analyzer/crates/project-model/Cargo.toml b/src/tools/rust-analyzer/crates/project-model/Cargo.toml
index 3552ed19162..924a4a89e21 100644
--- a/src/tools/rust-analyzer/crates/project-model/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/project-model/Cargo.toml
@@ -27,7 +27,6 @@ itertools.workspace = true
 base-db.workspace = true
 cfg.workspace = true
 paths.workspace = true
-profile.workspace = true
 stdx.workspace = true
 toolchain.workspace = true
 
@@ -35,4 +34,4 @@ toolchain.workspace = true
 expect-test = "1.4.0"
 
 [lints]
-workspace = true
\ No newline at end of file
+workspace = true
diff --git a/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs b/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs
index 27a8db40a99..709fc037174 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/build_scripts.rs
@@ -71,8 +71,7 @@ impl WorkspaceBuildScripts {
                 cmd
             }
             _ => {
-                let mut cmd = Command::new(Tool::Cargo.path());
-                Sysroot::set_rustup_toolchain_env(&mut cmd, sysroot);
+                let mut cmd = Sysroot::tool(sysroot, Tool::Cargo);
 
                 cmd.args(["check", "--quiet", "--workspace", "--message-format=json"]);
                 cmd.args(&config.extra_args);
@@ -430,8 +429,7 @@ impl WorkspaceBuildScripts {
         }
         let res = (|| {
             let target_libdir = (|| {
-                let mut cargo_config = Command::new(Tool::Cargo.path());
-                Sysroot::set_rustup_toolchain_env(&mut cargo_config, sysroot);
+                let mut cargo_config = Sysroot::tool(sysroot, Tool::Cargo);
                 cargo_config.envs(extra_env);
                 cargo_config
                     .current_dir(current_dir)
@@ -440,7 +438,7 @@ impl WorkspaceBuildScripts {
                 if let Ok(it) = utf8_stdout(cargo_config) {
                     return Ok(it);
                 }
-                let mut cmd = Sysroot::rustc(sysroot);
+                let mut cmd = Sysroot::tool(sysroot, Tool::Rustc);
                 cmd.envs(extra_env);
                 cmd.args(["--print", "target-libdir"]);
                 utf8_stdout(cmd)
diff --git a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs
index 609b1f67b57..53b41ea1e87 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/cargo_workspace.rs
@@ -1,8 +1,8 @@
 //! See [`CargoWorkspace`].
 
+use std::ops;
 use std::path::PathBuf;
 use std::str::from_utf8;
-use std::{ops, process::Command};
 
 use anyhow::Context;
 use base_db::Edition;
@@ -243,8 +243,11 @@ impl CargoWorkspace {
     ) -> anyhow::Result<cargo_metadata::Metadata> {
         let targets = find_list_of_build_targets(config, cargo_toml, sysroot);
 
+        let cargo = Sysroot::tool(sysroot, Tool::Cargo);
         let mut meta = MetadataCommand::new();
-        meta.cargo_path(Tool::Cargo.path());
+        meta.cargo_path(cargo.get_program());
+        cargo.get_envs().for_each(|(var, val)| _ = meta.env(var, val.unwrap_or_default()));
+        config.extra_env.iter().for_each(|(var, val)| _ = meta.env(var, val));
         meta.manifest_path(cargo_toml.to_path_buf());
         match &config.features {
             CargoFeatures::All => {
@@ -291,10 +294,7 @@ impl CargoWorkspace {
         progress("metadata".to_owned());
 
         (|| -> Result<cargo_metadata::Metadata, cargo_metadata::Error> {
-            let mut command = meta.cargo_command();
-            Sysroot::set_rustup_toolchain_env(&mut command, sysroot);
-            command.envs(&config.extra_env);
-            let output = command.output()?;
+            let output = meta.cargo_command().output()?;
             if !output.status.success() {
                 return Err(cargo_metadata::Error::CargoMetadata {
                     stderr: String::from_utf8(output.stderr)?,
@@ -501,7 +501,7 @@ fn rustc_discover_host_triple(
     extra_env: &FxHashMap<String, String>,
     sysroot: Option<&Sysroot>,
 ) -> Option<String> {
-    let mut rustc = Sysroot::rustc(sysroot);
+    let mut rustc = Sysroot::tool(sysroot, Tool::Rustc);
     rustc.envs(extra_env);
     rustc.current_dir(cargo_toml.parent()).arg("-vV");
     tracing::debug!("Discovering host platform by {:?}", rustc);
@@ -529,8 +529,7 @@ fn cargo_config_build_target(
     extra_env: &FxHashMap<String, String>,
     sysroot: Option<&Sysroot>,
 ) -> Vec<String> {
-    let mut cargo_config = Command::new(Tool::Cargo.path());
-    Sysroot::set_rustup_toolchain_env(&mut cargo_config, sysroot);
+    let mut cargo_config = Sysroot::tool(sysroot, Tool::Cargo);
     cargo_config.envs(extra_env);
     cargo_config
         .current_dir(cargo_toml.parent())
diff --git a/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs b/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs
index 001296fb000..501b1fdc8c5 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/rustc_cfg.rs
@@ -1,9 +1,8 @@
 //! Runs `rustc --print cfg` to get built-in cfg flags.
 
-use std::process::Command;
-
 use anyhow::Context;
 use rustc_hash::FxHashMap;
+use toolchain::Tool;
 
 use crate::{cfg_flag::CfgFlag, utf8_stdout, ManifestPath, Sysroot};
 
@@ -69,8 +68,8 @@ fn get_rust_cfgs(
 ) -> anyhow::Result<String> {
     let sysroot = match config {
         RustcCfgConfig::Cargo(sysroot, cargo_toml) => {
-            let mut cmd = Command::new(toolchain::Tool::Cargo.path());
-            Sysroot::set_rustup_toolchain_env(&mut cmd, sysroot);
+            let mut cmd = Sysroot::tool(sysroot, Tool::Cargo);
+
             cmd.envs(extra_env);
             cmd.current_dir(cargo_toml.parent())
                 .args(["rustc", "-Z", "unstable-options", "--print", "cfg"])
@@ -90,7 +89,7 @@ fn get_rust_cfgs(
         RustcCfgConfig::Rustc(sysroot) => sysroot,
     };
 
-    let mut cmd = Sysroot::rustc(sysroot);
+    let mut cmd = Sysroot::tool(sysroot, Tool::Rustc);
     cmd.envs(extra_env);
     cmd.args(["--print", "cfg", "-O"]);
     if let Some(target) = target {
diff --git a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
index ea24393ed8a..3127bae8b0c 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/sysroot.rs
@@ -12,7 +12,7 @@ use itertools::Itertools;
 use la_arena::{Arena, Idx};
 use paths::{AbsPath, AbsPathBuf};
 use rustc_hash::FxHashMap;
-use toolchain::probe_for_binary;
+use toolchain::{probe_for_binary, Tool};
 
 use crate::{utf8_stdout, CargoConfig, CargoWorkspace, ManifestPath};
 
@@ -193,23 +193,26 @@ impl Sysroot {
         Ok(Sysroot::load(sysroot_dir, Some(sysroot_src_dir), metadata))
     }
 
-    pub fn set_rustup_toolchain_env(cmd: &mut Command, sysroot: Option<&Self>) {
-        if let Some(sysroot) = sysroot {
-            cmd.env("RUSTUP_TOOLCHAIN", AsRef::<std::path::Path>::as_ref(&sysroot.root));
-        }
-    }
-
-    /// Returns a `Command` that is configured to run `rustc` from the sysroot if it exists,
-    /// otherwise returns what [toolchain::Tool::Rustc] returns.
-    pub fn rustc(sysroot: Option<&Self>) -> Command {
-        let mut cmd = Command::new(match sysroot {
+    /// Returns a command to run a tool preferring the cargo proxies if the sysroot exists.
+    pub fn tool(sysroot: Option<&Self>, tool: Tool) -> Command {
+        match sysroot {
             Some(sysroot) => {
-                toolchain::Tool::Rustc.path_in_or_discover(sysroot.root.join("bin").as_ref())
+                // special case rustc, we can look that up directly in the sysroot's bin folder
+                // as it should never invoke another cargo binary
+                if let Tool::Rustc = tool {
+                    if let Some(path) =
+                        probe_for_binary(sysroot.root.join("bin").join(Tool::Rustc.name()).into())
+                    {
+                        return Command::new(path);
+                    }
+                }
+
+                let mut cmd = Command::new(tool.prefer_proxy());
+                cmd.env("RUSTUP_TOOLCHAIN", AsRef::<std::path::Path>::as_ref(&sysroot.root));
+                cmd
             }
-            None => toolchain::Tool::Rustc.path(),
-        });
-        Self::set_rustup_toolchain_env(&mut cmd, sysroot);
-        cmd
+            _ => Command::new(tool.path()),
+        }
     }
 
     pub fn discover_proc_macro_srv(&self) -> anyhow::Result<AbsPathBuf> {
@@ -411,7 +414,7 @@ fn discover_sysroot_dir(
     current_dir: &AbsPath,
     extra_env: &FxHashMap<String, String>,
 ) -> Result<AbsPathBuf> {
-    let mut rustc = Command::new(toolchain::rustc());
+    let mut rustc = Command::new(Tool::Rustc.path());
     rustc.envs(extra_env);
     rustc.current_dir(current_dir).args(["--print", "sysroot"]);
     tracing::debug!("Discovering sysroot by {:?}", rustc);
@@ -443,7 +446,7 @@ fn discover_sysroot_src_dir_or_add_component(
 ) -> Result<AbsPathBuf> {
     discover_sysroot_src_dir(sysroot_path)
         .or_else(|| {
-            let mut rustup = Command::new(toolchain::rustup());
+            let mut rustup = Command::new(Tool::Rustup.prefer_proxy());
             rustup.envs(extra_env);
             rustup.current_dir(current_dir).args(["component", "add", "rust-src"]);
             tracing::info!("adding rust-src component by {:?}", rustup);
diff --git a/src/tools/rust-analyzer/crates/project-model/src/target_data_layout.rs b/src/tools/rust-analyzer/crates/project-model/src/target_data_layout.rs
index df77541762d..4e810a0232e 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/target_data_layout.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/target_data_layout.rs
@@ -1,7 +1,7 @@
 //! Runs `rustc --print target-spec-json` to get the target_data_layout.
-use std::process::Command;
 
 use rustc_hash::FxHashMap;
+use toolchain::Tool;
 
 use crate::{utf8_stdout, ManifestPath, Sysroot};
 
@@ -28,8 +28,7 @@ pub fn get(
     };
     let sysroot = match config {
         RustcDataLayoutConfig::Cargo(sysroot, cargo_toml) => {
-            let mut cmd = Command::new(toolchain::Tool::Cargo.path());
-            Sysroot::set_rustup_toolchain_env(&mut cmd, sysroot);
+            let mut cmd = Sysroot::tool(sysroot, Tool::Cargo);
             cmd.envs(extra_env);
             cmd.current_dir(cargo_toml.parent())
                 .args([
@@ -57,7 +56,7 @@ pub fn get(
         RustcDataLayoutConfig::Rustc(sysroot) => sysroot,
     };
 
-    let mut cmd = Sysroot::rustc(sysroot);
+    let mut cmd = Sysroot::tool(sysroot, Tool::Rustc);
     cmd.envs(extra_env)
         .args(["-Z", "unstable-options", "--print", "target-spec-json"])
         .env("RUSTC_BOOTSTRAP", "1");
diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
index adf15d45fc6..1a138b17bad 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
@@ -2,7 +2,7 @@
 //! metadata` or `rust-project.json`) into representation stored in the salsa
 //! database -- `CrateGraph`.
 
-use std::{collections::VecDeque, fmt, fs, iter, process::Command, str::FromStr, sync};
+use std::{collections::VecDeque, fmt, fs, iter, str::FromStr, sync};
 
 use anyhow::{format_err, Context};
 use base_db::{
@@ -172,11 +172,13 @@ impl fmt::Debug for ProjectWorkspace {
 
 fn get_toolchain_version(
     current_dir: &AbsPath,
-    mut cmd: Command,
+    sysroot: Option<&Sysroot>,
+    tool: Tool,
     extra_env: &FxHashMap<String, String>,
     prefix: &str,
 ) -> Result<Option<Version>, anyhow::Error> {
     let cargo_version = utf8_stdout({
+        let mut cmd = Sysroot::tool(sysroot, tool);
         cmd.envs(extra_env);
         cmd.arg("--version").current_dir(current_dir);
         cmd
@@ -297,11 +299,8 @@ impl ProjectWorkspace {
 
                 let toolchain = get_toolchain_version(
                     cargo_toml.parent(),
-                    {
-                        let mut cmd = Command::new(toolchain::Tool::Cargo.path());
-                        Sysroot::set_rustup_toolchain_env(&mut cmd, sysroot_ref);
-                        cmd
-                    },
+                    sysroot_ref,
+                    Tool::Cargo,
                     &config.extra_env,
                     "cargo ",
                 )?;
@@ -386,7 +385,8 @@ impl ProjectWorkspace {
         let data_layout_config = RustcDataLayoutConfig::Rustc(sysroot_ref);
         let toolchain = match get_toolchain_version(
             project_json.path(),
-            Sysroot::rustc(sysroot_ref),
+            sysroot_ref,
+            Tool::Rustc,
             extra_env,
             "rustc ",
         ) {
@@ -433,18 +433,15 @@ impl ProjectWorkspace {
         };
 
         let sysroot_ref = sysroot.as_ref().ok();
-        let toolchain = match get_toolchain_version(
-            dir,
-            Sysroot::rustc(sysroot_ref),
-            &config.extra_env,
-            "rustc ",
-        ) {
-            Ok(it) => it,
-            Err(e) => {
-                tracing::error!("{e}");
-                None
-            }
-        };
+        let toolchain =
+            match get_toolchain_version(dir, sysroot_ref, Tool::Rustc, &config.extra_env, "rustc ")
+            {
+                Ok(it) => it,
+                Err(e) => {
+                    tracing::error!("{e}");
+                    None
+                }
+            };
 
         let rustc_cfg = rustc_cfg::get(None, &config.extra_env, RustcCfgConfig::Rustc(sysroot_ref));
         let data_layout = target_data_layout::get(
@@ -1573,8 +1570,7 @@ fn cargo_config_env(
     extra_env: &FxHashMap<String, String>,
     sysroot: Option<&Sysroot>,
 ) -> FxHashMap<String, String> {
-    let mut cargo_config = Command::new(Tool::Cargo.path());
-    Sysroot::set_rustup_toolchain_env(&mut cargo_config, sysroot);
+    let mut cargo_config = Sysroot::tool(sysroot, Tool::Cargo);
     cargo_config.envs(extra_env);
     cargo_config
         .current_dir(cargo_toml.parent())
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
index a212041e66b..766606be7be 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
@@ -85,7 +85,6 @@ force-always-assert = ["always-assert/force"]
 sysroot-abi = []
 in-rust-tree = [
     "sysroot-abi",
-    "ide/in-rust-tree",
     "syntax/in-rust-tree",
     "parser/in-rust-tree",
     "hir/in-rust-tree",
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
index 8762564a8f1..ef184032bfb 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -371,7 +371,7 @@ impl flags::AnalysisStats {
 
             let parse = sema.parse(file_id);
             let file_txt = db.file_text(file_id);
-            let path = vfs.file_path(file_id).as_path().unwrap().to_owned();
+            let path = vfs.file_path(file_id).as_path().unwrap();
 
             for node in parse.syntax().descendants() {
                 let expr = match syntax::ast::Expr::cast(node.clone()) {
@@ -446,7 +446,7 @@ impl flags::AnalysisStats {
                     edit.apply(&mut txt);
 
                     if self.validate_term_search {
-                        std::fs::write(&path, txt).unwrap();
+                        std::fs::write(path, txt).unwrap();
 
                         let res = ws.run_build_scripts(&cargo_config, &|_| ()).unwrap();
                         if let Some(err) = res.error() {
@@ -495,7 +495,7 @@ impl flags::AnalysisStats {
             }
             // Revert file back to original state
             if self.validate_term_search {
-                std::fs::write(&path, file_txt.to_string()).unwrap();
+                std::fs::write(path, file_txt.to_string()).unwrap();
             }
 
             bar.inc(1);
@@ -982,6 +982,7 @@ impl flags::AnalysisStats {
                     },
                     prefer_no_std: false,
                     prefer_prelude: true,
+                    style_lints: false,
                 },
                 ide::AssistResolveStrategy::All,
                 file_id,
@@ -1077,12 +1078,12 @@ fn location_csv_pat(db: &RootDatabase, vfs: &Vfs, sm: &BodySourceMap, pat_id: Pa
     format!("{path},{}:{},{}:{}", start.line + 1, start.col, end.line + 1, end.col)
 }
 
-fn expr_syntax_range(
+fn expr_syntax_range<'a>(
     db: &RootDatabase,
-    vfs: &Vfs,
+    vfs: &'a Vfs,
     sm: &BodySourceMap,
     expr_id: ExprId,
-) -> Option<(VfsPath, LineCol, LineCol)> {
+) -> Option<(&'a VfsPath, LineCol, LineCol)> {
     let src = sm.expr_syntax(expr_id);
     if let Ok(src) = src {
         let root = db.parse_or_expand(src.file_id);
@@ -1098,12 +1099,12 @@ fn expr_syntax_range(
         None
     }
 }
-fn pat_syntax_range(
+fn pat_syntax_range<'a>(
     db: &RootDatabase,
-    vfs: &Vfs,
+    vfs: &'a Vfs,
     sm: &BodySourceMap,
     pat_id: PatId,
-) -> Option<(VfsPath, LineCol, LineCol)> {
+) -> Option<(&'a VfsPath, LineCol, LineCol)> {
     let src = sm.pat_syntax(pat_id);
     if let Ok(src) = src {
         let root = db.parse_or_expand(src.file_id);
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs
index 31d2a67981f..f3f5ec1ebde 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/lsif.rs
@@ -7,11 +7,7 @@ use ide::{
     Analysis, AnalysisHost, FileId, FileRange, MonikerKind, PackageInformation, RootDatabase,
     StaticIndex, StaticIndexedFile, TokenId, TokenStaticData,
 };
-use ide_db::{
-    base_db::salsa::{self, ParallelDatabase},
-    line_index::WideEncoding,
-    LineIndexDatabase,
-};
+use ide_db::{line_index::WideEncoding, LineIndexDatabase};
 use load_cargo::{load_workspace, LoadCargoConfig, ProcMacroServerChoice};
 use lsp_types::lsif;
 use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace, RustLibSource};
@@ -25,14 +21,6 @@ use crate::{
     version::version,
 };
 
-/// Need to wrap Snapshot to provide `Clone` impl for `map_with`
-struct Snap<DB>(DB);
-impl<DB: ParallelDatabase> Clone for Snap<salsa::Snapshot<DB>> {
-    fn clone(&self) -> Snap<salsa::Snapshot<DB>> {
-        Snap(self.0.snapshot())
-    }
-}
-
 struct LsifManager<'a> {
     count: i32,
     token_map: FxHashMap<TokenId, Id>,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs
index 9276d241aff..7ad87ab97fc 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/rustc_tests.rs
@@ -5,7 +5,7 @@ use std::thread::Builder;
 use std::time::{Duration, Instant};
 use std::{cell::RefCell, fs::read_to_string, panic::AssertUnwindSafe, path::PathBuf};
 
-use hir::{Change, Crate};
+use hir::{ChangeWithProcMacros, Crate};
 use ide::{AnalysisHost, DiagnosticCode, DiagnosticsConfig};
 use itertools::Either;
 use profile::StopWatch;
@@ -122,7 +122,7 @@ impl Tester {
             FxHashMap::default()
         };
         let text = read_to_string(&p).unwrap();
-        let mut change = Change::new();
+        let mut change = ChangeWithProcMacros::new();
         // Ignore unstable tests, since they move too fast and we do not intend to support all of them.
         let mut ignore_test = text.contains("#![feature");
         // Ignore test with extern crates, as this infra don't support them yet.
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
index 0da6101b350..9e81c8dd665 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -311,6 +311,8 @@ config_data! {
         /// Map of prefixes to be substituted when parsing diagnostic file paths.
         /// This should be the reverse mapping of what is passed to `rustc` as `--remap-path-prefix`.
         diagnostics_remapPrefix: FxHashMap<String, String> = "{}",
+        /// Whether to run additional style lints.
+        diagnostics_styleLints_enable: bool =    "false",
         /// List of warnings that should be displayed with hint severity.
         ///
         /// The warnings will be indicated by faded text or three dots in code
@@ -375,6 +377,9 @@ config_data! {
         /// How to render the size information in a memory layout hover.
         hover_memoryLayout_size: Option<MemoryLayoutHoverRenderKindDef> = "\"both\"",
 
+        /// How many associated items of a trait to display when hovering a trait.
+        hover_show_traitAssocItems: Option<usize> = "null",
+
         /// Whether to enforce the import granularity setting for all files. If set to false rust-analyzer will try to keep import styles consistent per file.
         imports_granularity_enforce: bool              = "false",
         /// How imports should be grouped into use statements.
@@ -518,7 +523,6 @@ config_data! {
         /// Exclude tests from find-all-references.
         references_excludeTests: bool = "false",
 
-
         /// Command to be executed instead of 'cargo' for runnables.
         runnables_command: Option<String> = "null",
         /// Additional arguments to be passed to cargo for runnables such as
@@ -1142,6 +1146,10 @@ impl Config {
         self.experimental("colorDiagnosticOutput")
     }
 
+    pub fn test_explorer(&self) -> bool {
+        self.experimental("testExplorer")
+    }
+
     pub fn publish_diagnostics(&self) -> bool {
         self.data.diagnostics_enable
     }
@@ -1160,6 +1168,7 @@ impl Config {
             insert_use: self.insert_use_config(),
             prefer_no_std: self.data.imports_preferNoStd,
             prefer_prelude: self.data.imports_preferPrelude,
+            style_lints: self.data.diagnostics_styleLints_enable,
         }
     }
 
@@ -1680,6 +1689,7 @@ impl Config {
                 }
             },
             keywords: self.data.hover_documentation_keywords_enable,
+            max_trait_assoc_items_count: self.data.hover_show_traitAssocItems,
         }
     }
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
index b2d507491b1..0e560e54eda 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/global_state.rs
@@ -7,8 +7,8 @@ use std::{collections::hash_map::Entry, time::Instant};
 
 use crossbeam_channel::{unbounded, Receiver, Sender};
 use flycheck::FlycheckHandle;
-use hir::Change;
-use ide::{Analysis, AnalysisHost, Cancellable, FileId};
+use hir::ChangeWithProcMacros;
+use ide::{Analysis, AnalysisHost, Cancellable, FileId, SourceRootId};
 use ide_db::base_db::{CrateId, ProcMacroPaths};
 use load_cargo::SourceRootConfig;
 use lsp_types::{SemanticTokens, Url};
@@ -66,6 +66,8 @@ pub(crate) struct GlobalState {
     pub(crate) diagnostics: DiagnosticCollection,
     pub(crate) mem_docs: MemDocs,
     pub(crate) source_root_config: SourceRootConfig,
+    /// A mapping that maps a local source root's `SourceRootId` to it parent's `SourceRootId`, if it has one.
+    pub(crate) local_roots_parent_map: FxHashMap<SourceRootId, SourceRootId>,
     pub(crate) semantic_tokens_cache: Arc<Mutex<FxHashMap<Url, SemanticTokens>>>,
 
     // status
@@ -83,6 +85,9 @@ pub(crate) struct GlobalState {
     pub(crate) flycheck_receiver: Receiver<flycheck::Message>,
     pub(crate) last_flycheck_error: Option<String>,
 
+    // Test explorer
+    pub(crate) test_run_session: Option<flycheck::CargoTestHandle>,
+
     // VFS
     pub(crate) loader: Handle<Box<dyn vfs::loader::Handle>, Receiver<vfs::loader::Message>>,
     pub(crate) vfs: Arc<RwLock<(vfs::Vfs, IntMap<FileId, LineEndings>)>>,
@@ -201,6 +206,7 @@ impl GlobalState {
             send_hint_refresh_query: false,
             last_reported_status: None,
             source_root_config: SourceRootConfig::default(),
+            local_roots_parent_map: FxHashMap::default(),
             config_errors: Default::default(),
 
             proc_macro_clients: Arc::from_iter([]),
@@ -212,6 +218,8 @@ impl GlobalState {
             flycheck_receiver,
             last_flycheck_error: None,
 
+            test_run_session: None,
+
             vfs: Arc::new(RwLock::new((vfs::Vfs::default(), IntMap::default()))),
             vfs_config_version: 0,
             vfs_progress_config_version: 0,
@@ -238,7 +246,7 @@ impl GlobalState {
 
         let mut file_changes = FxHashMap::<_, (bool, ChangedFile)>::default();
         let (change, modified_rust_files, workspace_structure_change) = {
-            let mut change = Change::new();
+            let mut change = ChangeWithProcMacros::new();
             let mut guard = self.vfs.write();
             let changed_files = guard.0.take_changes();
             if changed_files.is_empty() {
@@ -297,7 +305,7 @@ impl GlobalState {
             let mut bytes = vec![];
             let mut modified_rust_files = vec![];
             for file in changed_files {
-                let vfs_path = &vfs.file_path(file.file_id);
+                let vfs_path = vfs.file_path(file.file_id);
                 if let Some(path) = vfs_path.as_path() {
                     let path = path.to_path_buf();
                     if reload::should_refresh_for_change(&path, file.kind()) {
@@ -481,7 +489,7 @@ impl GlobalStateSnapshot {
     }
 
     pub(crate) fn anchored_path(&self, path: &AnchoredPathBuf) -> Url {
-        let mut base = self.vfs_read().file_path(path.anchor);
+        let mut base = self.vfs_read().file_path(path.anchor).clone();
         base.pop();
         let path = base.join(&path.path).unwrap();
         let path = path.as_path().unwrap();
@@ -489,7 +497,7 @@ impl GlobalStateSnapshot {
     }
 
     pub(crate) fn file_id_to_file_path(&self, file_id: FileId) -> vfs::VfsPath {
-        self.vfs_read().file_path(file_id)
+        self.vfs_read().file_path(file_id).clone()
     }
 
     pub(crate) fn cargo_target_for_crate_root(
@@ -497,7 +505,7 @@ impl GlobalStateSnapshot {
         crate_id: CrateId,
     ) -> Option<(&CargoWorkspace, Target)> {
         let file_id = self.analysis.crate_root(crate_id).ok()?;
-        let path = self.vfs_read().file_path(file_id);
+        let path = self.vfs_read().file_path(file_id).clone();
         let path = path.as_path()?;
         self.workspaces.iter().find_map(|ws| match ws {
             ProjectWorkspace::Cargo { cargo, .. } => {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/hack_recover_crate_name.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/hack_recover_crate_name.rs
new file mode 100644
index 00000000000..d7285653c5f
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/hack_recover_crate_name.rs
@@ -0,0 +1,25 @@
+//! Currently cargo does not emit crate name in the `cargo test --format=json`, which needs to be changed. This
+//! module contains a way to recover crate names in a very hacky and wrong way.
+
+// FIXME(hack_recover_crate_name): Remove this module.
+
+use std::sync::{Mutex, MutexGuard, OnceLock};
+
+use ide_db::FxHashMap;
+
+static STORAGE: OnceLock<Mutex<FxHashMap<String, String>>> = OnceLock::new();
+
+fn get_storage() -> MutexGuard<'static, FxHashMap<String, String>> {
+    STORAGE.get_or_init(|| Mutex::new(FxHashMap::default())).lock().unwrap()
+}
+
+pub(crate) fn insert_name(name_with_crate: String) {
+    let Some((_, name_without_crate)) = name_with_crate.split_once("::") else {
+        return;
+    };
+    get_storage().insert(name_without_crate.to_owned(), name_with_crate);
+}
+
+pub(crate) fn lookup_name(name_without_crate: String) -> Option<String> {
+    get_storage().get(&name_without_crate).cloned()
+}
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs
index cf646a2e282..ff213748b4f 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/notification.rs
@@ -16,7 +16,7 @@ use crate::{
     config::Config,
     global_state::GlobalState,
     lsp::{from_proto, utils::apply_document_changes},
-    lsp_ext::RunFlycheckParams,
+    lsp_ext::{self, RunFlycheckParams},
     mem_docs::DocumentData,
     reload,
 };
@@ -373,3 +373,10 @@ pub(crate) fn handle_run_flycheck(
     }
     Ok(())
 }
+
+pub(crate) fn handle_abort_run_test(state: &mut GlobalState, _: ()) -> anyhow::Result<()> {
+    if state.test_run_session.take().is_some() {
+        state.send_notification::<lsp_ext::EndRunTest>(());
+    }
+    Ok(())
+}
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
index 04a04395429..1d98457add3 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/handlers/request.rs
@@ -39,6 +39,7 @@ use crate::{
     config::{Config, RustfmtConfig, WorkspaceSymbolConfig},
     diff::diff,
     global_state::{GlobalState, GlobalStateSnapshot},
+    hack_recover_crate_name,
     line_index::LineEndings,
     lsp::{
         from_proto, to_proto,
@@ -192,6 +193,70 @@ pub(crate) fn handle_view_item_tree(
     Ok(res)
 }
 
+pub(crate) fn handle_run_test(
+    state: &mut GlobalState,
+    params: lsp_ext::RunTestParams,
+) -> anyhow::Result<()> {
+    if let Some(_session) = state.test_run_session.take() {
+        state.send_notification::<lsp_ext::EndRunTest>(());
+    }
+    // We detect the lowest common ansector of all included tests, and
+    // run it. We ignore excluded tests for now, the client will handle
+    // it for us.
+    let lca = match params.include {
+        Some(tests) => tests
+            .into_iter()
+            .reduce(|x, y| {
+                let mut common_prefix = "".to_owned();
+                for (xc, yc) in x.chars().zip(y.chars()) {
+                    if xc != yc {
+                        break;
+                    }
+                    common_prefix.push(xc);
+                }
+                common_prefix
+            })
+            .unwrap_or_default(),
+        None => "".to_owned(),
+    };
+    let handle = if lca.is_empty() {
+        flycheck::CargoTestHandle::new(None)
+    } else if let Some((_, path)) = lca.split_once("::") {
+        flycheck::CargoTestHandle::new(Some(path))
+    } else {
+        flycheck::CargoTestHandle::new(None)
+    };
+    state.test_run_session = Some(handle?);
+    Ok(())
+}
+
+pub(crate) fn handle_discover_test(
+    snap: GlobalStateSnapshot,
+    params: lsp_ext::DiscoverTestParams,
+) -> anyhow::Result<lsp_ext::DiscoverTestResults> {
+    let _p = tracing::span!(tracing::Level::INFO, "handle_discover_test").entered();
+    let (tests, scope) = match params.test_id {
+        Some(id) => {
+            let crate_id = id.split_once("::").map(|it| it.0).unwrap_or(&id);
+            (snap.analysis.discover_tests_in_crate_by_test_id(crate_id)?, vec![crate_id.to_owned()])
+        }
+        None => (snap.analysis.discover_test_roots()?, vec![]),
+    };
+    for t in &tests {
+        hack_recover_crate_name::insert_name(t.id.clone());
+    }
+    Ok(lsp_ext::DiscoverTestResults {
+        tests: tests
+            .into_iter()
+            .map(|t| {
+                let line_index = t.file.and_then(|f| snap.file_line_index(f).ok());
+                to_proto::test_item(&snap, t, line_index.as_ref())
+            })
+            .collect(),
+        scope,
+    })
+}
+
 pub(crate) fn handle_view_crate_graph(
     snap: GlobalStateSnapshot,
     params: ViewCrateGraphParams,
@@ -1937,7 +2002,7 @@ fn run_rustfmt(
     let mut command = match snap.config.rustfmt() {
         RustfmtConfig::Rustfmt { extra_args, enable_range_formatting } => {
             // FIXME: Set RUSTUP_TOOLCHAIN
-            let mut cmd = process::Command::new(toolchain::rustfmt());
+            let mut cmd = process::Command::new(toolchain::Tool::Rustfmt.path());
             cmd.envs(snap.config.extra_env());
             cmd.args(extra_args);
 
@@ -2097,7 +2162,7 @@ pub(crate) fn fetch_dependency_list(
         .into_iter()
         .filter_map(|it| {
             let root_file_path = state.file_id_to_file_path(it.root_file_id);
-            crate_path(root_file_path).and_then(to_url).map(|path| CrateInfoResult {
+            crate_path(&root_file_path).and_then(to_url).map(|path| CrateInfoResult {
                 name: it.name,
                 version: it.version,
                 path,
@@ -2118,7 +2183,7 @@ pub(crate) fn fetch_dependency_list(
 /// An `Option` value representing the path to the directory of the crate with the given
 /// name, if such a crate is found. If no crate with the given name is found, this function
 /// returns `None`.
-fn crate_path(root_file_path: VfsPath) -> Option<VfsPath> {
+fn crate_path(root_file_path: &VfsPath) -> Option<VfsPath> {
     let mut current_dir = root_file_path.parent();
     while let Some(path) = current_dir {
         let cargo_toml_path = path.join("../Cargo.toml")?;
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs
index 9d692175203..3bba4847f92 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/integrated_benchmarks.rs
@@ -10,8 +10,10 @@
 //! in release mode in VS Code. There's however "rust-analyzer: Copy Run Command Line"
 //! which you can use to paste the command in terminal and add `--release` manually.
 
-use hir::Change;
-use ide::{AnalysisHost, CallableSnippets, CompletionConfig, FilePosition, TextSize};
+use hir::ChangeWithProcMacros;
+use ide::{
+    AnalysisHost, CallableSnippets, CompletionConfig, DiagnosticsConfig, FilePosition, TextSize,
+};
 use ide_db::{
     imports::insert_use::{ImportGranularity, InsertUseConfig},
     SnippetCap,
@@ -55,23 +57,25 @@ fn integrated_highlighting_benchmark() {
         vfs.file_id(&path).unwrap_or_else(|| panic!("can't find virtual file for {path}"))
     };
 
+    let _g = crate::tracing::hprof::init("*>150");
+
     {
         let _it = stdx::timeit("initial");
         let analysis = host.analysis();
         analysis.highlight_as_html(file_id, false).unwrap();
     }
 
-    crate::tracing::hprof::init("*>100");
-
     {
         let _it = stdx::timeit("change");
         let mut text = host.analysis().file_text(file_id).unwrap().to_string();
         text.push_str("\npub fn _dummy() {}\n");
-        let mut change = Change::new();
+        let mut change = ChangeWithProcMacros::new();
         change.change_file(file_id, Some(Arc::from(text)));
         host.apply_change(change);
     }
 
+    let _g = crate::tracing::hprof::init("*>50");
+
     {
         let _it = stdx::timeit("after change");
         let _span = profile::cpu_span();
@@ -120,7 +124,7 @@ fn integrated_completion_benchmark() {
         let completion_offset =
             patch(&mut text, "db.struct_data(self.id)", "sel;\ndb.struct_data(self.id)")
                 + "sel".len();
-        let mut change = Change::new();
+        let mut change = ChangeWithProcMacros::new();
         change.change_file(file_id, Some(Arc::from(text)));
         host.apply_change(change);
         completion_offset
@@ -155,7 +159,7 @@ fn integrated_completion_benchmark() {
         analysis.completions(&config, position, None).unwrap();
     }
 
-    crate::tracing::hprof::init("*>5");
+    let _g = crate::tracing::hprof::init("*");
 
     let completion_offset = {
         let _it = stdx::timeit("change");
@@ -163,7 +167,7 @@ fn integrated_completion_benchmark() {
         let completion_offset =
             patch(&mut text, "sel;\ndb.struct_data(self.id)", ";sel;\ndb.struct_data(self.id)")
                 + ";sel".len();
-        let mut change = Change::new();
+        let mut change = ChangeWithProcMacros::new();
         change.change_file(file_id, Some(Arc::from(text)));
         host.apply_change(change);
         completion_offset
@@ -205,7 +209,7 @@ fn integrated_completion_benchmark() {
         let completion_offset =
             patch(&mut text, "sel;\ndb.struct_data(self.id)", "self.;\ndb.struct_data(self.id)")
                 + "self.".len();
-        let mut change = Change::new();
+        let mut change = ChangeWithProcMacros::new();
         change.change_file(file_id, Some(Arc::from(text)));
         host.apply_change(change);
         completion_offset
@@ -242,6 +246,80 @@ fn integrated_completion_benchmark() {
     }
 }
 
+#[test]
+fn integrated_diagnostics_benchmark() {
+    if std::env::var("RUN_SLOW_BENCHES").is_err() {
+        return;
+    }
+
+    // Load rust-analyzer itself.
+    let workspace_to_load = project_root();
+    let file = "./crates/hir/src/lib.rs";
+
+    let cargo_config = CargoConfig {
+        sysroot: Some(project_model::RustLibSource::Discover),
+        ..CargoConfig::default()
+    };
+    let load_cargo_config = LoadCargoConfig {
+        load_out_dirs_from_check: true,
+        with_proc_macro_server: ProcMacroServerChoice::None,
+        prefill_caches: true,
+    };
+
+    let (db, vfs, _proc_macro) = {
+        let _it = stdx::timeit("workspace loading");
+        load_workspace_at(&workspace_to_load, &cargo_config, &load_cargo_config, &|_| {}).unwrap()
+    };
+    let mut host = AnalysisHost::with_database(db);
+
+    let file_id = {
+        let file = workspace_to_load.join(file);
+        let path = VfsPath::from(AbsPathBuf::assert(file));
+        vfs.file_id(&path).unwrap_or_else(|| panic!("can't find virtual file for {path}"))
+    };
+
+    let diagnostics_config = DiagnosticsConfig {
+        enabled: false,
+        proc_macros_enabled: true,
+        proc_attr_macros_enabled: true,
+        disable_experimental: true,
+        disabled: Default::default(),
+        expr_fill_default: Default::default(),
+        style_lints: false,
+        insert_use: InsertUseConfig {
+            granularity: ImportGranularity::Crate,
+            enforce_granularity: false,
+            prefix_kind: hir::PrefixKind::ByCrate,
+            group: true,
+            skip_glob_imports: true,
+        },
+        prefer_no_std: false,
+        prefer_prelude: false,
+    };
+    host.analysis()
+        .diagnostics(&diagnostics_config, ide::AssistResolveStrategy::None, file_id)
+        .unwrap();
+
+    let _g = crate::tracing::hprof::init("*>1");
+
+    {
+        let _it = stdx::timeit("change");
+        let mut text = host.analysis().file_text(file_id).unwrap().to_string();
+        patch(&mut text, "db.struct_data(self.id)", "();\ndb.struct_data(self.id)");
+        let mut change = ChangeWithProcMacros::new();
+        change.change_file(file_id, Some(Arc::from(text)));
+        host.apply_change(change);
+    };
+
+    {
+        let _p = tracing::span!(tracing::Level::INFO, "diagnostics").entered();
+        let _span = profile::cpu_span();
+        host.analysis()
+            .diagnostics(&diagnostics_config, ide::AssistResolveStrategy::None, file_id)
+            .unwrap();
+    }
+}
+
 fn patch(what: &mut String, from: &str, to: &str) -> usize {
     let idx = what.find(from).unwrap();
     *what = what.replacen(from, to, 1);
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs
index 473ca991ad9..175ffa622ff 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lib.rs
@@ -19,6 +19,7 @@ mod diagnostics;
 mod diff;
 mod dispatch;
 mod global_state;
+mod hack_recover_crate_name;
 mod line_index;
 mod main_loop;
 mod mem_docs;
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
index aa40728ce6c..86ab652f8ef 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/ext.rs
@@ -163,6 +163,108 @@ impl Request for ViewItemTree {
     const METHOD: &'static str = "rust-analyzer/viewItemTree";
 }
 
+#[derive(Deserialize, Serialize, Debug)]
+#[serde(rename_all = "camelCase")]
+pub struct DiscoverTestParams {
+    pub test_id: Option<String>,
+}
+
+#[derive(Deserialize, Serialize, Debug)]
+#[serde(rename_all = "camelCase")]
+pub enum TestItemKind {
+    Package,
+    Module,
+    Test,
+}
+
+#[derive(Deserialize, Serialize, Debug)]
+#[serde(rename_all = "camelCase")]
+pub struct TestItem {
+    pub id: String,
+    pub label: String,
+    pub kind: TestItemKind,
+    pub can_resolve_children: bool,
+    pub parent: Option<String>,
+    pub text_document: Option<TextDocumentIdentifier>,
+    pub range: Option<Range>,
+    pub runnable: Option<Runnable>,
+}
+
+#[derive(Deserialize, Serialize, Debug)]
+#[serde(rename_all = "camelCase")]
+pub struct DiscoverTestResults {
+    pub tests: Vec<TestItem>,
+    pub scope: Vec<String>,
+}
+
+pub enum DiscoverTest {}
+
+impl Request for DiscoverTest {
+    type Params = DiscoverTestParams;
+    type Result = DiscoverTestResults;
+    const METHOD: &'static str = "experimental/discoverTest";
+}
+
+pub enum DiscoveredTests {}
+
+impl Notification for DiscoveredTests {
+    type Params = DiscoverTestResults;
+    const METHOD: &'static str = "experimental/discoveredTests";
+}
+
+#[derive(Deserialize, Serialize, Debug)]
+#[serde(rename_all = "camelCase")]
+pub struct RunTestParams {
+    pub include: Option<Vec<String>>,
+    pub exclude: Option<Vec<String>>,
+}
+
+pub enum RunTest {}
+
+impl Request for RunTest {
+    type Params = RunTestParams;
+    type Result = ();
+    const METHOD: &'static str = "experimental/runTest";
+}
+
+pub enum EndRunTest {}
+
+impl Notification for EndRunTest {
+    type Params = ();
+    const METHOD: &'static str = "experimental/endRunTest";
+}
+
+pub enum AbortRunTest {}
+
+impl Notification for AbortRunTest {
+    type Params = ();
+    const METHOD: &'static str = "experimental/abortRunTest";
+}
+
+#[derive(Deserialize, Serialize, Debug)]
+#[serde(rename_all = "camelCase", tag = "tag")]
+pub enum TestState {
+    Passed,
+    Failed { message: String },
+    Skipped,
+    Started,
+    Enqueued,
+}
+
+#[derive(Deserialize, Serialize, Debug)]
+#[serde(rename_all = "camelCase")]
+pub struct ChangeTestStateParams {
+    pub test_id: String,
+    pub state: TestState,
+}
+
+pub enum ChangeTestState {}
+
+impl Notification for ChangeTestState {
+    type Params = ChangeTestStateParams;
+    const METHOD: &'static str = "experimental/changeTestState";
+}
+
 pub enum ExpandMacro {}
 
 impl Request for ExpandMacro {
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
index 481ebfefd4e..e2b55f4a5c5 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/lsp/to_proto.rs
@@ -1498,6 +1498,32 @@ pub(crate) fn code_lens(
     Ok(())
 }
 
+pub(crate) fn test_item(
+    snap: &GlobalStateSnapshot,
+    test_item: ide::TestItem,
+    line_index: Option<&LineIndex>,
+) -> lsp_ext::TestItem {
+    lsp_ext::TestItem {
+        id: test_item.id,
+        label: test_item.label,
+        kind: match test_item.kind {
+            ide::TestItemKind::Crate => lsp_ext::TestItemKind::Package,
+            ide::TestItemKind::Module => lsp_ext::TestItemKind::Module,
+            ide::TestItemKind::Function => lsp_ext::TestItemKind::Test,
+        },
+        can_resolve_children: matches!(
+            test_item.kind,
+            ide::TestItemKind::Crate | ide::TestItemKind::Module
+        ),
+        parent: test_item.parent,
+        text_document: test_item
+            .file
+            .map(|f| lsp_types::TextDocumentIdentifier { uri: url(snap, f) }),
+        range: line_index.and_then(|l| Some(range(l, test_item.text_range?))),
+        runnable: test_item.runnable.and_then(|r| runnable(snap, r).ok()),
+    }
+}
+
 pub(crate) mod command {
     use ide::{FileRange, NavigationTarget};
     use serde_json::to_value;
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
index 72f6d0fde5f..bca6db19dcf 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/main_loop.rs
@@ -1,14 +1,15 @@
 //! The main loop of `rust-analyzer` responsible for dispatching LSP
 //! requests/replies and notifications back to the client.
-use crate::lsp::ext;
+
 use std::{
     fmt,
     time::{Duration, Instant},
 };
 
 use always_assert::always;
-use crossbeam_channel::{select, Receiver};
+use crossbeam_channel::{never, select, Receiver};
 use ide_db::base_db::{SourceDatabase, SourceDatabaseExt, VfsPath};
+use itertools::Itertools;
 use lsp_server::{Connection, Notification, Request};
 use lsp_types::notification::Notification as _;
 use stdx::thread::ThreadIntent;
@@ -19,8 +20,9 @@ use crate::{
     diagnostics::fetch_native_diagnostics,
     dispatch::{NotificationDispatcher, RequestDispatcher},
     global_state::{file_id_to_url, url_to_file_id, GlobalState},
+    hack_recover_crate_name,
     lsp::{
-        from_proto,
+        from_proto, to_proto,
         utils::{notification_is, Progress},
     },
     lsp_ext,
@@ -58,6 +60,7 @@ enum Event {
     QueuedTask(QueuedTask),
     Vfs(vfs::loader::Message),
     Flycheck(flycheck::Message),
+    TestResult(flycheck::CargoTestMessage),
 }
 
 impl fmt::Display for Event {
@@ -68,6 +71,7 @@ impl fmt::Display for Event {
             Event::Vfs(_) => write!(f, "Event::Vfs"),
             Event::Flycheck(_) => write!(f, "Event::Flycheck"),
             Event::QueuedTask(_) => write!(f, "Event::QueuedTask"),
+            Event::TestResult(_) => write!(f, "Event::TestResult"),
         }
     }
 }
@@ -81,9 +85,10 @@ pub(crate) enum QueuedTask {
 #[derive(Debug)]
 pub(crate) enum Task {
     Response(lsp_server::Response),
-    ClientNotification(ext::UnindexedProjectParams),
+    ClientNotification(lsp_ext::UnindexedProjectParams),
     Retry(lsp_server::Request),
     Diagnostics(Vec<(FileId, Vec<lsp_types::Diagnostic>)>),
+    DiscoverTest(lsp_ext::DiscoverTestResults),
     PrimeCaches(PrimeCachesProgress),
     FetchWorkspace(ProjectWorkspaceProgress),
     FetchBuildData(BuildDataProgress),
@@ -127,6 +132,7 @@ impl fmt::Debug for Event {
             Event::QueuedTask(it) => fmt::Debug::fmt(it, f),
             Event::Vfs(it) => fmt::Debug::fmt(it, f),
             Event::Flycheck(it) => fmt::Debug::fmt(it, f),
+            Event::TestResult(it) => fmt::Debug::fmt(it, f),
         }
     }
 }
@@ -214,6 +220,10 @@ impl GlobalState {
 
             recv(self.flycheck_receiver) -> task =>
                 Some(Event::Flycheck(task.unwrap())),
+
+            recv(self.test_run_session.as_ref().map(|s| s.receiver()).unwrap_or(&never())) -> task =>
+                Some(Event::TestResult(task.unwrap())),
+
         }
     }
 
@@ -322,6 +332,18 @@ impl GlobalState {
                     self.handle_flycheck_msg(message);
                 }
             }
+            Event::TestResult(message) => {
+                let _p =
+                    tracing::span!(tracing::Level::INFO, "GlobalState::handle_event/test_result")
+                        .entered();
+                self.handle_cargo_test_msg(message);
+                // Coalesce many test result event into a single loop turn
+                while let Some(message) =
+                    self.test_run_session.as_ref().and_then(|r| r.receiver().try_recv().ok())
+                {
+                    self.handle_cargo_test_msg(message);
+                }
+            }
         }
         let event_handling_duration = loop_start.elapsed();
 
@@ -364,10 +386,12 @@ impl GlobalState {
                 }
             }
 
-            let update_diagnostics = (!was_quiescent || state_changed || memdocs_added_or_removed)
-                && self.config.publish_diagnostics();
-            if update_diagnostics {
-                self.update_diagnostics()
+            let things_changed = !was_quiescent || state_changed || memdocs_added_or_removed;
+            if things_changed && self.config.publish_diagnostics() {
+                self.update_diagnostics();
+            }
+            if things_changed && self.config.test_explorer() {
+                self.update_tests();
             }
         }
 
@@ -488,6 +512,55 @@ impl GlobalState {
         });
     }
 
+    fn update_tests(&mut self) {
+        let db = self.analysis_host.raw_database();
+        let subscriptions = self
+            .mem_docs
+            .iter()
+            .map(|path| self.vfs.read().0.file_id(path).unwrap())
+            .filter(|&file_id| {
+                let source_root = db.file_source_root(file_id);
+                !db.source_root(source_root).is_library
+            })
+            .collect::<Vec<_>>();
+        tracing::trace!("updating tests for {:?}", subscriptions);
+
+        // Updating tests are triggered by the user typing
+        // so we run them on a latency sensitive thread.
+        self.task_pool.handle.spawn(ThreadIntent::LatencySensitive, {
+            let snapshot = self.snapshot();
+            move || {
+                let tests = subscriptions
+                    .into_iter()
+                    .filter_map(|f| snapshot.analysis.crates_for(f).ok())
+                    .flatten()
+                    .unique()
+                    .filter_map(|c| snapshot.analysis.discover_tests_in_crate(c).ok())
+                    .flatten()
+                    .collect::<Vec<_>>();
+                for t in &tests {
+                    hack_recover_crate_name::insert_name(t.id.clone());
+                }
+                let scope = tests
+                    .iter()
+                    .filter_map(|t| Some(t.id.split_once("::")?.0))
+                    .unique()
+                    .map(|it| it.to_owned())
+                    .collect();
+                Task::DiscoverTest(lsp_ext::DiscoverTestResults {
+                    tests: tests
+                        .into_iter()
+                        .map(|t| {
+                            let line_index = t.file.and_then(|f| snapshot.file_line_index(f).ok());
+                            to_proto::test_item(&snapshot, t, line_index.as_ref())
+                        })
+                        .collect(),
+                    scope,
+                })
+            }
+        });
+    }
+
     fn update_status_or_notify(&mut self) {
         let status = self.current_status();
         if self.last_reported_status.as_ref() != Some(&status) {
@@ -598,6 +671,9 @@ impl GlobalState {
                 }
             }
             Task::BuildDepsHaveChanged => self.build_deps_changed = true,
+            Task::DiscoverTest(tests) => {
+                self.send_notification::<lsp_ext::DiscoveredTests>(tests);
+            }
         }
     }
 
@@ -666,7 +742,7 @@ impl GlobalState {
                     let id = from_proto::file_id(&snap, &uri).expect("unable to get FileId");
                     if let Ok(crates) = &snap.analysis.crates_for(id) {
                         if crates.is_empty() {
-                            let params = ext::UnindexedProjectParams {
+                            let params = lsp_ext::UnindexedProjectParams {
                                 text_documents: vec![lsp_types::TextDocumentIdentifier { uri }],
                             };
                             sender.send(Task::ClientNotification(params)).unwrap();
@@ -698,6 +774,32 @@ impl GlobalState {
         }
     }
 
+    fn handle_cargo_test_msg(&mut self, message: flycheck::CargoTestMessage) {
+        match message {
+            flycheck::CargoTestMessage::Test { name, state } => {
+                let state = match state {
+                    flycheck::TestState::Started => lsp_ext::TestState::Started,
+                    flycheck::TestState::Ignored => lsp_ext::TestState::Skipped,
+                    flycheck::TestState::Ok => lsp_ext::TestState::Passed,
+                    flycheck::TestState::Failed { stdout } => {
+                        lsp_ext::TestState::Failed { message: stdout }
+                    }
+                };
+                let Some(test_id) = hack_recover_crate_name::lookup_name(name) else {
+                    return;
+                };
+                self.send_notification::<lsp_ext::ChangeTestState>(
+                    lsp_ext::ChangeTestStateParams { test_id, state },
+                );
+            }
+            flycheck::CargoTestMessage::Suite => (),
+            flycheck::CargoTestMessage::Finished => {
+                self.send_notification::<lsp_ext::EndRunTest>(());
+                self.test_run_session = None;
+            }
+        }
+    }
+
     fn handle_flycheck_msg(&mut self, message: flycheck::Message) {
         match message {
             flycheck::Message::AddDiagnostic { id, workspace_root, diagnostic } => {
@@ -803,6 +905,7 @@ impl GlobalState {
             .on_sync_mut::<lsp_ext::RebuildProcMacros>(handlers::handle_proc_macros_rebuild)
             .on_sync_mut::<lsp_ext::MemoryUsage>(handlers::handle_memory_usage)
             .on_sync_mut::<lsp_ext::ShuffleCrateGraph>(handlers::handle_shuffle_crate_graph)
+            .on_sync_mut::<lsp_ext::RunTest>(handlers::handle_run_test)
             // Request handlers which are related to the user typing
             // are run on the main thread to reduce latency:
             .on_sync::<lsp_ext::JoinLines>(handlers::handle_join_lines)
@@ -843,6 +946,7 @@ impl GlobalState {
             .on::<lsp_ext::ViewFileText>(handlers::handle_view_file_text)
             .on::<lsp_ext::ViewCrateGraph>(handlers::handle_view_crate_graph)
             .on::<lsp_ext::ViewItemTree>(handlers::handle_view_item_tree)
+            .on::<lsp_ext::DiscoverTest>(handlers::handle_discover_test)
             .on::<lsp_ext::ExpandMacro>(handlers::handle_expand_macro)
             .on::<lsp_ext::ParentModule>(handlers::handle_parent_module)
             .on::<lsp_ext::Runnables>(handlers::handle_runnables)
@@ -906,6 +1010,7 @@ impl GlobalState {
             .on_sync_mut::<lsp_ext::CancelFlycheck>(handlers::handle_cancel_flycheck)?
             .on_sync_mut::<lsp_ext::ClearFlycheck>(handlers::handle_clear_flycheck)?
             .on_sync_mut::<lsp_ext::RunFlycheck>(handlers::handle_run_flycheck)?
+            .on_sync_mut::<lsp_ext::AbortRunTest>(handlers::handle_abort_run_test)?
             .finish();
         Ok(())
     }
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
index f6bc032c019..c2725e1fad9 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
@@ -16,7 +16,7 @@
 use std::{iter, mem};
 
 use flycheck::{FlycheckConfig, FlycheckHandle};
-use hir::{db::DefDatabase, Change, ProcMacros};
+use hir::{db::DefDatabase, ChangeWithProcMacros, ProcMacros};
 use ide::CrateId;
 use ide_db::{
     base_db::{salsa::Durability, CrateGraph, ProcMacroPaths, Version},
@@ -357,7 +357,7 @@ impl GlobalState {
     }
 
     pub(crate) fn set_proc_macros(&mut self, proc_macros: ProcMacros) {
-        let mut change = Change::new();
+        let mut change = ChangeWithProcMacros::new();
         change.set_proc_macros(proc_macros);
         self.analysis_host.apply_change(change);
     }
@@ -515,6 +515,7 @@ impl GlobalState {
             version: self.vfs_config_version,
         });
         self.source_root_config = project_folders.source_root_config;
+        self.local_roots_parent_map = self.source_root_config.source_root_parent_map();
 
         self.recreate_crate_graph(cause);
 
@@ -548,7 +549,7 @@ impl GlobalState {
 
             ws_to_crate_graph(&self.workspaces, self.config.extra_env(), load)
         };
-        let mut change = Change::new();
+        let mut change = ChangeWithProcMacros::new();
         if self.config.expand_proc_macros() {
             change.set_proc_macros(
                 crate_graph
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/config.rs
index fcdbd1e6d9b..f77d9893304 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/config.rs
@@ -4,13 +4,10 @@
 use std::io;
 
 use anyhow::Context;
-use tracing::{level_filters::LevelFilter, Level};
+use tracing::level_filters::LevelFilter;
 use tracing_subscriber::{
-    filter::{self, Targets},
-    fmt::{format::FmtSpan, MakeWriter},
-    layer::SubscriberExt,
-    util::SubscriberInitExt,
-    Layer, Registry,
+    filter::Targets, fmt::MakeWriter, layer::SubscriberExt, util::SubscriberInitExt, Layer,
+    Registry,
 };
 use tracing_tree::HierarchicalLayer;
 
@@ -50,10 +47,7 @@ where
 
         let writer = self.writer;
 
-        let ra_fmt_layer = tracing_subscriber::fmt::layer()
-            .with_span_events(FmtSpan::CLOSE)
-            .with_writer(writer)
-            .with_filter(filter);
+        let ra_fmt_layer = tracing_subscriber::fmt::layer().with_writer(writer).with_filter(filter);
 
         let mut chalk_layer = None;
         if let Some(chalk_filter) = self.chalk_filter {
@@ -74,32 +68,7 @@ where
             );
         };
 
-        let mut profiler_layer = None;
-        if let Some(spec) = self.profile_filter {
-            let (write_filter, allowed_names) = hprof::WriteFilter::from_spec(&spec);
-
-            // this filter the first pass for `tracing`: these are all the "profiling" spans, but things like
-            // span depth or duration are not filtered here: that only occurs at write time.
-            let profile_filter = filter::filter_fn(move |metadata| {
-                let allowed = match &allowed_names {
-                    Some(names) => names.contains(metadata.name()),
-                    None => true,
-                };
-
-                metadata.is_span()
-                    && allowed
-                    && metadata.level() >= &Level::INFO
-                    && !metadata.target().starts_with("salsa")
-                    && !metadata.target().starts_with("chalk")
-            });
-
-            let layer = hprof::SpanTree::default()
-                .aggregate(true)
-                .spec_filter(write_filter)
-                .with_filter(profile_filter);
-
-            profiler_layer = Some(layer);
-        }
+        let profiler_layer = self.profile_filter.map(|spec| hprof::layer(&spec));
 
         Registry::default().with(ra_fmt_layer).with(chalk_layer).with(profiler_layer).try_init()?;
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/hprof.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/hprof.rs
index 90649873297..73f94671f2d 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/hprof.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/tracing/hprof.rs
@@ -52,7 +52,15 @@ use tracing_subscriber::{
 
 use crate::tracing::hprof;
 
-pub fn init(spec: &str) {
+pub fn init(spec: &str) -> tracing::subscriber::DefaultGuard {
+    let subscriber = Registry::default().with(layer(spec));
+    tracing::subscriber::set_default(subscriber)
+}
+
+pub fn layer<S>(spec: &str) -> impl Layer<S>
+where
+    S: Subscriber + for<'span> tracing_subscriber::registry::LookupSpan<'span>,
+{
     let (write_filter, allowed_names) = WriteFilter::from_spec(spec);
 
     // this filter the first pass for `tracing`: these are all the "profiling" spans, but things like
@@ -63,20 +71,15 @@ pub fn init(spec: &str) {
             None => true,
         };
 
-        metadata.is_span()
-            && allowed
+        allowed
+            && metadata.is_span()
             && metadata.level() >= &Level::INFO
             && !metadata.target().starts_with("salsa")
+            && metadata.name() != "compute_exhaustiveness_and_usefulness"
             && !metadata.target().starts_with("chalk")
     });
 
-    let layer = hprof::SpanTree::default()
-        .aggregate(true)
-        .spec_filter(write_filter)
-        .with_filter(profile_filter);
-
-    let subscriber = Registry::default().with(layer);
-    tracing::subscriber::set_global_default(subscriber).unwrap();
+    hprof::SpanTree::default().aggregate(true).spec_filter(write_filter).with_filter(profile_filter)
 }
 
 #[derive(Default, Debug)]
diff --git a/src/tools/rust-analyzer/crates/salsa/Cargo.toml b/src/tools/rust-analyzer/crates/salsa/Cargo.toml
index 9eec21f6a15..0d3e1197b5c 100644
--- a/src/tools/rust-analyzer/crates/salsa/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/salsa/Cargo.toml
@@ -28,7 +28,6 @@ salsa-macros = { version = "0.0.0", path = "salsa-macros" }
 [dev-dependencies]
 linked-hash-map = "0.5.6"
 rand = "0.8.5"
-test-log = "0.2.14"
 expect-test = "1.4.0"
 dissimilar = "1.0.7"
 
diff --git a/src/tools/rust-analyzer/crates/salsa/salsa-macros/src/query_group.rs b/src/tools/rust-analyzer/crates/salsa/salsa-macros/src/query_group.rs
index a868d920b66..5983765eec7 100644
--- a/src/tools/rust-analyzer/crates/salsa/salsa-macros/src/query_group.rs
+++ b/src/tools/rust-analyzer/crates/salsa/salsa-macros/src/query_group.rs
@@ -235,13 +235,24 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
 
         queries_with_storage.push(fn_name);
 
+        let tracing = if let QueryStorage::Memoized = query.storage {
+            let s = format!("{trait_name}::{fn_name}");
+            Some(quote! {
+                let _p = tracing::span!(tracing::Level::DEBUG, #s, #(#key_names = tracing::field::debug(&#key_names)),*).entered();
+            })
+        } else {
+            None
+        }
+        .into_iter();
+
         query_fn_definitions.extend(quote! {
             fn #fn_name(&self, #(#key_names: #keys),*) -> #value {
+                #(#tracing),*
                 // Create a shim to force the code to be monomorphized in the
                 // query crate. Our experiments revealed that this makes a big
                 // difference in total compilation time in rust-analyzer, though
                 // it's not totally obvious why that should be.
-                fn __shim(db: &(dyn #trait_name + '_),  #(#key_names: #keys),*) -> #value {
+                fn __shim(db: &(dyn #trait_name + '_), #(#key_names: #keys),*) -> #value {
                     salsa::plumbing::get_query_table::<#qt>(db).get((#(#key_names),*))
                 }
                 __shim(self, #(#key_names),*)
diff --git a/src/tools/rust-analyzer/crates/salsa/src/derived.rs b/src/tools/rust-analyzer/crates/salsa/src/derived.rs
index 153df999f53..3b5bd7f9e3b 100644
--- a/src/tools/rust-analyzer/crates/salsa/src/derived.rs
+++ b/src/tools/rust-analyzer/crates/salsa/src/derived.rs
@@ -136,7 +136,7 @@ where
     ) -> std::fmt::Result {
         let slot_map = self.slot_map.read();
         let key = slot_map.get_index(index as usize).unwrap().0;
-        write!(fmt, "{}({:?})", Q::QUERY_NAME, key)
+        write!(fmt, "{}::{}({:?})", std::any::type_name::<Q>(), Q::QUERY_NAME, key)
     }
 
     fn maybe_changed_after(
@@ -146,13 +146,13 @@ where
         revision: Revision,
     ) -> bool {
         debug_assert!(revision < db.salsa_runtime().current_revision());
-        let read = self.slot_map.read();
-        let Some((key, slot)) = read.get_index(index as usize) else {
-            return false;
+        let (key, slot) = {
+            let read = self.slot_map.read();
+            let Some((key, slot)) = read.get_index(index as usize) else {
+                return false;
+            };
+            (key.clone(), slot.clone())
         };
-        let (key, slot) = (key.clone(), slot.clone());
-        // note: this drop is load-bearing. removing it would causes deadlocks.
-        drop(read);
         slot.maybe_changed_after(db, revision, &key)
     }
 
diff --git a/src/tools/rust-analyzer/crates/salsa/src/runtime.rs b/src/tools/rust-analyzer/crates/salsa/src/runtime.rs
index a7d5a245782..e11cabfe11e 100644
--- a/src/tools/rust-analyzer/crates/salsa/src/runtime.rs
+++ b/src/tools/rust-analyzer/crates/salsa/src/runtime.rs
@@ -595,7 +595,7 @@ impl ActiveQuery {
     fn remove_cycle_participants(&mut self, cycle: &Cycle) {
         if let Some(my_dependencies) = &mut self.dependencies {
             for p in cycle.participant_keys() {
-                my_dependencies.remove(&p);
+                my_dependencies.swap_remove(&p);
             }
         }
     }
diff --git a/src/tools/rust-analyzer/crates/salsa/tests/cycles.rs b/src/tools/rust-analyzer/crates/salsa/tests/cycles.rs
index 00ca5332440..ea5d15a250f 100644
--- a/src/tools/rust-analyzer/crates/salsa/tests/cycles.rs
+++ b/src/tools/rust-analyzer/crates/salsa/tests/cycles.rs
@@ -2,7 +2,6 @@ use std::panic::UnwindSafe;
 
 use expect_test::expect;
 use salsa::{Durability, ParallelDatabase, Snapshot};
-use test_log::test;
 
 // Axes:
 //
@@ -172,8 +171,8 @@ fn cycle_memoized() {
     let cycle = extract_cycle(|| db.memoized_a());
     expect![[r#"
         [
-            "memoized_a(())",
-            "memoized_b(())",
+            "cycles::MemoizedAQuery::memoized_a(())",
+            "cycles::MemoizedBQuery::memoized_b(())",
         ]
     "#]]
     .assert_debug_eq(&cycle.unexpected_participants(&db));
@@ -185,8 +184,8 @@ fn cycle_volatile() {
     let cycle = extract_cycle(|| db.volatile_a());
     expect![[r#"
         [
-            "volatile_a(())",
-            "volatile_b(())",
+            "cycles::VolatileAQuery::volatile_a(())",
+            "cycles::VolatileBQuery::volatile_b(())",
         ]
     "#]]
     .assert_debug_eq(&cycle.unexpected_participants(&db));
@@ -223,8 +222,8 @@ fn inner_cycle() {
     let cycle = err.unwrap_err().cycle;
     expect![[r#"
         [
-            "cycle_a(())",
-            "cycle_b(())",
+            "cycles::CycleAQuery::cycle_a(())",
+            "cycles::CycleBQuery::cycle_b(())",
         ]
     "#]]
     .assert_debug_eq(&cycle);
@@ -263,8 +262,8 @@ fn cycle_revalidate_unchanged_twice() {
         Err(
             Error {
                 cycle: [
-                    "cycle_a(())",
-                    "cycle_b(())",
+                    "cycles::CycleAQuery::cycle_a(())",
+                    "cycles::CycleBQuery::cycle_b(())",
                 ],
             },
         )
@@ -345,8 +344,8 @@ fn cycle_mixed_1() {
         Err(
             Error {
                 cycle: [
-                    "cycle_b(())",
-                    "cycle_c(())",
+                    "cycles::CycleBQuery::cycle_b(())",
+                    "cycles::CycleCQuery::cycle_c(())",
                 ],
             },
         )
@@ -372,9 +371,9 @@ fn cycle_mixed_2() {
         Err(
             Error {
                 cycle: [
-                    "cycle_a(())",
-                    "cycle_b(())",
-                    "cycle_c(())",
+                    "cycles::CycleAQuery::cycle_a(())",
+                    "cycles::CycleBQuery::cycle_b(())",
+                    "cycles::CycleCQuery::cycle_c(())",
                 ],
             },
         )
@@ -401,16 +400,16 @@ fn cycle_deterministic_order() {
             Err(
                 Error {
                     cycle: [
-                        "cycle_a(())",
-                        "cycle_b(())",
+                        "cycles::CycleAQuery::cycle_a(())",
+                        "cycles::CycleBQuery::cycle_b(())",
                     ],
                 },
             ),
             Err(
                 Error {
                     cycle: [
-                        "cycle_a(())",
-                        "cycle_b(())",
+                        "cycles::CycleAQuery::cycle_a(())",
+                        "cycles::CycleBQuery::cycle_b(())",
                     ],
                 },
             ),
@@ -446,24 +445,24 @@ fn cycle_multiple() {
             Err(
                 Error {
                     cycle: [
-                        "cycle_a(())",
-                        "cycle_b(())",
+                        "cycles::CycleAQuery::cycle_a(())",
+                        "cycles::CycleBQuery::cycle_b(())",
                     ],
                 },
             ),
             Err(
                 Error {
                     cycle: [
-                        "cycle_a(())",
-                        "cycle_b(())",
+                        "cycles::CycleAQuery::cycle_a(())",
+                        "cycles::CycleBQuery::cycle_b(())",
                     ],
                 },
             ),
             Err(
                 Error {
                     cycle: [
-                        "cycle_a(())",
-                        "cycle_b(())",
+                        "cycles::CycleAQuery::cycle_a(())",
+                        "cycles::CycleBQuery::cycle_b(())",
                     ],
                 },
             ),
@@ -486,7 +485,7 @@ fn cycle_recovery_set_but_not_participating() {
     let r = extract_cycle(|| drop(db.cycle_a()));
     expect![[r#"
         [
-            "cycle_c(())",
+            "cycles::CycleCQuery::cycle_c(())",
         ]
     "#]]
     .assert_debug_eq(&r.all_participants(&db));
diff --git a/src/tools/rust-analyzer/crates/salsa/tests/on_demand_inputs.rs b/src/tools/rust-analyzer/crates/salsa/tests/on_demand_inputs.rs
index 677d633ee7c..cad594f536f 100644
--- a/src/tools/rust-analyzer/crates/salsa/tests/on_demand_inputs.rs
+++ b/src/tools/rust-analyzer/crates/salsa/tests/on_demand_inputs.rs
@@ -103,10 +103,10 @@ fn on_demand_input_durability() {
     expect_test::expect![[r#"
         RefCell {
             value: [
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: b(1) } }",
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: a(1) } }",
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: b(2) } }",
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: a(2) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::BQuery::b(1) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::AQuery::a(1) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::BQuery::b(2) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::AQuery::a(2) } }",
             ],
         }
     "#]].assert_debug_eq(&events);
@@ -119,11 +119,11 @@ fn on_demand_input_durability() {
     expect_test::expect![[r#"
         RefCell {
             value: [
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: c(1) } }",
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: b(1) } }",
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: c(2) } }",
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: a(2) } }",
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: b(2) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::CQuery::c(1) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: on_demand_inputs::BQuery::b(1) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::CQuery::c(2) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::AQuery::a(2) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: on_demand_inputs::BQuery::b(2) } }",
             ],
         }
     "#]].assert_debug_eq(&events);
@@ -137,10 +137,10 @@ fn on_demand_input_durability() {
     expect_test::expect![[r#"
         RefCell {
             value: [
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: a(1) } }",
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: c(1) } }",
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: a(2) } }",
-                "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: c(2) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::AQuery::a(1) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: on_demand_inputs::CQuery::c(1) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: WillExecute { database_key: on_demand_inputs::AQuery::a(2) } }",
+                "Event { runtime_id: RuntimeId { counter: 0 }, kind: DidValidateMemoizedValue { database_key: on_demand_inputs::CQuery::c(2) } }",
             ],
         }
     "#]].assert_debug_eq(&events);
diff --git a/src/tools/rust-analyzer/crates/salsa/tests/parallel/parallel_cycle_all_recover.rs b/src/tools/rust-analyzer/crates/salsa/tests/parallel/parallel_cycle_all_recover.rs
index cee51b4db75..a13ae3418f2 100644
--- a/src/tools/rust-analyzer/crates/salsa/tests/parallel/parallel_cycle_all_recover.rs
+++ b/src/tools/rust-analyzer/crates/salsa/tests/parallel/parallel_cycle_all_recover.rs
@@ -4,7 +4,6 @@
 
 use crate::setup::{Knobs, ParDatabaseImpl};
 use salsa::ParallelDatabase;
-use test_log::test;
 
 // Recover cycle test:
 //
diff --git a/src/tools/rust-analyzer/crates/salsa/tests/parallel/parallel_cycle_mid_recover.rs b/src/tools/rust-analyzer/crates/salsa/tests/parallel/parallel_cycle_mid_recover.rs
index f78c05c5593..971fe7ab120 100644
--- a/src/tools/rust-analyzer/crates/salsa/tests/parallel/parallel_cycle_mid_recover.rs
+++ b/src/tools/rust-analyzer/crates/salsa/tests/parallel/parallel_cycle_mid_recover.rs
@@ -4,7 +4,6 @@
 
 use crate::setup::{Knobs, ParDatabaseImpl};
 use salsa::ParallelDatabase;
-use test_log::test;
 
 // Recover cycle test:
 //
diff --git a/src/tools/rust-analyzer/crates/salsa/tests/parallel/parallel_cycle_none_recover.rs b/src/tools/rust-analyzer/crates/salsa/tests/parallel/parallel_cycle_none_recover.rs
index 35fe3791182..2930c4e379f 100644
--- a/src/tools/rust-analyzer/crates/salsa/tests/parallel/parallel_cycle_none_recover.rs
+++ b/src/tools/rust-analyzer/crates/salsa/tests/parallel/parallel_cycle_none_recover.rs
@@ -5,7 +5,6 @@
 use crate::setup::{Knobs, ParDatabaseImpl};
 use expect_test::expect;
 use salsa::ParallelDatabase;
-use test_log::test;
 
 #[test]
 fn parallel_cycle_none_recover() {
@@ -28,8 +27,8 @@ fn parallel_cycle_none_recover() {
     if let Some(c) = err_b.downcast_ref::<salsa::Cycle>() {
         expect![[r#"
             [
-                "a(-1)",
-                "b(-1)",
+                "parallel::parallel_cycle_none_recover::AQuery::a(-1)",
+                "parallel::parallel_cycle_none_recover::BQuery::b(-1)",
             ]
         "#]]
         .assert_debug_eq(&c.unexpected_participants(&db));
diff --git a/src/tools/rust-analyzer/crates/salsa/tests/parallel/parallel_cycle_one_recovers.rs b/src/tools/rust-analyzer/crates/salsa/tests/parallel/parallel_cycle_one_recovers.rs
index 7d3944714ae..025fbf37477 100644
--- a/src/tools/rust-analyzer/crates/salsa/tests/parallel/parallel_cycle_one_recovers.rs
+++ b/src/tools/rust-analyzer/crates/salsa/tests/parallel/parallel_cycle_one_recovers.rs
@@ -4,7 +4,6 @@
 
 use crate::setup::{Knobs, ParDatabaseImpl};
 use salsa::ParallelDatabase;
-use test_log::test;
 
 // Recover cycle test:
 //
diff --git a/src/tools/rust-analyzer/crates/span/src/ast_id.rs b/src/tools/rust-analyzer/crates/span/src/ast_id.rs
index 2d98aa81e50..332745aae6e 100644
--- a/src/tools/rust-analyzer/crates/span/src/ast_id.rs
+++ b/src/tools/rust-analyzer/crates/span/src/ast_id.rs
@@ -83,24 +83,28 @@ register_ast_id_node! {
     Item,
         Adt,
             Enum,
+                Variant,
             Struct,
+                RecordField,
+                TupleField,
             Union,
-        Const,
+        AssocItem,
+            Const,
+            Fn,
+            MacroCall,
+            TypeAlias,
         ExternBlock,
         ExternCrate,
-        Fn,
         Impl,
         Macro,
             MacroDef,
             MacroRules,
-        MacroCall,
         Module,
         Static,
         Trait,
         TraitAlias,
-        TypeAlias,
         Use,
-    AssocItem, BlockExpr, Variant, RecordField, TupleField, ConstArg, Param, SelfParam
+    BlockExpr, ConstArg, Param, SelfParam
 }
 
 /// Maps items' `SyntaxNode`s to `ErasedFileAstId`s and back.
diff --git a/src/tools/rust-analyzer/crates/stdx/src/process.rs b/src/tools/rust-analyzer/crates/stdx/src/process.rs
index bca0cbc36d1..e6935f06b2c 100644
--- a/src/tools/rust-analyzer/crates/stdx/src/process.rs
+++ b/src/tools/rust-analyzer/crates/stdx/src/process.rs
@@ -15,6 +15,7 @@ pub fn streaming_output(
     err: ChildStderr,
     on_stdout_line: &mut dyn FnMut(&str),
     on_stderr_line: &mut dyn FnMut(&str),
+    on_eof: &mut dyn FnMut(),
 ) -> io::Result<(Vec<u8>, Vec<u8>)> {
     let mut stdout = Vec::new();
     let mut stderr = Vec::new();
@@ -44,6 +45,9 @@ pub fn streaming_output(
                     on_stderr_line(line);
                 }
             }
+            if eof {
+                on_eof();
+            }
         }
     })?;
 
@@ -63,6 +67,7 @@ pub fn spawn_with_streaming_output(
         child.stderr.take().unwrap(),
         on_stdout_line,
         on_stderr_line,
+        &mut || (),
     )?;
     let status = child.wait()?;
     Ok(Output { status, stdout, stderr })
diff --git a/src/tools/rust-analyzer/crates/syntax/Cargo.toml b/src/tools/rust-analyzer/crates/syntax/Cargo.toml
index a0fd73ee13f..9a8d73cf7ff 100644
--- a/src/tools/rust-analyzer/crates/syntax/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/syntax/Cargo.toml
@@ -27,7 +27,6 @@ tracing.workspace = true
 ra-ap-rustc_lexer.workspace = true
 
 parser.workspace = true
-profile.workspace = true
 stdx.workspace = true
 text-edit.workspace = true
 
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
index f299dda4f0f..ff18fee9bab 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
@@ -724,7 +724,10 @@ pub fn record_pat_field_list(
 ) -> ast::RecordPatFieldList {
     let mut fields = fields.into_iter().join(", ");
     if let Some(rest_pat) = rest_pat {
-        format_to!(fields, ", {rest_pat}");
+        if !fields.is_empty() {
+            fields.push_str(", ");
+        }
+        format_to!(fields, "{rest_pat}");
     }
     ast_from_text(&format!("fn f(S {{ {fields} }}: ()))"))
 }
diff --git a/src/tools/rust-analyzer/crates/syntax/src/lib.rs b/src/tools/rust-analyzer/crates/syntax/src/lib.rs
index b755de86d32..1bb82cc191f 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/lib.rs
@@ -97,8 +97,11 @@ impl<T> Parse<T> {
     pub fn syntax_node(&self) -> SyntaxNode {
         SyntaxNode::new_root(self.green.clone())
     }
-    pub fn errors(&self) -> &[SyntaxError] {
-        self.errors.as_deref().unwrap_or_default()
+
+    pub fn errors(&self) -> Vec<SyntaxError> {
+        let mut errors = if let Some(e) = self.errors.as_deref() { e.to_vec() } else { vec![] };
+        validation::validate(&self.syntax_node(), &mut errors);
+        errors
     }
 }
 
@@ -111,10 +114,10 @@ impl<T: AstNode> Parse<T> {
         T::cast(self.syntax_node()).unwrap()
     }
 
-    pub fn ok(self) -> Result<T, Arc<[SyntaxError]>> {
-        match self.errors {
-            Some(e) => Err(e),
-            None => Ok(self.tree()),
+    pub fn ok(self) -> Result<T, Vec<SyntaxError>> {
+        match self.errors() {
+            errors if !errors.is_empty() => Err(errors),
+            _ => Ok(self.tree()),
         }
     }
 }
@@ -132,7 +135,7 @@ impl Parse<SyntaxNode> {
 impl Parse<SourceFile> {
     pub fn debug_dump(&self) -> String {
         let mut buf = format!("{:#?}", self.tree().syntax());
-        for err in self.errors.as_deref().into_iter().flat_map(<[_]>::iter) {
+        for err in self.errors() {
             format_to!(buf, "error {:?}: {}\n", err.range(), err);
         }
         buf
@@ -168,11 +171,10 @@ pub use crate::ast::SourceFile;
 
 impl SourceFile {
     pub fn parse(text: &str) -> Parse<SourceFile> {
-        let (green, mut errors) = parsing::parse_text(text);
+        let _p = tracing::span!(tracing::Level::INFO, "SourceFile::parse").entered();
+        let (green, errors) = parsing::parse_text(text);
         let root = SyntaxNode::new_root(green.clone());
 
-        errors.extend(validation::validate(&root));
-
         assert_eq!(root.kind(), SyntaxKind::SOURCE_FILE);
         Parse {
             green,
diff --git a/src/tools/rust-analyzer/crates/syntax/src/parsing.rs b/src/tools/rust-analyzer/crates/syntax/src/parsing.rs
index 1250b5274c1..d750476f63c 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/parsing.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/parsing.rs
@@ -10,6 +10,7 @@ use crate::{syntax_node::GreenNode, SyntaxError, SyntaxTreeBuilder};
 pub(crate) use crate::parsing::reparsing::incremental_reparse;
 
 pub(crate) fn parse_text(text: &str) -> (GreenNode, Vec<SyntaxError>) {
+    let _p = tracing::span!(tracing::Level::INFO, "parse_text").entered();
     let lexed = parser::LexedStr::new(text);
     let parser_input = lexed.to_input();
     let parser_output = parser::TopEntryPoint::SourceFile.parse(&parser_input);
@@ -21,6 +22,7 @@ pub(crate) fn build_tree(
     lexed: parser::LexedStr<'_>,
     parser_output: parser::Output,
 ) -> (GreenNode, Vec<SyntaxError>, bool) {
+    let _p = tracing::span!(tracing::Level::INFO, "build_tree").entered();
     let mut builder = SyntaxTreeBuilder::default();
 
     let is_eof = lexed.intersperse_trivia(&parser_output, &mut |step| match step {
diff --git a/src/tools/rust-analyzer/crates/syntax/src/tests.rs b/src/tools/rust-analyzer/crates/syntax/src/tests.rs
index 4c0a538f712..5400071c4b6 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/tests.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/tests.rs
@@ -39,7 +39,7 @@ fn benchmark_parser() {
     let tree = {
         let _b = bench("parsing");
         let p = SourceFile::parse(&data);
-        assert!(p.errors.is_none());
+        assert!(p.errors().is_empty());
         assert_eq!(p.tree().syntax.text_range().len(), 352474.into());
         p.tree()
     };
@@ -57,7 +57,7 @@ fn validation_tests() {
     dir_tests(&test_data_dir(), &["parser/validation"], "rast", |text, path| {
         let parse = SourceFile::parse(text);
         let errors = parse.errors();
-        assert_errors_are_present(errors, path);
+        assert_errors_are_present(&errors, path);
         parse.debug_dump()
     });
 }
diff --git a/src/tools/rust-analyzer/crates/syntax/src/validation.rs b/src/tools/rust-analyzer/crates/syntax/src/validation.rs
index 5c5b26f525f..dbfab537fe5 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/validation.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/validation.rs
@@ -15,33 +15,32 @@ use crate::{
     SyntaxNode, SyntaxToken, TextSize, T,
 };
 
-pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> {
+pub(crate) fn validate(root: &SyntaxNode, errors: &mut Vec<SyntaxError>) {
+    let _p = tracing::span!(tracing::Level::INFO, "parser::validate").entered();
     // FIXME:
     // * Add unescape validation of raw string literals and raw byte string literals
     // * Add validation of doc comments are being attached to nodes
 
-    let mut errors = Vec::new();
     for node in root.descendants() {
         match_ast! {
             match node {
-                ast::Literal(it) => validate_literal(it, &mut errors),
-                ast::Const(it) => validate_const(it, &mut errors),
-                ast::BlockExpr(it) => block::validate_block_expr(it, &mut errors),
-                ast::FieldExpr(it) => validate_numeric_name(it.name_ref(), &mut errors),
-                ast::RecordExprField(it) => validate_numeric_name(it.name_ref(), &mut errors),
-                ast::Visibility(it) => validate_visibility(it, &mut errors),
-                ast::RangeExpr(it) => validate_range_expr(it, &mut errors),
-                ast::PathSegment(it) => validate_path_keywords(it, &mut errors),
-                ast::RefType(it) => validate_trait_object_ref_ty(it, &mut errors),
-                ast::PtrType(it) => validate_trait_object_ptr_ty(it, &mut errors),
-                ast::FnPtrType(it) => validate_trait_object_fn_ptr_ret_ty(it, &mut errors),
-                ast::MacroRules(it) => validate_macro_rules(it, &mut errors),
-                ast::LetExpr(it) => validate_let_expr(it, &mut errors),
+                ast::Literal(it) => validate_literal(it, errors),
+                ast::Const(it) => validate_const(it, errors),
+                ast::BlockExpr(it) => block::validate_block_expr(it, errors),
+                ast::FieldExpr(it) => validate_numeric_name(it.name_ref(), errors),
+                ast::RecordExprField(it) => validate_numeric_name(it.name_ref(), errors),
+                ast::Visibility(it) => validate_visibility(it, errors),
+                ast::RangeExpr(it) => validate_range_expr(it, errors),
+                ast::PathSegment(it) => validate_path_keywords(it, errors),
+                ast::RefType(it) => validate_trait_object_ref_ty(it, errors),
+                ast::PtrType(it) => validate_trait_object_ptr_ty(it, errors),
+                ast::FnPtrType(it) => validate_trait_object_fn_ptr_ret_ty(it, errors),
+                ast::MacroRules(it) => validate_macro_rules(it, errors),
+                ast::LetExpr(it) => validate_let_expr(it, errors),
                 _ => (),
             }
         }
     }
-    errors
 }
 
 fn rustc_unescape_error_to_string(err: unescape::EscapeError) -> (&'static str, bool) {
diff --git a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
index e118262b4ed..a654366c62a 100644
--- a/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/test-fixture/src/lib.rs
@@ -7,7 +7,7 @@ use base_db::{
 };
 use cfg::CfgOptions;
 use hir_expand::{
-    change::Change,
+    change::ChangeWithProcMacros,
     db::ExpandDatabase,
     proc_macro::{
         ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroKind, ProcMacros,
@@ -103,7 +103,7 @@ impl<DB: ExpandDatabase + SourceDatabaseExt + Default + 'static> WithFixture for
 pub struct ChangeFixture {
     pub file_position: Option<(FileId, RangeOrOffset)>,
     pub files: Vec<FileId>,
-    pub change: Change,
+    pub change: ChangeWithProcMacros,
 }
 
 const SOURCE_ROOT_PREFIX: &str = "/";
@@ -149,15 +149,15 @@ impl ChangeFixture {
         for entry in fixture {
             let text = if entry.text.contains(CURSOR_MARKER) {
                 if entry.text.contains(ESCAPED_CURSOR_MARKER) {
-                    entry.text.replace(ESCAPED_CURSOR_MARKER, CURSOR_MARKER)
+                    entry.text.replace(ESCAPED_CURSOR_MARKER, CURSOR_MARKER).into()
                 } else {
                     let (range_or_offset, text) = extract_range_or_offset(&entry.text);
                     assert!(file_position.is_none());
                     file_position = Some((file_id, range_or_offset));
-                    text
+                    text.into()
                 }
             } else {
-                entry.text.clone()
+                entry.text.as_str().into()
             };
 
             let meta = FileMeta::from_fixture(entry, current_source_root_kind);
@@ -195,7 +195,10 @@ impl ChangeFixture {
                 let prev = crates.insert(crate_name.clone(), crate_id);
                 assert!(prev.is_none(), "multiple crates with same name: {}", crate_name);
                 for dep in meta.deps {
-                    let prelude = meta.extern_prelude.contains(&dep);
+                    let prelude = match &meta.extern_prelude {
+                        Some(v) => v.contains(&dep),
+                        None => true,
+                    };
                     let dep = CrateName::normalize_dashes(&dep);
                     crate_deps.push((crate_name.clone(), dep, prelude))
                 }
@@ -206,7 +209,7 @@ impl ChangeFixture {
                 default_env.extend(meta.env.iter().map(|(x, y)| (x.to_owned(), y.to_owned())));
             }
 
-            source_change.change_file(file_id, Some(text.into()));
+            source_change.change_file(file_id, Some(text));
             let path = VfsPath::new_virtual_path(meta.path);
             file_set.insert(file_id, path);
             files.push(file_id);
@@ -317,7 +320,7 @@ impl ChangeFixture {
         };
         roots.push(root);
 
-        let mut change = Change {
+        let mut change = ChangeWithProcMacros {
             source_change,
             proc_macros: proc_macros.is_empty().not().then_some(proc_macros),
             toolchains: Some(iter::repeat(toolchain).take(crate_graph.len()).collect()),
@@ -443,7 +446,7 @@ struct FileMeta {
     path: String,
     krate: Option<(String, CrateOrigin, Option<String>)>,
     deps: Vec<String>,
-    extern_prelude: Vec<String>,
+    extern_prelude: Option<Vec<String>>,
     cfg: CfgOptions,
     edition: Edition,
     env: Env,
@@ -473,7 +476,7 @@ impl FileMeta {
         Self {
             path: f.path,
             krate: f.krate.map(|it| parse_crate(it, current_source_root_kind, f.library)),
-            extern_prelude: f.extern_prelude.unwrap_or_else(|| deps.clone()),
+            extern_prelude: f.extern_prelude,
             deps,
             cfg,
             edition: f.edition.map_or(Edition::CURRENT, |v| Edition::from_str(&v).unwrap()),
diff --git a/src/tools/rust-analyzer/crates/toolchain/src/lib.rs b/src/tools/rust-analyzer/crates/toolchain/src/lib.rs
index 793138588a3..a77fed585af 100644
--- a/src/tools/rust-analyzer/crates/toolchain/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/toolchain/src/lib.rs
@@ -16,18 +16,48 @@ pub enum Tool {
 }
 
 impl Tool {
+    pub fn proxy(self) -> Option<PathBuf> {
+        cargo_proxy(self.name())
+    }
+
+    /// Return a `PathBuf` to use for the given executable.
+    ///
+    /// The current implementation checks three places for an executable to use:
+    /// 1) `$CARGO_HOME/bin/<executable_name>`
+    ///      where $CARGO_HOME defaults to ~/.cargo (see https://doc.rust-lang.org/cargo/guide/cargo-home.html)
+    ///      example: for cargo, this tries $CARGO_HOME/bin/cargo, or ~/.cargo/bin/cargo if $CARGO_HOME is unset.
+    ///      It seems that this is a reasonable place to try for cargo, rustc, and rustup
+    /// 2) Appropriate environment variable (erroring if this is set but not a usable executable)
+    ///      example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc
+    /// 3) $PATH/`<executable_name>`
+    ///      example: for cargo, this tries all paths in $PATH with appended `cargo`, returning the
+    ///      first that exists
+    /// 4) If all else fails, we just try to use the executable name directly
+    pub fn prefer_proxy(self) -> PathBuf {
+        invoke(&[cargo_proxy, lookup_as_env_var, lookup_in_path], self.name())
+    }
+
+    /// Return a `PathBuf` to use for the given executable.
+    ///
+    /// The current implementation checks three places for an executable to use:
+    /// 1) Appropriate environment variable (erroring if this is set but not a usable executable)
+    ///      example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc
+    /// 2) $PATH/`<executable_name>`
+    ///      example: for cargo, this tries all paths in $PATH with appended `cargo`, returning the
+    ///      first that exists
+    /// 3) `$CARGO_HOME/bin/<executable_name>`
+    ///      where $CARGO_HOME defaults to ~/.cargo (see https://doc.rust-lang.org/cargo/guide/cargo-home.html)
+    ///      example: for cargo, this tries $CARGO_HOME/bin/cargo, or ~/.cargo/bin/cargo if $CARGO_HOME is unset.
+    ///      It seems that this is a reasonable place to try for cargo, rustc, and rustup
+    /// 4) If all else fails, we just try to use the executable name directly
     pub fn path(self) -> PathBuf {
-        get_path_for_executable(self.name())
+        invoke(&[lookup_as_env_var, lookup_in_path, cargo_proxy], self.name())
     }
 
     pub fn path_in(self, path: &Path) -> Option<PathBuf> {
         probe_for_binary(path.join(self.name()))
     }
 
-    pub fn path_in_or_discover(self, path: &Path) -> PathBuf {
-        probe_for_binary(path.join(self.name())).unwrap_or_else(|| self.path())
-    }
-
     pub fn name(self) -> &'static str {
         match self {
             Tool::Cargo => "cargo",
@@ -38,60 +68,21 @@ impl Tool {
     }
 }
 
-pub fn cargo() -> PathBuf {
-    get_path_for_executable("cargo")
+fn invoke(list: &[fn(&str) -> Option<PathBuf>], executable: &str) -> PathBuf {
+    list.iter().find_map(|it| it(executable)).unwrap_or_else(|| executable.into())
 }
 
-pub fn rustc() -> PathBuf {
-    get_path_for_executable("rustc")
+/// Looks up the binary as its SCREAMING upper case in the env variables.
+fn lookup_as_env_var(executable_name: &str) -> Option<PathBuf> {
+    env::var_os(executable_name.to_ascii_uppercase()).map(Into::into)
 }
 
-pub fn rustup() -> PathBuf {
-    get_path_for_executable("rustup")
-}
-
-pub fn rustfmt() -> PathBuf {
-    get_path_for_executable("rustfmt")
-}
-
-/// Return a `PathBuf` to use for the given executable.
-///
-/// E.g., `get_path_for_executable("cargo")` may return just `cargo` if that
-/// gives a valid Cargo executable; or it may return a full path to a valid
-/// Cargo.
-fn get_path_for_executable(executable_name: &'static str) -> PathBuf {
-    // The current implementation checks three places for an executable to use:
-    // 1) Appropriate environment variable (erroring if this is set but not a usable executable)
-    //      example: for cargo, this checks $CARGO environment variable; for rustc, $RUSTC; etc
-    // 2) `$CARGO_HOME/bin/<executable_name>`
-    //      where $CARGO_HOME defaults to ~/.cargo (see https://doc.rust-lang.org/cargo/guide/cargo-home.html)
-    //      example: for cargo, this tries $CARGO_HOME/bin/cargo, or ~/.cargo/bin/cargo if $CARGO_HOME is unset.
-    //      It seems that this is a reasonable place to try for cargo, rustc, and rustup
-    // 3) `<executable_name>`
-    //      example: for cargo, this tries just `cargo`, which will succeed if `cargo` is on the $PATH
-    let env_var = executable_name.to_ascii_uppercase();
-    if let Some(path) = env::var_os(env_var) {
-        return path.into();
-    }
-
-    if let Some(mut path) = get_cargo_home() {
-        path.push("bin");
-        path.push(executable_name);
-        if let Some(path) = probe_for_binary(path) {
-            return path;
-        }
-    }
-
-    if lookup_in_path(executable_name) {
-        return executable_name.into();
-    }
-
-    executable_name.into()
-}
-
-fn lookup_in_path(exec: &str) -> bool {
-    let paths = env::var_os("PATH").unwrap_or_default();
-    env::split_paths(&paths).map(|path| path.join(exec)).find_map(probe_for_binary).is_some()
+/// Looks up the binary in the cargo home directory if it exists.
+fn cargo_proxy(executable_name: &str) -> Option<PathBuf> {
+    let mut path = get_cargo_home()?;
+    path.push("bin");
+    path.push(executable_name);
+    probe_for_binary(path)
 }
 
 fn get_cargo_home() -> Option<PathBuf> {
@@ -107,6 +98,11 @@ fn get_cargo_home() -> Option<PathBuf> {
     None
 }
 
+fn lookup_in_path(exec: &str) -> Option<PathBuf> {
+    let paths = env::var_os("PATH").unwrap_or_default();
+    env::split_paths(&paths).map(|path| path.join(exec)).find_map(probe_for_binary)
+}
+
 pub fn probe_for_binary(path: PathBuf) -> Option<PathBuf> {
     let with_extension = match env::consts::EXE_EXTENSION {
         "" => None,
diff --git a/src/tools/rust-analyzer/crates/vfs/src/file_set.rs b/src/tools/rust-analyzer/crates/vfs/src/file_set.rs
index 0392ef3cebe..7eeb10d544a 100644
--- a/src/tools/rust-analyzer/crates/vfs/src/file_set.rs
+++ b/src/tools/rust-analyzer/crates/vfs/src/file_set.rs
@@ -123,6 +123,11 @@ impl FileSetConfig {
         self.n_file_sets
     }
 
+    /// Get the lexicographically ordered vector of the underlying map.
+    pub fn roots(&self) -> Vec<(Vec<u8>, u64)> {
+        self.map.stream().into_byte_vec()
+    }
+
     /// Returns the set index for the given `path`.
     ///
     /// `scratch_space` is used as a buffer and will be entirely replaced.
diff --git a/src/tools/rust-analyzer/crates/vfs/src/lib.rs b/src/tools/rust-analyzer/crates/vfs/src/lib.rs
index 34a85818eb8..824ce398703 100644
--- a/src/tools/rust-analyzer/crates/vfs/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/vfs/src/lib.rs
@@ -163,8 +163,8 @@ impl Vfs {
     /// # Panics
     ///
     /// Panics if the id is not present in the `Vfs`.
-    pub fn file_path(&self, file_id: FileId) -> VfsPath {
-        self.interner.lookup(file_id).clone()
+    pub fn file_path(&self, file_id: FileId) -> &VfsPath {
+        self.interner.lookup(file_id)
     }
 
     /// Returns an iterator over the stored ids and their corresponding paths.
diff --git a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
index f3100ee194e..af5b4e51ef3 100644
--- a/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
+++ b/src/tools/rust-analyzer/docs/dev/lsp-extensions.md
@@ -1,5 +1,5 @@
 <!---
-lsp/ext.rs hash: 8be79cc3b7f10ad7
+lsp/ext.rs hash: 6bc140531b403717
 
 If you need to change the above hash to make the test pass, please check if you
 need to adjust this doc as well and ping this issue:
@@ -385,6 +385,130 @@ rust-analyzer supports only one `kind`, `"cargo"`. The `args` for `"cargo"` look
 }
 ```
 
+## Test explorer
+
+**Experimental Client Capability:** `{ "testExplorer": boolean }`
+
+If this capability is set, the `experimental/discoveredTests` notification will be sent from the
+server to the client.
+
+**Method:** `experimental/discoverTest`
+
+**Request:** `DiscoverTestParams`
+
+```typescript
+interface DiscoverTestParams {
+    // The test that we need to resolve its children. If not present,
+    // the response should return top level tests.
+    testId?: string | undefined;
+}
+```
+
+**Response:** `DiscoverTestResults`
+
+```typescript
+interface TestItem {
+    // A unique identifier for the test
+    id: string;
+    // The file containing this test
+    textDocument?: lc.TextDocumentIdentifier | undefined;
+    // The range in the file containing this test
+    range?: lc.Range | undefined;
+    // A human readable name for this test
+    label: string;
+    // The kind of this test item. Based on the kind,
+	// an icon is chosen by the editor. 
+    kind: "package" | "module" | "test";
+    // True if this test may have children not available eagerly
+    canResolveChildren: boolean;
+    // The id of the parent test in the test tree. If not present, this test
+    // is a top level test.
+    parent?: string | undefined;
+    // The information useful for running the test. The client can use `runTest`
+    // request for simple execution, but for more complex execution forms
+    // like debugging, this field is useful.
+    // Note that this field includes some information about label and location as well, but
+    // those exist just for keeping things in sync with other methods of running runnables
+    // (for example using one consistent name in the vscode's launch.json) so for any propose
+    // other than running tests this field should not be used.
+    runnable?: Runnable | undefined;
+};
+
+interface DiscoverTestResults {
+    // The discovered tests.
+    tests: TestItem[];
+    // For each test which its id is in this list, the response
+    // contains all tests that are children of this test, and
+    // client should remove old tests not included in the response.
+    scope: string[];
+}
+```
+
+**Method:** `experimental/discoveredTests`
+
+**Notification:** `DiscoverTestResults`
+
+This notification is sent from the server to the client when the
+server detect changes in the existing tests. The `DiscoverTestResults` is
+the same as the one in `experimental/discoverTest` response.
+
+**Method:** `experimental/runTest`
+
+**Request:** `RunTestParams`
+
+```typescript
+interface RunTestParams {
+    // Id of the tests to be run. If a test is included, all of its children are included implicitly. If
+    // this property is undefined, then the server should simply run all tests.
+    include?: string[] | undefined;
+    // An array of test ids the user has marked as excluded from the test included in this run; exclusions
+    // should apply after inclusions.
+    // May be omitted if no exclusions were requested. Server should not run excluded tests or
+    // any children of excluded tests.
+    exclude?: string[] | undefined;
+}
+```
+
+**Response:** `void`
+
+**Method:** `experimental/endRunTest`
+
+**Notification:**
+
+This notification is sent from the server to the client when the current running
+session is finished. The server should not send any run notification
+after this.
+
+**Method:** `experimental/abortRunTest`
+
+**Notification:**
+
+This notification is sent from the client to the server when the user is no longer
+interested in the test results. The server should clean up its resources and send
+a `experimental/endRunTest` when is done.
+
+**Method:** `experimental/changeTestState`
+
+**Notification:** `ChangeTestStateParams`
+
+```typescript
+type TestState = { tag: "passed" } 
+    | {
+        tag: "failed"; 
+        // The standard error of the test, containing the panic message. Clients should
+        // render it similar to a terminal, and e.g. handle ansi colors.
+        message: string;
+    }
+    | { tag: "started" }
+    | { tag: "enqueued" }
+    | { tag: "skipped" };
+
+interface ChangeTestStateParams {
+    testId: string;
+    state: TestState;
+}
+```
+
 ## Open External Documentation
 
 This request is sent from the client to the server to obtain web and local URL(s) for documentation related to the symbol under the cursor, if available.
diff --git a/src/tools/rust-analyzer/docs/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc
index d4ba5af9231..5e782b78311 100644
--- a/src/tools/rust-analyzer/docs/user/generated_config.adoc
+++ b/src/tools/rust-analyzer/docs/user/generated_config.adoc
@@ -386,6 +386,11 @@ have more false positives than usual.
 Map of prefixes to be substituted when parsing diagnostic file paths.
 This should be the reverse mapping of what is passed to `rustc` as `--remap-path-prefix`.
 --
+[[rust-analyzer.diagnostics.styleLints.enable]]rust-analyzer.diagnostics.styleLints.enable (default: `false`)::
++
+--
+Whether to run additional style lints.
+--
 [[rust-analyzer.diagnostics.warningsAsHint]]rust-analyzer.diagnostics.warningsAsHint (default: `[]`)::
 +
 --
@@ -515,6 +520,11 @@ How to render the offset information in a memory layout hover.
 --
 How to render the size information in a memory layout hover.
 --
+[[rust-analyzer.hover.show.traitAssocItems]]rust-analyzer.hover.show.traitAssocItems (default: `null`)::
++
+--
+How many associated items of a trait to display when hovering a trait.
+--
 [[rust-analyzer.imports.granularity.enforce]]rust-analyzer.imports.granularity.enforce (default: `false`)::
 +
 --
diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json
index d86365591a6..c34b8e25de0 100644
--- a/src/tools/rust-analyzer/editors/code/package.json
+++ b/src/tools/rust-analyzer/editors/code/package.json
@@ -510,6 +510,11 @@
                     "default": true,
                     "type": "boolean"
                 },
+                "rust-analyzer.testExplorer": {
+                    "markdownDescription": "Whether to show the test explorer.",
+                    "default": false,
+                    "type": "boolean"
+                },
                 "$generated-start": {},
                 "rust-analyzer.assist.emitMustUse": {
                     "markdownDescription": "Whether to insert #[must_use] when generating `as_` methods\nfor enum variants.",
@@ -948,6 +953,11 @@
                     "default": {},
                     "type": "object"
                 },
+                "rust-analyzer.diagnostics.styleLints.enable": {
+                    "markdownDescription": "Whether to run additional style lints.",
+                    "default": false,
+                    "type": "boolean"
+                },
                 "rust-analyzer.diagnostics.warningsAsHint": {
                     "markdownDescription": "List of warnings that should be displayed with hint severity.\n\nThe warnings will be indicated by faded text or three dots in code\nand will not show up in the `Problems Panel`.",
                     "default": [],
@@ -1134,6 +1144,15 @@
                         }
                     ]
                 },
+                "rust-analyzer.hover.show.traitAssocItems": {
+                    "markdownDescription": "How many associated items of a trait to display when hovering a trait.",
+                    "default": null,
+                    "type": [
+                        "null",
+                        "integer"
+                    ],
+                    "minimum": 0
+                },
                 "rust-analyzer.imports.granularity.enforce": {
                     "markdownDescription": "Whether to enforce the import granularity setting for all files. If set to false rust-analyzer will try to keep import styles consistent per file.",
                     "default": false,
diff --git a/src/tools/rust-analyzer/editors/code/src/client.ts b/src/tools/rust-analyzer/editors/code/src/client.ts
index c27a446b380..1cbf247297f 100644
--- a/src/tools/rust-analyzer/editors/code/src/client.ts
+++ b/src/tools/rust-analyzer/editors/code/src/client.ts
@@ -372,13 +372,18 @@ export async function createClient(
     );
 
     // To turn on all proposed features use: client.registerProposedFeatures();
-    client.registerFeature(new ExperimentalFeatures());
+    client.registerFeature(new ExperimentalFeatures(config));
     client.registerFeature(new OverrideFeatures());
 
     return client;
 }
 
 class ExperimentalFeatures implements lc.StaticFeature {
+    private readonly testExplorer: boolean;
+
+    constructor(config: Config) {
+        this.testExplorer = config.testExplorer || false;
+    }
     getState(): lc.FeatureState {
         return { kind: "static" };
     }
@@ -391,6 +396,7 @@ class ExperimentalFeatures implements lc.StaticFeature {
             colorDiagnosticOutput: true,
             openServerLogs: true,
             localDocs: true,
+            testExplorer: this.testExplorer,
             commands: {
                 commands: [
                     "rust-analyzer.runSingle",
diff --git a/src/tools/rust-analyzer/editors/code/src/config.ts b/src/tools/rust-analyzer/editors/code/src/config.ts
index 51a0aece820..92a816bfbcb 100644
--- a/src/tools/rust-analyzer/editors/code/src/config.ts
+++ b/src/tools/rust-analyzer/editors/code/src/config.ts
@@ -266,6 +266,10 @@ export class Config {
         return this.get<string | undefined>("cargoRunner");
     }
 
+    get testExplorer() {
+        return this.get<boolean | undefined>("testExplorer");
+    }
+
     get runnablesExtraEnv() {
         const item = this.get<any>("runnables.extraEnv") ?? this.get<any>("runnableEnv");
         if (!item) return item;
diff --git a/src/tools/rust-analyzer/editors/code/src/ctx.ts b/src/tools/rust-analyzer/editors/code/src/ctx.ts
index 01a3aca1323..f76dec2629a 100644
--- a/src/tools/rust-analyzer/editors/code/src/ctx.ts
+++ b/src/tools/rust-analyzer/editors/code/src/ctx.ts
@@ -24,6 +24,7 @@ import { PersistentState } from "./persistent_state";
 import { bootstrap } from "./bootstrap";
 import type { RustAnalyzerExtensionApi } from "./main";
 import type { JsonProject } from "./rust_project";
+import { prepareTestExplorer } from "./test_explorer";
 
 // We only support local folders, not eg. Live Share (`vlsl:` scheme), so don't activate if
 // only those are in use. We use "Empty" to represent these scenarios
@@ -74,6 +75,7 @@ export class Ctx implements RustAnalyzerExtensionApi {
     private _client: lc.LanguageClient | undefined;
     private _serverPath: string | undefined;
     private traceOutputChannel: vscode.OutputChannel | undefined;
+    private testController: vscode.TestController | undefined;
     private outputChannel: vscode.OutputChannel | undefined;
     private clientSubscriptions: Disposable[];
     private state: PersistentState;
@@ -102,14 +104,20 @@ export class Ctx implements RustAnalyzerExtensionApi {
         workspace: Workspace,
     ) {
         extCtx.subscriptions.push(this);
+        this.config = new Config(extCtx);
         this.statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
+        if (this.config.testExplorer) {
+            this.testController = vscode.tests.createTestController(
+                "rustAnalyzerTestController",
+                "Rust Analyzer test controller",
+            );
+        }
         this.workspace = workspace;
         this.clientSubscriptions = [];
         this.commandDisposables = [];
         this.commandFactories = commandFactories;
         this.unlinkedFiles = [];
         this.state = new PersistentState(extCtx.globalState);
-        this.config = new Config(extCtx);
 
         this.updateCommands("disable");
         this.setServerStatus({
@@ -120,6 +128,7 @@ export class Ctx implements RustAnalyzerExtensionApi {
     dispose() {
         this.config.dispose();
         this.statusBar.dispose();
+        this.testController?.dispose();
         void this.disposeClient();
         this.commandDisposables.forEach((disposable) => disposable.dispose());
     }
@@ -264,6 +273,9 @@ export class Ctx implements RustAnalyzerExtensionApi {
         await client.start();
         this.updateCommands();
 
+        if (this.testController) {
+            prepareTestExplorer(this, this.testController, client);
+        }
         if (this.config.showDependenciesExplorer) {
             this.prepareTreeDependenciesView(client);
         }
@@ -491,7 +503,7 @@ export class Ctx implements RustAnalyzerExtensionApi {
         this.extCtx.subscriptions.push(d);
     }
 
-    private pushClientCleanup(d: Disposable) {
+    pushClientCleanup(d: Disposable) {
         this.clientSubscriptions.push(d);
     }
 }
diff --git a/src/tools/rust-analyzer/editors/code/src/debug.ts b/src/tools/rust-analyzer/editors/code/src/debug.ts
index d9c6b6ac456..3fc63fc7d81 100644
--- a/src/tools/rust-analyzer/editors/code/src/debug.ts
+++ b/src/tools/rust-analyzer/editors/code/src/debug.ts
@@ -81,8 +81,9 @@ async function getDebugConfiguration(
     if (!editor) return;
 
     const knownEngines: Record<string, DebugConfigProvider> = {
-        "vadimcn.vscode-lldb": getLldbDebugConfig,
-        "ms-vscode.cpptools": getCppvsDebugConfig,
+        "ms-vscode.cpptools": getCCppDebugConfig,
+        "vadimcn.vscode-lldb": getCodeLldbDebugConfig,
+        "webfreak.debug": getNativeDebugConfig,
     };
     const debugOptions = ctx.config.debug;
 
@@ -97,12 +98,14 @@ async function getDebugConfiguration(
     }
 
     if (!debugEngine) {
+        const commandCCpp: string = createCommandLink("ms-vscode.cpptools");
         const commandCodeLLDB: string = createCommandLink("vadimcn.vscode-lldb");
-        const commandCpp: string = createCommandLink("ms-vscode.cpptools");
+        const commandNativeDebug: string = createCommandLink("webfreak.debug");
 
         await vscode.window.showErrorMessage(
             `Install [CodeLLDB](command:${commandCodeLLDB} "Open CodeLLDB")` +
-                ` or [C/C++](command:${commandCpp} "Open C/C++") extension for debugging.`,
+                `, [C/C++](command:${commandCCpp} "Open C/C++") ` +
+                `or [Native Debug](command:${commandNativeDebug} "Open Native Debug") for debugging.`,
         );
         return;
     }
@@ -184,7 +187,7 @@ async function getDebugExecutableInfo(
     return executableInfo;
 }
 
-function getLldbDebugConfig(
+function getCCppDebugConfig(
     runnable: ra.Runnable,
     executable: string,
     cargoWorkspace: string,
@@ -192,19 +195,18 @@ function getLldbDebugConfig(
     sourceFileMap?: Record<string, string>,
 ): vscode.DebugConfiguration {
     return {
-        type: "lldb",
+        type: os.platform() === "win32" ? "cppvsdbg" : "cppdbg",
         request: "launch",
         name: runnable.label,
         program: executable,
         args: runnable.args.executableArgs,
         cwd: cargoWorkspace || runnable.args.workspaceRoot,
-        sourceMap: sourceFileMap,
-        sourceLanguages: ["rust"],
+        sourceFileMap,
         env,
     };
 }
 
-function getCppvsDebugConfig(
+function getCodeLldbDebugConfig(
     runnable: ra.Runnable,
     executable: string,
     cargoWorkspace: string,
@@ -212,13 +214,49 @@ function getCppvsDebugConfig(
     sourceFileMap?: Record<string, string>,
 ): vscode.DebugConfiguration {
     return {
-        type: os.platform() === "win32" ? "cppvsdbg" : "cppdbg",
+        type: "lldb",
         request: "launch",
         name: runnable.label,
         program: executable,
         args: runnable.args.executableArgs,
         cwd: cargoWorkspace || runnable.args.workspaceRoot,
-        sourceFileMap,
+        sourceMap: sourceFileMap,
+        sourceLanguages: ["rust"],
         env,
     };
 }
+
+function getNativeDebugConfig(
+    runnable: ra.Runnable,
+    executable: string,
+    cargoWorkspace: string,
+    env: Record<string, string>,
+    _sourceFileMap?: Record<string, string>,
+): vscode.DebugConfiguration {
+    return {
+        type: "gdb",
+        request: "launch",
+        name: runnable.label,
+        target: executable,
+        // See https://github.com/WebFreak001/code-debug/issues/359
+        arguments: quote(runnable.args.executableArgs),
+        cwd: cargoWorkspace || runnable.args.workspaceRoot,
+        env,
+        valuesFormatting: "prettyPrinters",
+    };
+}
+
+// Based on https://github.com/ljharb/shell-quote/blob/main/quote.js
+function quote(xs: string[]) {
+    return xs
+        .map(function (s) {
+            if (/["\s]/.test(s) && !/'/.test(s)) {
+                return "'" + s.replace(/(['\\])/g, "\\$1") + "'";
+            }
+            if (/["'\s]/.test(s)) {
+                return '"' + s.replace(/(["\\$`!])/g, "\\$1") + '"';
+            }
+            return s.replace(/([A-Za-z]:)?([#!"$&'()*,:;<=>?@[\\\]^`{|}])/g, "$1\\$2");
+        })
+        .join(" ");
+}
diff --git a/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts b/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts
index 6c961f53e7e..31ac3d9413e 100644
--- a/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts
+++ b/src/tools/rust-analyzer/editors/code/src/lsp_ext.ts
@@ -68,6 +68,42 @@ export const viewItemTree = new lc.RequestType<ViewItemTreeParams, string, void>
     "rust-analyzer/viewItemTree",
 );
 
+export type DiscoverTestParams = { testId?: string | undefined };
+export type RunTestParams = {
+    include?: string[] | undefined;
+    exclude?: string[] | undefined;
+};
+export type TestItem = {
+    id: string;
+    label: string;
+    kind: "package" | "module" | "test";
+    canResolveChildren: boolean;
+    parent?: string | undefined;
+    textDocument?: lc.TextDocumentIdentifier | undefined;
+    range?: lc.Range | undefined;
+    runnable?: Runnable | undefined;
+};
+export type DiscoverTestResults = { tests: TestItem[]; scope: string[] };
+export type TestState =
+    | { tag: "failed"; message: string }
+    | { tag: "passed" }
+    | { tag: "started" }
+    | { tag: "enqueued" }
+    | { tag: "skipped" };
+export type ChangeTestStateParams = { testId: string; state: TestState };
+export const discoverTest = new lc.RequestType<DiscoverTestParams, DiscoverTestResults, void>(
+    "experimental/discoverTest",
+);
+export const discoveredTests = new lc.NotificationType<DiscoverTestResults>(
+    "experimental/discoveredTests",
+);
+export const runTest = new lc.RequestType<RunTestParams, void, void>("experimental/runTest");
+export const abortRunTest = new lc.NotificationType0("experimental/abortRunTest");
+export const endRunTest = new lc.NotificationType0("experimental/endRunTest");
+export const changeTestState = new lc.NotificationType<ChangeTestStateParams>(
+    "experimental/changeTestState",
+);
+
 export type AnalyzerStatusParams = { textDocument?: lc.TextDocumentIdentifier };
 
 export interface FetchDependencyListParams {}
diff --git a/src/tools/rust-analyzer/editors/code/src/test_explorer.ts b/src/tools/rust-analyzer/editors/code/src/test_explorer.ts
new file mode 100644
index 00000000000..2f0b4d5b5cf
--- /dev/null
+++ b/src/tools/rust-analyzer/editors/code/src/test_explorer.ts
@@ -0,0 +1,173 @@
+import * as vscode from "vscode";
+import type * as lc from "vscode-languageclient/node";
+import * as ra from "./lsp_ext";
+
+import type { Ctx } from "./ctx";
+import { startDebugSession } from "./debug";
+
+export const prepareTestExplorer = (
+    ctx: Ctx,
+    testController: vscode.TestController,
+    client: lc.LanguageClient,
+) => {
+    let currentTestRun: vscode.TestRun | undefined;
+    let idToTestMap: Map<string, vscode.TestItem> = new Map();
+    const idToRunnableMap: Map<string, ra.Runnable> = new Map();
+
+    testController.createRunProfile(
+        "Run Tests",
+        vscode.TestRunProfileKind.Run,
+        async (request: vscode.TestRunRequest, cancelToken: vscode.CancellationToken) => {
+            if (currentTestRun) {
+                await client.sendNotification(ra.abortRunTest);
+                while (currentTestRun) {
+                    await new Promise((resolve) => setTimeout(resolve, 1));
+                }
+            }
+
+            currentTestRun = testController.createTestRun(request);
+            cancelToken.onCancellationRequested(async () => {
+                await client.sendNotification(ra.abortRunTest);
+            });
+            const include = request.include?.map((x) => x.id);
+            const exclude = request.exclude?.map((x) => x.id);
+            await client.sendRequest(ra.runTest, { include, exclude });
+        },
+        true,
+        undefined,
+        false,
+    );
+
+    testController.createRunProfile(
+        "Debug Tests",
+        vscode.TestRunProfileKind.Debug,
+        async (request: vscode.TestRunRequest) => {
+            if (request.include?.length !== 1 || request.exclude?.length !== 0) {
+                await vscode.window.showErrorMessage("You can debug only one test at a time");
+                return;
+            }
+            const id = request.include[0]!.id;
+            const runnable = idToRunnableMap.get(id);
+            if (!runnable) {
+                await vscode.window.showErrorMessage("You can debug only one test at a time");
+                return;
+            }
+            await startDebugSession(ctx, runnable);
+        },
+        true,
+        undefined,
+        false,
+    );
+
+    const addTest = (item: ra.TestItem) => {
+        const parentList = item.parent
+            ? idToTestMap.get(item.parent)!.children
+            : testController.items;
+        const oldTest = parentList.get(item.id);
+        const uri = item.textDocument?.uri ? vscode.Uri.parse(item.textDocument?.uri) : undefined;
+        const range =
+            item.range &&
+            new vscode.Range(
+                new vscode.Position(item.range.start.line, item.range.start.character),
+                new vscode.Position(item.range.end.line, item.range.end.character),
+            );
+        if (oldTest) {
+            if (oldTest.uri?.toString() === uri?.toString()) {
+                oldTest.range = range;
+                return;
+            }
+            parentList.delete(item.id);
+        }
+        const iconToVscodeMap = {
+            package: "package",
+            module: "symbol-module",
+            test: "beaker",
+        };
+        const test = testController.createTestItem(
+            item.id,
+            `$(${iconToVscodeMap[item.kind]}) ${item.label}`,
+            uri,
+        );
+        test.range = range;
+        test.canResolveChildren = item.canResolveChildren;
+        idToTestMap.set(item.id, test);
+        if (item.runnable) {
+            idToRunnableMap.set(item.id, item.runnable);
+        }
+        parentList.add(test);
+    };
+
+    const addTestGroup = (testsAndScope: ra.DiscoverTestResults) => {
+        const { tests, scope } = testsAndScope;
+        const testSet: Set<string> = new Set();
+        for (const test of tests) {
+            addTest(test);
+            testSet.add(test.id);
+        }
+        // FIXME(hack_recover_crate_name): We eagerly resolve every test if we got a lazy top level response (detected
+        // by `!scope`). ctx is not a good thing and wastes cpu and memory unnecessarily, so we should remove it.
+        if (!scope) {
+            for (const test of tests) {
+                void testController.resolveHandler!(idToTestMap.get(test.id));
+            }
+        }
+        if (!scope) {
+            return;
+        }
+        const recursivelyRemove = (tests: vscode.TestItemCollection) => {
+            for (const [testId, _] of tests) {
+                if (!testSet.has(testId)) {
+                    tests.delete(testId);
+                } else {
+                    recursivelyRemove(tests.get(testId)!.children);
+                }
+            }
+        };
+        for (const root of scope) {
+            recursivelyRemove(idToTestMap.get(root)!.children);
+        }
+    };
+
+    ctx.pushClientCleanup(
+        client.onNotification(ra.discoveredTests, (results) => {
+            addTestGroup(results);
+        }),
+    );
+
+    ctx.pushClientCleanup(
+        client.onNotification(ra.endRunTest, () => {
+            currentTestRun!.end();
+            currentTestRun = undefined;
+        }),
+    );
+
+    ctx.pushClientCleanup(
+        client.onNotification(ra.changeTestState, (results) => {
+            const test = idToTestMap.get(results.testId)!;
+            if (results.state.tag === "failed") {
+                currentTestRun!.failed(test, new vscode.TestMessage(results.state.message));
+            } else if (results.state.tag === "passed") {
+                currentTestRun!.passed(test);
+            } else if (results.state.tag === "started") {
+                currentTestRun!.started(test);
+            } else if (results.state.tag === "skipped") {
+                currentTestRun!.skipped(test);
+            } else if (results.state.tag === "enqueued") {
+                currentTestRun!.enqueued(test);
+            }
+        }),
+    );
+
+    testController.resolveHandler = async (item) => {
+        const results = await client.sendRequest(ra.discoverTest, { testId: item?.id });
+        addTestGroup(results);
+    };
+
+    testController.refreshHandler = async () => {
+        testController.items.forEach((t) => {
+            testController.items.delete(t.id);
+        });
+        idToTestMap = new Map();
+        await testController.resolveHandler!(undefined);
+    };
+};
diff --git a/src/tools/rust-analyzer/lib/line-index/Cargo.toml b/src/tools/rust-analyzer/lib/line-index/Cargo.toml
index 77e187de1ed..8ae4954dd0d 100644
--- a/src/tools/rust-analyzer/lib/line-index/Cargo.toml
+++ b/src/tools/rust-analyzer/lib/line-index/Cargo.toml
@@ -10,5 +10,8 @@ edition = "2021"
 text-size = "1.1.1"
 nohash-hasher = "0.2.0"
 
+[dev-dependencies]
+oorandom = "11.1.3"
+
 [lints]
-workspace = true
\ No newline at end of file
+workspace = true
diff --git a/src/tools/rust-analyzer/lib/line-index/src/tests.rs b/src/tools/rust-analyzer/lib/line-index/src/tests.rs
index 981008e346b..57fad1dfc05 100644
--- a/src/tools/rust-analyzer/lib/line-index/src/tests.rs
+++ b/src/tools/rust-analyzer/lib/line-index/src/tests.rs
@@ -142,3 +142,56 @@ fn test_to_wide() {
     let wide_line_col = line_index.to_wide(WideEncoding::Utf16, line_col.unwrap());
     assert_eq!(wide_line_col, Some(WideLineCol { line: 5, col: 4 }));
 }
+
+#[test]
+fn test_every_chars() {
+    let text: String = {
+        let mut chars: Vec<char> = ((0 as char)..char::MAX).collect(); // Neat!
+        chars.extend("\n".repeat(chars.len() / 16).chars());
+        let seed = std::hash::Hasher::finish(&std::hash::BuildHasher::build_hasher(
+            #[allow(clippy::disallowed_types)]
+            &std::collections::hash_map::RandomState::new(),
+        ));
+        let mut rng = oorandom::Rand32::new(seed);
+        let mut rand_index = |i| rng.rand_range(0..i as u32) as usize;
+        let mut remaining = chars.len() - 1;
+        while remaining > 0 {
+            let index = rand_index(remaining);
+            chars.swap(remaining, index);
+            remaining -= 1;
+        }
+        chars.into_iter().collect()
+    };
+    assert!(text.contains('💩')); // Sanity check.
+
+    let line_index = LineIndex::new(&text);
+
+    let mut lin_col = LineCol { line: 0, col: 0 };
+    let mut col_utf16 = 0;
+    let mut col_utf32 = 0;
+    for (offset, c) in text.char_indices() {
+        let got_offset = line_index.offset(lin_col).unwrap();
+        assert_eq!(usize::from(got_offset), offset);
+
+        let got_lin_col = line_index.line_col(got_offset);
+        assert_eq!(got_lin_col, lin_col);
+
+        for (enc, col) in [(WideEncoding::Utf16, col_utf16), (WideEncoding::Utf32, col_utf32)] {
+            let wide_lin_col = line_index.to_wide(enc, lin_col).unwrap();
+            let got_lin_col = line_index.to_utf8(enc, wide_lin_col).unwrap();
+            assert_eq!(got_lin_col, lin_col);
+            assert_eq!(wide_lin_col.col, col)
+        }
+
+        if c == '\n' {
+            lin_col.line += 1;
+            lin_col.col = 0;
+            col_utf16 = 0;
+            col_utf32 = 0;
+        } else {
+            lin_col.col += c.len_utf8() as u32;
+            col_utf16 += c.len_utf16() as u32;
+            col_utf32 += 1;
+        }
+    }
+}
diff --git a/src/tools/rust-analyzer/lib/lsp-server/src/req_queue.rs b/src/tools/rust-analyzer/lib/lsp-server/src/req_queue.rs
index 7b47f5388b5..347a9fb6fb9 100644
--- a/src/tools/rust-analyzer/lib/lsp-server/src/req_queue.rs
+++ b/src/tools/rust-analyzer/lib/lsp-server/src/req_queue.rs
@@ -37,7 +37,7 @@ impl<I> Incoming<I> {
     }
 
     pub fn cancel(&mut self, id: RequestId) -> Option<Response> {
-        let _data = self.complete(id.clone())?;
+        let _data = self.complete(&id)?;
         let error = ResponseError {
             code: ErrorCode::RequestCanceled as i32,
             message: "canceled by client".to_owned(),
@@ -46,8 +46,8 @@ impl<I> Incoming<I> {
         Some(Response { id, result: None, error: Some(error) })
     }
 
-    pub fn complete(&mut self, id: RequestId) -> Option<I> {
-        self.pending.remove(&id)
+    pub fn complete(&mut self, id: &RequestId) -> Option<I> {
+        self.pending.remove(id)
     }
 
     pub fn is_completed(&self, id: &RequestId) -> bool {
diff --git a/src/tools/rust-analyzer/xtask/Cargo.toml b/src/tools/rust-analyzer/xtask/Cargo.toml
index 863a63ac82e..5e758e0190c 100644
--- a/src/tools/rust-analyzer/xtask/Cargo.toml
+++ b/src/tools/rust-analyzer/xtask/Cargo.toml
@@ -14,7 +14,8 @@ xshell.workspace = true
 xflags = "0.3.0"
 time = { version = "0.3", default-features = false }
 zip = { version = "0.6", default-features = false, features = ["deflate", "time"] }
+stdx.workspace = true
 # Avoid adding more dependencies to this crate
 
 [lints]
-workspace = true
\ No newline at end of file
+workspace = true
diff --git a/src/tools/rust-analyzer/xtask/src/codegen.rs b/src/tools/rust-analyzer/xtask/src/codegen.rs
new file mode 100644
index 00000000000..40f872a24ab
--- /dev/null
+++ b/src/tools/rust-analyzer/xtask/src/codegen.rs
@@ -0,0 +1,218 @@
+use std::{
+    fmt, fs, mem,
+    path::{Path, PathBuf},
+};
+
+use xshell::{cmd, Shell};
+
+use crate::{flags, project_root};
+
+pub(crate) mod assists_doc_tests;
+pub(crate) mod diagnostics_docs;
+mod lints;
+
+impl flags::Codegen {
+    pub(crate) fn run(self, _sh: &Shell) -> anyhow::Result<()> {
+        match self.codegen_type.unwrap_or_default() {
+            flags::CodegenType::All => {
+                diagnostics_docs::generate(self.check);
+                assists_doc_tests::generate(self.check);
+                // lints::generate(self.check) Updating clones the rust repo, so don't run it unless
+                // explicitly asked for
+            }
+            flags::CodegenType::AssistsDocTests => assists_doc_tests::generate(self.check),
+            flags::CodegenType::DiagnosticsDocs => diagnostics_docs::generate(self.check),
+            flags::CodegenType::LintDefinitions => lints::generate(self.check),
+        }
+        Ok(())
+    }
+}
+
+fn list_rust_files(dir: &Path) -> Vec<PathBuf> {
+    let mut res = list_files(dir);
+    res.retain(|it| {
+        it.file_name().unwrap_or_default().to_str().unwrap_or_default().ends_with(".rs")
+    });
+    res
+}
+
+fn list_files(dir: &Path) -> Vec<PathBuf> {
+    let mut res = Vec::new();
+    let mut work = vec![dir.to_path_buf()];
+    while let Some(dir) = work.pop() {
+        for entry in dir.read_dir().unwrap() {
+            let entry = entry.unwrap();
+            let file_type = entry.file_type().unwrap();
+            let path = entry.path();
+            let is_hidden =
+                path.file_name().unwrap_or_default().to_str().unwrap_or_default().starts_with('.');
+            if !is_hidden {
+                if file_type.is_dir() {
+                    work.push(path);
+                } else if file_type.is_file() {
+                    res.push(path);
+                }
+            }
+        }
+    }
+    res
+}
+
+#[derive(Clone)]
+pub(crate) struct CommentBlock {
+    pub(crate) id: String,
+    pub(crate) line: usize,
+    pub(crate) contents: Vec<String>,
+    is_doc: bool,
+}
+
+impl CommentBlock {
+    fn extract(tag: &str, text: &str) -> Vec<CommentBlock> {
+        assert!(tag.starts_with(char::is_uppercase));
+
+        let tag = format!("{tag}:");
+        let mut blocks = CommentBlock::extract_untagged(text);
+        blocks.retain_mut(|block| {
+            let first = block.contents.remove(0);
+            let Some(id) = first.strip_prefix(&tag) else {
+                return false;
+            };
+
+            if block.is_doc {
+                panic!("Use plain (non-doc) comments with tags like {tag}:\n    {first}");
+            }
+
+            block.id = id.trim().to_owned();
+            true
+        });
+        blocks
+    }
+
+    fn extract_untagged(text: &str) -> Vec<CommentBlock> {
+        let mut res = Vec::new();
+
+        let lines = text.lines().map(str::trim_start);
+
+        let dummy_block =
+            CommentBlock { id: String::new(), line: 0, contents: Vec::new(), is_doc: false };
+        let mut block = dummy_block.clone();
+        for (line_num, line) in lines.enumerate() {
+            match line.strip_prefix("//") {
+                Some(mut contents) => {
+                    if let Some('/' | '!') = contents.chars().next() {
+                        contents = &contents[1..];
+                        block.is_doc = true;
+                    }
+                    if let Some(' ') = contents.chars().next() {
+                        contents = &contents[1..];
+                    }
+                    block.contents.push(contents.to_owned());
+                }
+                None => {
+                    if !block.contents.is_empty() {
+                        let block = mem::replace(&mut block, dummy_block.clone());
+                        res.push(block);
+                    }
+                    block.line = line_num + 2;
+                }
+            }
+        }
+        if !block.contents.is_empty() {
+            res.push(block);
+        }
+        res
+    }
+}
+
+#[derive(Debug)]
+pub(crate) struct Location {
+    pub(crate) file: PathBuf,
+    pub(crate) line: usize,
+}
+
+impl fmt::Display for Location {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let path = self.file.strip_prefix(project_root()).unwrap().display().to_string();
+        let path = path.replace('\\', "/");
+        let name = self.file.file_name().unwrap();
+        write!(
+            f,
+            "https://github.com/rust-lang/rust-analyzer/blob/master/{}#L{}[{}]",
+            path,
+            self.line,
+            name.to_str().unwrap()
+        )
+    }
+}
+
+fn ensure_rustfmt(sh: &Shell) {
+    let version = cmd!(sh, "rustup run stable rustfmt --version").read().unwrap_or_default();
+    if !version.contains("stable") {
+        panic!(
+            "Failed to run rustfmt from toolchain 'stable'. \
+                 Please run `rustup component add rustfmt --toolchain stable` to install it.",
+        );
+    }
+}
+
+fn reformat(text: String) -> String {
+    let sh = Shell::new().unwrap();
+    ensure_rustfmt(&sh);
+    let rustfmt_toml = project_root().join("rustfmt.toml");
+    let mut stdout = cmd!(
+        sh,
+        "rustup run stable rustfmt --config-path {rustfmt_toml} --config fn_single_line=true"
+    )
+    .stdin(text)
+    .read()
+    .unwrap();
+    if !stdout.ends_with('\n') {
+        stdout.push('\n');
+    }
+    stdout
+}
+
+fn add_preamble(generator: &'static str, mut text: String) -> String {
+    let preamble = format!("//! Generated by `{generator}`, do not edit by hand.\n\n");
+    text.insert_str(0, &preamble);
+    text
+}
+
+/// Checks that the `file` has the specified `contents`. If that is not the
+/// case, updates the file and then fails the test.
+#[allow(clippy::print_stderr)]
+fn ensure_file_contents(file: &Path, contents: &str, check: bool) {
+    if let Ok(old_contents) = fs::read_to_string(file) {
+        if normalize_newlines(&old_contents) == normalize_newlines(contents) {
+            // File is already up to date.
+            return;
+        }
+    }
+
+    let display_path = file.strip_prefix(project_root()).unwrap_or(file);
+    if check {
+        panic!(
+            "{} was not up-to-date{}",
+            file.display(),
+            if std::env::var("CI").is_ok() {
+                "\n    NOTE: run `cargo codegen` locally and commit the updated files\n"
+            } else {
+                ""
+            }
+        );
+    } else {
+        eprintln!(
+            "\n\x1b[31;1merror\x1b[0m: {} was not up-to-date, updating\n",
+            display_path.display()
+        );
+
+        if let Some(parent) = file.parent() {
+            let _ = fs::create_dir_all(parent);
+        }
+        fs::write(file, contents).unwrap();
+    }
+}
+
+fn normalize_newlines(s: &str) -> String {
+    s.replace("\r\n", "\n")
+}
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/tests/sourcegen.rs b/src/tools/rust-analyzer/xtask/src/codegen/assists_doc_tests.rs
index 847cb1af51e..b2d89dde765 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/tests/sourcegen.rs
+++ b/src/tools/rust-analyzer/xtask/src/codegen/assists_doc_tests.rs
@@ -3,10 +3,15 @@
 use std::{fmt, fs, path::Path};
 
 use stdx::format_to_acc;
-use test_utils::project_root;
 
-#[test]
-fn sourcegen_assists_docs() {
+use crate::{
+    codegen::{
+        add_preamble, ensure_file_contents, list_rust_files, reformat, CommentBlock, Location,
+    },
+    project_root,
+};
+
+pub(crate) fn generate(check: bool) {
     let assists = Assist::collect();
 
     {
@@ -40,10 +45,11 @@ r#####"
                 buf.push_str(&test)
             }
         }
-        let buf = sourcegen::add_preamble("sourcegen_assists_docs", sourcegen::reformat(buf));
-        sourcegen::ensure_file_contents(
+        let buf = add_preamble("sourcegen_assists_docs", reformat(buf));
+        ensure_file_contents(
             &project_root().join("crates/ide-assists/src/tests/generated.rs"),
             &buf,
+            check,
         );
     }
 
@@ -52,7 +58,7 @@ r#####"
         // git repo. Instead, `cargo xtask release` runs this test before making
         // a release.
 
-        let contents = sourcegen::add_preamble(
+        let contents = add_preamble(
             "sourcegen_assists_docs",
             assists.into_iter().map(|it| it.to_string()).collect::<Vec<_>>().join("\n\n"),
         );
@@ -71,7 +77,7 @@ struct Section {
 #[derive(Debug)]
 struct Assist {
     id: String,
-    location: sourcegen::Location,
+    location: Location,
     sections: Vec<Section>,
 }
 
@@ -80,7 +86,7 @@ impl Assist {
         let handlers_dir = project_root().join("crates/ide-assists/src/handlers");
 
         let mut res = Vec::new();
-        for path in sourcegen::list_rust_files(&handlers_dir) {
+        for path in list_rust_files(&handlers_dir) {
             collect_file(&mut res, path.as_path());
         }
         res.sort_by(|lhs, rhs| lhs.id.cmp(&rhs.id));
@@ -88,7 +94,7 @@ impl Assist {
 
         fn collect_file(acc: &mut Vec<Assist>, path: &Path) {
             let text = fs::read_to_string(path).unwrap();
-            let comment_blocks = sourcegen::CommentBlock::extract("Assist", &text);
+            let comment_blocks = CommentBlock::extract("Assist", &text);
 
             for block in comment_blocks {
                 let id = block.id;
@@ -97,7 +103,7 @@ impl Assist {
                     "invalid assist id: {id:?}"
                 );
                 let mut lines = block.contents.iter().peekable();
-                let location = sourcegen::Location { file: path.to_path_buf(), line: block.line };
+                let location = Location { file: path.to_path_buf(), line: block.line };
                 let mut assist = Assist { id, location, sections: Vec::new() };
 
                 while lines.peek().is_some() {
diff --git a/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests/sourcegen.rs b/src/tools/rust-analyzer/xtask/src/codegen/diagnostics_docs.rs
index 9e7fcfc590b..cf30531e7f9 100644
--- a/src/tools/rust-analyzer/crates/ide-diagnostics/src/tests/sourcegen.rs
+++ b/src/tools/rust-analyzer/xtask/src/codegen/diagnostics_docs.rs
@@ -2,22 +2,26 @@
 
 use std::{fmt, fs, io, path::PathBuf};
 
-use sourcegen::project_root;
+use crate::{
+    codegen::{add_preamble, list_rust_files, CommentBlock, Location},
+    project_root,
+};
 
-#[test]
-fn sourcegen_diagnostic_docs() {
+pub(crate) fn generate(check: bool) {
     let diagnostics = Diagnostic::collect().unwrap();
-    let contents =
-        diagnostics.into_iter().map(|it| it.to_string()).collect::<Vec<_>>().join("\n\n");
-    let contents = sourcegen::add_preamble("sourcegen_diagnostic_docs", contents);
-    let dst = project_root().join("docs/user/generated_diagnostic.adoc");
-    fs::write(dst, contents).unwrap();
+    if !check {
+        let contents =
+            diagnostics.into_iter().map(|it| it.to_string()).collect::<Vec<_>>().join("\n\n");
+        let contents = add_preamble("sourcegen_diagnostic_docs", contents);
+        let dst = project_root().join("docs/user/generated_diagnostic.adoc");
+        fs::write(dst, contents).unwrap();
+    }
 }
 
 #[derive(Debug)]
 struct Diagnostic {
     id: String,
-    location: sourcegen::Location,
+    location: Location,
     doc: String,
 }
 
@@ -26,7 +30,7 @@ impl Diagnostic {
         let handlers_dir = project_root().join("crates/ide-diagnostics/src/handlers");
 
         let mut res = Vec::new();
-        for path in sourcegen::list_rust_files(&handlers_dir) {
+        for path in list_rust_files(&handlers_dir) {
             collect_file(&mut res, path)?;
         }
         res.sort_by(|lhs, rhs| lhs.id.cmp(&rhs.id));
@@ -34,7 +38,7 @@ impl Diagnostic {
 
         fn collect_file(acc: &mut Vec<Diagnostic>, path: PathBuf) -> io::Result<()> {
             let text = fs::read_to_string(&path)?;
-            let comment_blocks = sourcegen::CommentBlock::extract("Diagnostic", &text);
+            let comment_blocks = CommentBlock::extract("Diagnostic", &text);
 
             for block in comment_blocks {
                 let id = block.id;
@@ -42,7 +46,7 @@ impl Diagnostic {
                     panic!("invalid diagnostic name: {id:?}:\n  {msg}")
                 }
                 let doc = block.contents.join("\n");
-                let location = sourcegen::Location { file: path.clone(), line: block.line };
+                let location = Location { file: path.clone(), line: block.line };
                 acc.push(Diagnostic { id, location, doc })
             }
 
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/tests/sourcegen_lints.rs b/src/tools/rust-analyzer/xtask/src/codegen/lints.rs
index 86ed01c8e74..63abcfc0904 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/tests/sourcegen_lints.rs
+++ b/src/tools/rust-analyzer/xtask/src/codegen/lints.rs
@@ -2,18 +2,18 @@
 //! and lints from rustc, rustdoc, and clippy.
 use std::{borrow::Cow, fs, path::Path};
 
-use itertools::Itertools;
 use stdx::format_to;
-use test_utils::project_root;
 use xshell::{cmd, Shell};
 
+use crate::{
+    codegen::{add_preamble, ensure_file_contents, list_files, reformat},
+    project_root,
+};
+
 const DESTINATION: &str = "crates/ide-db/src/generated/lints.rs";
 
-/// This clones rustc repo, and so is not worth to keep up-to-date. We update
-/// manually by un-ignoring the test from time to time.
-#[test]
-#[ignore]
-fn sourcegen_lint_completions() {
+/// This clones rustc repo, and so is not worth to keep up-to-date on a constant basis.
+pub(crate) fn generate(check: bool) {
     let sh = &Shell::new().unwrap();
 
     let rust_repo = project_root().join("./target/rust");
@@ -73,10 +73,10 @@ pub struct LintGroup {
     .unwrap();
     generate_descriptor_clippy(&mut contents, &lints_json);
 
-    let contents = sourcegen::add_preamble("sourcegen_lints", sourcegen::reformat(contents));
+    let contents = add_preamble("sourcegen_lints", reformat(contents));
 
     let destination = project_root().join(DESTINATION);
-    sourcegen::ensure_file_contents(destination.as_path(), &contents);
+    ensure_file_contents(destination.as_path(), &contents, check);
 }
 
 /// Parses the output of `rustdoc -Whelp` and prints `Lint` and `LintGroup` constants into `buf`.
@@ -130,10 +130,9 @@ fn generate_lint_descriptor(sh: &Shell, buf: &mut String) {
         )
     });
 
-    let lints = lints
-        .chain(lint_groups)
-        .sorted_by(|(ident, ..), (ident2, ..)| ident.cmp(ident2))
-        .collect::<Vec<_>>();
+    let mut lints = lints.chain(lint_groups).collect::<Vec<_>>();
+    lints.sort_by(|(ident, ..), (ident2, ..)| ident.cmp(ident2));
+
     for (name, description, ..) in &lints {
         push_lint_completion(buf, &name.replace('-', "_"), description);
     }
@@ -177,10 +176,8 @@ fn generate_lint_descriptor(sh: &Shell, buf: &mut String) {
             )
         });
 
-    let lints_rustdoc = lints_rustdoc
-        .chain(lint_groups_rustdoc)
-        .sorted_by(|(ident, ..), (ident2, ..)| ident.cmp(ident2))
-        .collect::<Vec<_>>();
+    let mut lints_rustdoc = lints_rustdoc.chain(lint_groups_rustdoc).collect::<Vec<_>>();
+    lints_rustdoc.sort_by(|(ident, ..), (ident2, ..)| ident.cmp(ident2));
 
     for (name, description, ..) in &lints_rustdoc {
         push_lint_completion(buf, &name.replace('-', "_"), description)
@@ -212,7 +209,7 @@ fn find_and_slice<'a>(i: &'a str, p: &str) -> &'a str {
 fn generate_feature_descriptor(buf: &mut String, src_dir: &Path) {
     let mut features = ["language-features", "library-features"]
         .into_iter()
-        .flat_map(|it| sourcegen::list_files(&src_dir.join(it)))
+        .flat_map(|it| list_files(&src_dir.join(it)))
         // Get all `.md` files
         .filter(|path| path.extension() == Some("md".as_ref()))
         .map(|path| {
@@ -302,7 +299,7 @@ fn generate_descriptor_clippy(buf: &mut String, path: &Path) {
         let children = children.iter().map(|id| format!("clippy::{id}")).collect::<Vec<_>>();
         if !children.is_empty() {
             let lint_ident = format!("clippy::{id}");
-            let description = format!("lint group for: {}", children.iter().join(", "));
+            let description = format!("lint group for: {}", children.join(", "));
             push_lint_group(buf, &lint_ident, &description, &children);
         }
     }
@@ -331,7 +328,10 @@ fn push_lint_group(buf: &mut String, label: &str, description: &str, children: &
 
     push_lint_completion(buf, label, description);
 
-    let children = format!("&[{}]", children.iter().map(|it| format!("\"{it}\"")).join(", "));
+    let children = format!(
+        "&[{}]",
+        children.iter().map(|it| format!("\"{it}\"")).collect::<Vec<_>>().join(", ")
+    );
     format_to!(
         buf,
         r###"
diff --git a/src/tools/rust-analyzer/xtask/src/flags.rs b/src/tools/rust-analyzer/xtask/src/flags.rs
index e234090a07c..681c588bd01 100644
--- a/src/tools/rust-analyzer/xtask/src/flags.rs
+++ b/src/tools/rust-analyzer/xtask/src/flags.rs
@@ -52,6 +52,11 @@ xflags::xflags! {
         cmd bb {
             required suffix: String
         }
+
+        cmd codegen {
+            optional codegen_type: CodegenType
+            optional --check
+        }
     }
 }
 
@@ -73,8 +78,36 @@ pub enum XtaskCmd {
     PublishReleaseNotes(PublishReleaseNotes),
     Metrics(Metrics),
     Bb(Bb),
+    Codegen(Codegen),
+}
+
+#[derive(Debug)]
+pub struct Codegen {
+    pub check: bool,
+    pub codegen_type: Option<CodegenType>,
+}
+
+#[derive(Debug, Default)]
+pub enum CodegenType {
+    #[default]
+    All,
+    AssistsDocTests,
+    DiagnosticsDocs,
+    LintDefinitions,
 }
 
+impl FromStr for CodegenType {
+    type Err = String;
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match s {
+            "all" => Ok(Self::All),
+            "assists-doc-tests" => Ok(Self::AssistsDocTests),
+            "diagnostics-docs" => Ok(Self::DiagnosticsDocs),
+            "lints-definitions" => Ok(Self::LintDefinitions),
+            _ => Err("Invalid option".to_owned()),
+        }
+    }
+}
 #[derive(Debug)]
 pub struct Install {
     pub client: bool,
diff --git a/src/tools/rust-analyzer/xtask/src/main.rs b/src/tools/rust-analyzer/xtask/src/main.rs
index df4d9810e6f..9418675a348 100644
--- a/src/tools/rust-analyzer/xtask/src/main.rs
+++ b/src/tools/rust-analyzer/xtask/src/main.rs
@@ -13,6 +13,7 @@
 
 mod flags;
 
+mod codegen;
 mod dist;
 mod install;
 mod metrics;
@@ -20,10 +21,7 @@ mod publish;
 mod release;
 
 use anyhow::bail;
-use std::{
-    env,
-    path::{Path, PathBuf},
-};
+use std::{env, path::PathBuf};
 use xshell::{cmd, Shell};
 
 fn main() -> anyhow::Result<()> {
@@ -40,6 +38,7 @@ fn main() -> anyhow::Result<()> {
         flags::XtaskCmd::Dist(cmd) => cmd.run(sh),
         flags::XtaskCmd::PublishReleaseNotes(cmd) => cmd.run(sh),
         flags::XtaskCmd::Metrics(cmd) => cmd.run(sh),
+        flags::XtaskCmd::Codegen(cmd) => cmd.run(sh),
         flags::XtaskCmd::Bb(cmd) => {
             {
                 let _d = sh.push_dir("./crates/rust-analyzer");
@@ -54,14 +53,11 @@ fn main() -> anyhow::Result<()> {
     }
 }
 
+/// Returns the path to the root directory of `rust-analyzer` project.
 fn project_root() -> PathBuf {
-    Path::new(
-        &env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| env!("CARGO_MANIFEST_DIR").to_owned()),
-    )
-    .ancestors()
-    .nth(1)
-    .unwrap()
-    .to_path_buf()
+    let dir =
+        env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| env!("CARGO_MANIFEST_DIR").to_owned());
+    PathBuf::from(dir).parent().unwrap().to_owned()
 }
 
 fn run_fuzzer(sh: &Shell) -> anyhow::Result<()> {
diff --git a/src/tools/rust-analyzer/xtask/src/release.rs b/src/tools/rust-analyzer/xtask/src/release.rs
index 4a306914778..1a5e6dfb4cc 100644
--- a/src/tools/rust-analyzer/xtask/src/release.rs
+++ b/src/tools/rust-analyzer/xtask/src/release.rs
@@ -2,7 +2,7 @@ mod changelog;
 
 use xshell::{cmd, Shell};
 
-use crate::{date_iso, flags, is_release_tag, project_root};
+use crate::{codegen, date_iso, flags, is_release_tag, project_root};
 
 impl flags::Release {
     pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> {
@@ -23,8 +23,8 @@ impl flags::Release {
         }
 
         // Generates bits of manual.adoc.
-        cmd!(sh, "cargo test -p ide-assists -p ide-diagnostics -p rust-analyzer -- sourcegen_")
-            .run()?;
+        codegen::diagnostics_docs::generate(false);
+        codegen::assists_doc_tests::generate(false);
 
         let website_root = project_root().join("../rust-analyzer.github.io");
         {
diff --git a/src/tools/tidy/src/fluent_alphabetical.rs b/src/tools/tidy/src/fluent_alphabetical.rs
index 67b745373f0..9803b6eab2d 100644
--- a/src/tools/tidy/src/fluent_alphabetical.rs
+++ b/src/tools/tidy/src/fluent_alphabetical.rs
@@ -1,6 +1,7 @@
 //! Checks that all Flunt files have messages in alphabetical order
 
 use crate::walk::{filter_dirs, walk};
+use std::collections::HashMap;
 use std::{fs::OpenOptions, io::Write, path::Path};
 
 use regex::Regex;
@@ -13,11 +14,27 @@ fn filter_fluent(path: &Path) -> bool {
     if let Some(ext) = path.extension() { ext.to_str() != Some("ftl") } else { true }
 }
 
-fn check_alphabetic(filename: &str, fluent: &str, bad: &mut bool) {
+fn check_alphabetic(
+    filename: &str,
+    fluent: &str,
+    bad: &mut bool,
+    all_defined_msgs: &mut HashMap<String, String>,
+) {
     let mut matches = MESSAGE.captures_iter(fluent).peekable();
     while let Some(m) = matches.next() {
+        let name = m.get(1).unwrap();
+        if let Some(defined_filename) = all_defined_msgs.get(name.as_str()) {
+            tidy_error!(
+                bad,
+                "{filename}: message `{}` is already defined in {}",
+                name.as_str(),
+                defined_filename,
+            );
+        }
+
+        all_defined_msgs.insert(name.as_str().to_owned(), filename.to_owned());
+
         if let Some(next) = matches.peek() {
-            let name = m.get(1).unwrap();
             let next = next.get(1).unwrap();
             if name.as_str() > next.as_str() {
                 tidy_error!(
@@ -34,13 +51,29 @@ run `./x.py test tidy --bless` to sort the file correctly",
     }
 }
 
-fn sort_messages(fluent: &str) -> String {
+fn sort_messages(
+    filename: &str,
+    fluent: &str,
+    bad: &mut bool,
+    all_defined_msgs: &mut HashMap<String, String>,
+) -> String {
     let mut chunks = vec![];
     let mut cur = String::new();
     for line in fluent.lines() {
-        if MESSAGE.is_match(line) {
+        if let Some(name) = MESSAGE.find(line) {
+            if let Some(defined_filename) = all_defined_msgs.get(name.as_str()) {
+                tidy_error!(
+                    bad,
+                    "{filename}: message `{}` is already defined in {}",
+                    name.as_str(),
+                    defined_filename,
+                );
+            }
+
+            all_defined_msgs.insert(name.as_str().to_owned(), filename.to_owned());
             chunks.push(std::mem::take(&mut cur));
         }
+
         cur += line;
         cur.push('\n');
     }
@@ -53,20 +86,33 @@ fn sort_messages(fluent: &str) -> String {
 }
 
 pub fn check(path: &Path, bless: bool, bad: &mut bool) {
+    let mut all_defined_msgs = HashMap::new();
     walk(
         path,
         |path, is_dir| filter_dirs(path) || (!is_dir && filter_fluent(path)),
         &mut |ent, contents| {
             if bless {
-                let sorted = sort_messages(contents);
+                let sorted = sort_messages(
+                    ent.path().to_str().unwrap(),
+                    contents,
+                    bad,
+                    &mut all_defined_msgs,
+                );
                 if sorted != contents {
                     let mut f =
                         OpenOptions::new().write(true).truncate(true).open(ent.path()).unwrap();
                     f.write(sorted.as_bytes()).unwrap();
                 }
             } else {
-                check_alphabetic(ent.path().to_str().unwrap(), contents, bad);
+                check_alphabetic(
+                    ent.path().to_str().unwrap(),
+                    contents,
+                    bad,
+                    &mut all_defined_msgs,
+                );
             }
         },
     );
+
+    crate::fluent_used::check(path, all_defined_msgs, bad);
 }
diff --git a/src/tools/tidy/src/fluent_used.rs b/src/tools/tidy/src/fluent_used.rs
new file mode 100644
index 00000000000..b73e79cb38d
--- /dev/null
+++ b/src/tools/tidy/src/fluent_used.rs
@@ -0,0 +1,43 @@
+//! Checks that all Fluent messages appear at least twice
+
+use crate::walk::{filter_dirs, walk};
+use regex::Regex;
+use std::collections::HashMap;
+use std::path::Path;
+
+lazy_static::lazy_static! {
+    static ref WORD: Regex = Regex::new(r"\w+").unwrap();
+}
+
+fn filter_used_messages(
+    contents: &str,
+    msgs_not_appeared_yet: &mut HashMap<String, String>,
+    msgs_appeared_only_once: &mut HashMap<String, String>,
+) {
+    // we don't just check messages never appear in Rust files,
+    // because messages can be used as parts of other fluent messages in Fluent files,
+    // so we do checking messages appear only once in all Rust and Fluent files.
+    let mut matches = WORD.find_iter(contents);
+    while let Some(name) = matches.next() {
+        if let Some((name, filename)) = msgs_not_appeared_yet.remove_entry(name.as_str()) {
+            // if one msg appears for the first time,
+            // remove it from `msgs_not_appeared_yet` and insert it into `msgs_appeared_only_once`.
+            msgs_appeared_only_once.insert(name, filename);
+        } else {
+            // if one msg appears for the second time,
+            // remove it from `msgs_appeared_only_once`.
+            msgs_appeared_only_once.remove(name.as_str());
+        }
+    }
+}
+
+pub fn check(path: &Path, mut all_defined_msgs: HashMap<String, String>, bad: &mut bool) {
+    let mut msgs_appear_only_once = HashMap::new();
+    walk(path, |path, _| filter_dirs(path), &mut |_, contents| {
+        filter_used_messages(contents, &mut all_defined_msgs, &mut msgs_appear_only_once);
+    });
+
+    for (name, filename) in msgs_appear_only_once {
+        tidy_error!(bad, "{filename}: message `{}` is not used", name,);
+    }
+}
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index 6f3ade0ab58..670b7eb2be9 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -65,6 +65,7 @@ pub mod ext_tool_checks;
 pub mod extdeps;
 pub mod features;
 pub mod fluent_alphabetical;
+mod fluent_used;
 pub(crate) mod iter_header;
 pub mod mir_opt_tests;
 pub mod pal;
diff --git a/tests/assembly/nvptx-arch-default.rs b/tests/assembly/nvptx-arch-default.rs
index bac09574f17..a621fd6dcb2 100644
--- a/tests/assembly/nvptx-arch-default.rs
+++ b/tests/assembly/nvptx-arch-default.rs
@@ -1,7 +1,6 @@
 //@ assembly-output: ptx-linker
-//@ compile-flags: --crate-type cdylib
+//@ compile-flags: --crate-type cdylib -Z unstable-options -Clinker-flavor=llbc
 //@ only-nvptx64
-//@ ignore-nvptx64
 
 #![no_std]
 
diff --git a/tests/assembly/nvptx-arch-emit-asm.rs b/tests/assembly/nvptx-arch-emit-asm.rs
index d24035cc831..e47f8e78e36 100644
--- a/tests/assembly/nvptx-arch-emit-asm.rs
+++ b/tests/assembly/nvptx-arch-emit-asm.rs
@@ -1,7 +1,6 @@
 //@ assembly-output: emit-asm
 //@ compile-flags: --crate-type rlib
 //@ only-nvptx64
-//@ ignore-nvptx64
 
 #![no_std]
 
diff --git a/tests/assembly/nvptx-arch-target-cpu.rs b/tests/assembly/nvptx-arch-target-cpu.rs
index 212af20f4de..609ab297e63 100644
--- a/tests/assembly/nvptx-arch-target-cpu.rs
+++ b/tests/assembly/nvptx-arch-target-cpu.rs
@@ -1,7 +1,6 @@
 //@ assembly-output: ptx-linker
-//@ compile-flags: --crate-type cdylib -C target-cpu=sm_50
+//@ compile-flags: --crate-type cdylib -C target-cpu=sm_50 -Z unstable-options -Clinker-flavor=llbc
 //@ only-nvptx64
-//@ ignore-nvptx64
 
 #![no_std]
 
diff --git a/tests/assembly/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs b/tests/assembly/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs
index a42d5dd3569..ce1d732f367 100644
--- a/tests/assembly/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs
+++ b/tests/assembly/nvptx-kernel-abi/nvptx-kernel-args-abi-v7.rs
@@ -1,7 +1,6 @@
 //@ assembly-output: ptx-linker
-//@ compile-flags: --crate-type cdylib -C target-cpu=sm_86
+//@ compile-flags: --crate-type cdylib -C target-cpu=sm_86 -Z unstable-options -Clinker-flavor=llbc
 //@ only-nvptx64
-//@ ignore-nvptx64
 
 // The following ABI tests are made with nvcc 11.6 does.
 //
@@ -226,10 +225,11 @@ pub unsafe extern "ptx-kernel" fn f_byte_array_arg(_a: [u8; 5]) {}
 #[no_mangle]
 pub unsafe extern "ptx-kernel" fn f_float_array_arg(_a: [f32; 5]) {}
 
-// CHECK: .visible .entry f_u128_array_arg(
-// CHECK: .param .align 16 .b8 f_u128_array_arg_param_0[80]
-#[no_mangle]
-pub unsafe extern "ptx-kernel" fn f_u128_array_arg(_a: [u128; 5]) {}
+// FIXME: u128 started to break compilation with disabled CI
+// NO_CHECK: .visible .entry f_u128_array_arg(
+// NO_CHECK: .param .align 16 .b8 f_u128_array_arg_param_0[80]
+//#[no_mangle]
+//pub unsafe extern "ptx-kernel" fn f_u128_array_arg(_a: [u128; 5]) {}
 
 // CHECK: .visible .entry f_u32_slice_arg(
 // CHECK: .param .u64 f_u32_slice_arg_param_0
@@ -247,7 +247,6 @@ pub unsafe extern "ptx-kernel" fn f_tuple_u8_u8_arg(_a: (u8, u8)) {}
 #[no_mangle]
 pub unsafe extern "ptx-kernel" fn f_tuple_u32_u32_arg(_a: (u32, u32)) {}
 
-
 // CHECK: .visible .entry f_tuple_u8_u8_u32_arg(
 // CHECK: .param .align 4 .b8 f_tuple_u8_u8_u32_arg_param_0[8]
 #[no_mangle]
diff --git a/tests/assembly/nvptx-safe-naming.rs b/tests/assembly/nvptx-safe-naming.rs
index 59fd527be3c..d7b46aadd9c 100644
--- a/tests/assembly/nvptx-safe-naming.rs
+++ b/tests/assembly/nvptx-safe-naming.rs
@@ -1,7 +1,6 @@
 //@ assembly-output: ptx-linker
-//@ compile-flags: --crate-type cdylib
+//@ compile-flags: --crate-type cdylib -Z unstable-options -Clinker-flavor=llbc
 //@ only-nvptx64
-//@ ignore-nvptx64
 
 #![feature(abi_ptx)]
 #![no_std]
@@ -10,7 +9,7 @@
 extern crate breakpoint_panic_handler;
 
 // Verify function name doesn't contain unacceaptable characters.
-// CHECK: .func (.param .b32 func_retval0) [[IMPL_FN:[a-zA-Z0-9$_]+square[a-zA-Z0-9$_]+]](
+// CHECK: .func (.param .b32 func_retval0) [[IMPL_FN:[a-zA-Z0-9$_]+square[a-zA-Z0-9$_]+]]
 
 // CHECK-LABEL: .visible .entry top_kernel(
 #[no_mangle]
diff --git a/tests/assembly/wasm_exceptions.rs b/tests/assembly/wasm_exceptions.rs
index 45df444dca4..3d3b13ff32b 100644
--- a/tests/assembly/wasm_exceptions.rs
+++ b/tests/assembly/wasm_exceptions.rs
@@ -1,4 +1,4 @@
-//@ only-wasm32-bare
+//@ only-wasm32
 //@ assembly-output: emit-asm
 //@ compile-flags: -C target-feature=+exception-handling
 //@ compile-flags: -C panic=unwind
diff --git a/tests/codegen/abi-main-signature-32bit-c-int.rs b/tests/codegen/abi-main-signature-32bit-c-int.rs
index 52db3d893e1..7684024a2e3 100644
--- a/tests/codegen/abi-main-signature-32bit-c-int.rs
+++ b/tests/codegen/abi-main-signature-32bit-c-int.rs
@@ -4,6 +4,7 @@
 // This test is for targets with 32bit c_int only.
 //@ ignore-msp430
 //@ ignore-avr
+//@ ignore-wasi wasi codegens the main symbol differently
 
 fn main() {
 }
diff --git a/tests/codegen/align-byval-vector.rs b/tests/codegen/align-byval-vector.rs
index 6596792ec88..02b7d6b0c5e 100644
--- a/tests/codegen/align-byval-vector.rs
+++ b/tests/codegen/align-byval-vector.rs
@@ -37,12 +37,12 @@ pub struct DoubleFoo {
 }
 
 extern "C" {
-    // x86-linux: declare void @f({{.*}}byval(%Foo) align 4{{.*}})
-    // x86-darwin: declare void @f({{.*}}byval(%Foo) align 16{{.*}})
+    // x86-linux: declare void @f({{.*}}byval([32 x i8]) align 4{{.*}})
+    // x86-darwin: declare void @f({{.*}}byval([32 x i8]) align 16{{.*}})
     fn f(foo: Foo);
 
-    // x86-linux: declare void @g({{.*}}byval(%DoubleFoo) align 4{{.*}})
-    // x86-darwin: declare void @g({{.*}}byval(%DoubleFoo) align 16{{.*}})
+    // x86-linux: declare void @g({{.*}}byval([64 x i8]) align 4{{.*}})
+    // x86-darwin: declare void @g({{.*}}byval([64 x i8]) align 16{{.*}})
     fn g(foo: DoubleFoo);
 }
 
diff --git a/tests/codegen/align-byval.rs b/tests/codegen/align-byval.rs
index 1016c7903eb..c74e236f29d 100644
--- a/tests/codegen/align-byval.rs
+++ b/tests/codegen/align-byval.rs
@@ -107,20 +107,20 @@ pub unsafe fn call_na1(x: NaturalAlign1) {
     // CHECK: start:
 
     // m68k: [[ALLOCA:%[a-z0-9+]]] = alloca %NaturalAlign1, align 1
-    // m68k: call void @natural_align_1({{.*}}byval(%NaturalAlign1) align 1{{.*}} [[ALLOCA]])
+    // m68k: call void @natural_align_1({{.*}}byval([2 x i8]) align 1{{.*}} [[ALLOCA]])
 
     // wasm: [[ALLOCA:%[a-z0-9+]]] = alloca %NaturalAlign1, align 1
-    // wasm: call void @natural_align_1({{.*}}byval(%NaturalAlign1) align 1{{.*}} [[ALLOCA]])
+    // wasm: call void @natural_align_1({{.*}}byval([2 x i8]) align 1{{.*}} [[ALLOCA]])
 
     // x86_64-linux: call void @natural_align_1(i16
 
     // x86_64-windows: call void @natural_align_1(i16
 
     // i686-linux: [[ALLOCA:%[a-z0-9+]]] = alloca %NaturalAlign1, align 4
-    // i686-linux: call void @natural_align_1({{.*}}byval(%NaturalAlign1) align 4{{.*}} [[ALLOCA]])
+    // i686-linux: call void @natural_align_1({{.*}}byval([2 x i8]) align 4{{.*}} [[ALLOCA]])
 
     // i686-windows: [[ALLOCA:%[a-z0-9+]]] = alloca %NaturalAlign1, align 4
-    // i686-windows: call void @natural_align_1({{.*}}byval(%NaturalAlign1) align 4{{.*}} [[ALLOCA]])
+    // i686-windows: call void @natural_align_1({{.*}}byval([2 x i8]) align 4{{.*}} [[ALLOCA]])
     natural_align_1(x);
 }
 
@@ -135,10 +135,10 @@ pub unsafe fn call_na2(x: NaturalAlign2) {
     // x86_64-windows-NEXT: call void @natural_align_2
 
     // i686-linux: [[ALLOCA:%[0-9]+]] = alloca %NaturalAlign2, align 4
-    // i686-linux: call void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}} [[ALLOCA]])
+    // i686-linux: call void @natural_align_2({{.*}}byval([34 x i8]) align 4{{.*}} [[ALLOCA]])
 
     // i686-windows: [[ALLOCA:%[0-9]+]] = alloca %NaturalAlign2, align 4
-    // i686-windows: call void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}} [[ALLOCA]])
+    // i686-windows: call void @natural_align_2({{.*}}byval([34 x i8]) align 4{{.*}} [[ALLOCA]])
     natural_align_2(x);
 }
 
@@ -199,141 +199,141 @@ pub unsafe fn call_fa16(x: ForceAlign16) {
 }
 
 extern "C" {
-    // m68k: declare void @natural_align_1({{.*}}byval(%NaturalAlign1) align 1{{.*}})
+    // m68k: declare void @natural_align_1({{.*}}byval([2 x i8]) align 1{{.*}})
 
-    // wasm: declare void @natural_align_1({{.*}}byval(%NaturalAlign1) align 1{{.*}})
+    // wasm: declare void @natural_align_1({{.*}}byval([2 x i8]) align 1{{.*}})
 
     // x86_64-linux: declare void @natural_align_1(i16)
 
     // x86_64-windows: declare void @natural_align_1(i16)
 
-    // i686-linux: declare void @natural_align_1({{.*}}byval(%NaturalAlign1) align 4{{.*}})
+    // i686-linux: declare void @natural_align_1({{.*}}byval([2 x i8]) align 4{{.*}})
 
-    // i686-windows: declare void @natural_align_1({{.*}}byval(%NaturalAlign1) align 4{{.*}})
+    // i686-windows: declare void @natural_align_1({{.*}}byval([2 x i8]) align 4{{.*}})
     fn natural_align_1(x: NaturalAlign1);
 
-    // m68k: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 2{{.*}})
+    // m68k: declare void @natural_align_2({{.*}}byval([34 x i8]) align 2{{.*}})
 
-    // wasm: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 2{{.*}})
+    // wasm: declare void @natural_align_2({{.*}}byval([34 x i8]) align 2{{.*}})
 
-    // x86_64-linux: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 2{{.*}})
+    // x86_64-linux: declare void @natural_align_2({{.*}}byval([34 x i8]) align 2{{.*}})
 
     // x86_64-windows: declare void @natural_align_2(
     // x86_64-windows-NOT: byval
     // x86_64-windows-SAME: align 2{{.*}})
 
-    // i686-linux: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}})
+    // i686-linux: declare void @natural_align_2({{.*}}byval([34 x i8]) align 4{{.*}})
 
-    // i686-windows: declare void @natural_align_2({{.*}}byval(%NaturalAlign2) align 4{{.*}})
+    // i686-windows: declare void @natural_align_2({{.*}}byval([34 x i8]) align 4{{.*}})
     fn natural_align_2(x: NaturalAlign2);
 
-    // m68k: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}})
+    // m68k: declare void @force_align_4({{.*}}byval([20 x i8]) align 4{{.*}})
 
-    // wasm: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}})
+    // wasm: declare void @force_align_4({{.*}}byval([20 x i8]) align 4{{.*}})
 
-    // x86_64-linux: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}})
+    // x86_64-linux: declare void @force_align_4({{.*}}byval([20 x i8]) align 4{{.*}})
 
     // x86_64-windows: declare void @force_align_4(
     // x86_64-windows-NOT: byval
     // x86_64-windows-SAME: align 4{{.*}})
 
-    // i686-linux: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}})
+    // i686-linux: declare void @force_align_4({{.*}}byval([20 x i8]) align 4{{.*}})
 
-    // i686-windows: declare void @force_align_4({{.*}}byval(%ForceAlign4) align 4{{.*}})
+    // i686-windows: declare void @force_align_4({{.*}}byval([20 x i8]) align 4{{.*}})
     fn force_align_4(x: ForceAlign4);
 
-    // m68k: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 4{{.*}})
+    // m68k: declare void @natural_align_8({{.*}}byval([24 x i8]) align 4{{.*}})
 
-    // wasm: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 8{{.*}})
+    // wasm: declare void @natural_align_8({{.*}}byval([24 x i8]) align 8{{.*}})
 
-    // x86_64-linux: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 8{{.*}})
+    // x86_64-linux: declare void @natural_align_8({{.*}}byval([24 x i8]) align 8{{.*}})
 
     // x86_64-windows: declare void @natural_align_8(
     // x86_64-windows-NOT: byval
     // x86_64-windows-SAME: align 8{{.*}})
 
-    // i686-linux: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 4{{.*}})
+    // i686-linux: declare void @natural_align_8({{.*}}byval([24 x i8]) align 4{{.*}})
 
-    // i686-windows: declare void @natural_align_8({{.*}}byval(%NaturalAlign8) align 4{{.*}})
+    // i686-windows: declare void @natural_align_8({{.*}}byval([24 x i8]) align 4{{.*}})
     fn natural_align_8(x: NaturalAlign8);
 
-    // m68k: declare void @force_align_8({{.*}}byval(%ForceAlign8) align 8{{.*}})
+    // m68k: declare void @force_align_8({{.*}}byval([24 x i8]) align 8{{.*}})
 
-    // wasm: declare void @force_align_8({{.*}}byval(%ForceAlign8) align 8{{.*}})
+    // wasm: declare void @force_align_8({{.*}}byval([24 x i8]) align 8{{.*}})
 
-    // x86_64-linux: declare void @force_align_8({{.*}}byval(%ForceAlign8) align 8{{.*}})
+    // x86_64-linux: declare void @force_align_8({{.*}}byval([24 x i8]) align 8{{.*}})
 
     // x86_64-windows: declare void @force_align_8(
     // x86_64-windows-NOT: byval
     // x86_64-windows-SAME: align 8{{.*}})
 
-    // i686-linux: declare void @force_align_8({{.*}}byval(%ForceAlign8) align 4{{.*}})
+    // i686-linux: declare void @force_align_8({{.*}}byval([24 x i8]) align 4{{.*}})
 
     // i686-windows: declare void @force_align_8(
     // i686-windows-NOT: byval
     // i686-windows-SAME: align 8{{.*}})
     fn force_align_8(x: ForceAlign8);
 
-    // m68k: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 4{{.*}})
+    // m68k: declare void @lower_fa8({{.*}}byval([24 x i8]) align 4{{.*}})
 
-    // wasm: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 8{{.*}})
+    // wasm: declare void @lower_fa8({{.*}}byval([24 x i8]) align 8{{.*}})
 
-    // x86_64-linux: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 8{{.*}})
+    // x86_64-linux: declare void @lower_fa8({{.*}}byval([24 x i8]) align 8{{.*}})
 
     // x86_64-windows: declare void @lower_fa8(
     // x86_64-windows-NOT: byval
     // x86_64-windows-SAME: align 8{{.*}})
 
-    // i686-linux: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 4{{.*}})
+    // i686-linux: declare void @lower_fa8({{.*}}byval([24 x i8]) align 4{{.*}})
 
-    // i686-windows: declare void @lower_fa8({{.*}}byval(%LowerFA8) align 4{{.*}})
+    // i686-windows: declare void @lower_fa8({{.*}}byval([24 x i8]) align 4{{.*}})
     fn lower_fa8(x: LowerFA8);
 
-    // m68k: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 8{{.*}})
+    // m68k: declare void @wrapped_fa8({{.*}}byval([24 x i8]) align 8{{.*}})
 
-    // wasm: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 8{{.*}})
+    // wasm: declare void @wrapped_fa8({{.*}}byval([24 x i8]) align 8{{.*}})
 
-    // x86_64-linux: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 8{{.*}})
+    // x86_64-linux: declare void @wrapped_fa8({{.*}}byval([24 x i8]) align 8{{.*}})
 
     // x86_64-windows: declare void @wrapped_fa8(
     // x86_64-windows-NOT: byval
     // x86_64-windows-SAME: align 8{{.*}})
 
-    // i686-linux: declare void @wrapped_fa8({{.*}}byval(%WrappedFA8) align 4{{.*}})
+    // i686-linux: declare void @wrapped_fa8({{.*}}byval([24 x i8]) align 4{{.*}})
 
     // i686-windows: declare void @wrapped_fa8(
     // i686-windows-NOT: byval
     // i686-windows-SAME: align 8{{.*}})
     fn wrapped_fa8(x: WrappedFA8);
 
-    // m68k: declare void @transparent_fa8({{.*}}byval(%TransparentFA8) align 8{{.*}})
+    // m68k: declare void @transparent_fa8({{.*}}byval([24 x i8]) align 8{{.*}})
 
-    // wasm: declare void @transparent_fa8({{.*}}byval(%TransparentFA8) align 8{{.*}})
+    // wasm: declare void @transparent_fa8({{.*}}byval([24 x i8]) align 8{{.*}})
 
-    // x86_64-linux: declare void @transparent_fa8({{.*}}byval(%TransparentFA8) align 8{{.*}})
+    // x86_64-linux: declare void @transparent_fa8({{.*}}byval([24 x i8]) align 8{{.*}})
 
     // x86_64-windows: declare void @transparent_fa8(
     // x86_64-windows-NOT: byval
     // x86_64-windows-SAME: align 8{{.*}})
 
-    // i686-linux: declare void @transparent_fa8({{.*}}byval(%TransparentFA8) align 4{{.*}})
+    // i686-linux: declare void @transparent_fa8({{.*}}byval([24 x i8]) align 4{{.*}})
 
     // i686-windows: declare void @transparent_fa8(
     // i686-windows-NOT: byval
     // i686-windows-SAME: align 8{{.*}})
     fn transparent_fa8(x: TransparentFA8);
 
-    // m68k: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 16{{.*}})
+    // m68k: declare void @force_align_16({{.*}}byval([80 x i8]) align 16{{.*}})
 
-    // wasm: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 16{{.*}})
+    // wasm: declare void @force_align_16({{.*}}byval([80 x i8]) align 16{{.*}})
 
-    // x86_64-linux: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 16{{.*}})
+    // x86_64-linux: declare void @force_align_16({{.*}}byval([80 x i8]) align 16{{.*}})
 
     // x86_64-windows: declare void @force_align_16(
     // x86_64-windows-NOT: byval
     // x86_64-windows-SAME: align 16{{.*}})
 
-    // i686-linux: declare void @force_align_16({{.*}}byval(%ForceAlign16) align 4{{.*}})
+    // i686-linux: declare void @force_align_16({{.*}}byval([80 x i8]) align 4{{.*}})
 
     // i686-windows: declare void @force_align_16(
     // i686-windows-NOT: byval
diff --git a/tests/codegen/align-enum.rs b/tests/codegen/align-enum.rs
index 17bf2cf7256..b40168d77a4 100644
--- a/tests/codegen/align-enum.rs
+++ b/tests/codegen/align-enum.rs
@@ -8,7 +8,6 @@ pub enum Align64 {
     A(u32),
     B(u32),
 }
-// CHECK: %Align64 = type { i32, [15 x i32] }
 
 pub struct Nested64 {
     a: u8,
diff --git a/tests/codegen/align-struct.rs b/tests/codegen/align-struct.rs
index 31859152830..dbbb85bee6f 100644
--- a/tests/codegen/align-struct.rs
+++ b/tests/codegen/align-struct.rs
@@ -5,7 +5,6 @@
 
 #[repr(align(64))]
 pub struct Align64(i32);
-// CHECK: %Align64 = type { i32, [15 x i32] }
 
 pub struct Nested64 {
     a: Align64,
@@ -13,19 +12,16 @@ pub struct Nested64 {
     c: i32,
     d: i8,
 }
-// CHECK: %Nested64 = type { %Align64, i32, i32, i8, [55 x i8] }
 
 pub enum Enum4 {
     A(i32),
     B(i32),
 }
-// No Aggregate type, and hence nothing in LLVM IR.
 
 pub enum Enum64 {
     A(Align64),
     B(i32),
 }
-// CHECK: %Enum64 = type { i32, [31 x i32] }
 
 // CHECK-LABEL: @align64
 #[no_mangle]
diff --git a/tests/codegen/debuginfo-inline-callsite-location.rs b/tests/codegen/debuginfo-inline-callsite-location.rs
index 833e8c0df91..f690c9c0937 100644
--- a/tests/codegen/debuginfo-inline-callsite-location.rs
+++ b/tests/codegen/debuginfo-inline-callsite-location.rs
@@ -4,9 +4,9 @@
 // can correctly merge the debug info if it merges the inlined code (e.g., for merging of tail
 // calls to panic.
 
-// CHECK:       tail call void @_ZN4core6option13unwrap_failed17h{{([0-9a-z]{16})}}E
+// CHECK:       tail call void @{{[A-Za-z0-9_]+4core6option13unwrap_failed}}
 // CHECK-SAME:  !dbg ![[#first_dbg:]]
-// CHECK:       tail call void @_ZN4core6option13unwrap_failed17h{{([0-9a-z]{16})}}E
+// CHECK:       tail call void @{{[A-Za-z0-9_]+4core6option13unwrap_failed}}
 // CHECK-SAME:  !dbg ![[#second_dbg:]]
 
 // CHECK-DAG:   ![[#func_dbg:]] = distinct !DISubprogram(name: "unwrap<i32>"
diff --git a/tests/codegen/drop.rs b/tests/codegen/drop.rs
index 93e54979a05..1e80247ba8a 100644
--- a/tests/codegen/drop.rs
+++ b/tests/codegen/drop.rs
@@ -1,4 +1,3 @@
-//@ ignore-wasm32-bare compiled with panic=abort by default
 //@ needs-unwind - this test verifies the amount of drop calls when unwinding is used
 //@ compile-flags: -C no-prepopulate-passes
 
diff --git a/tests/codegen/dst-offset.rs b/tests/codegen/dst-offset.rs
index f0157e5a106..ce735baeb6a 100644
--- a/tests/codegen/dst-offset.rs
+++ b/tests/codegen/dst-offset.rs
@@ -25,9 +25,9 @@ struct Dst<T: ?Sized> {
 pub fn dst_dyn_trait_offset(s: &Dst<dyn Drop>) -> &dyn Drop {
 // The alignment of dyn trait is unknown, so we compute the offset based on align from the vtable.
 
-// CHECK: [[SIZE_PTR:%[0-9]+]] = getelementptr inbounds {{.+}} [[VTABLE_PTR]]
+// CHECK: [[SIZE_PTR:%[0-9]+]] = getelementptr inbounds i8, ptr [[VTABLE_PTR]]
 // CHECK: load [[USIZE]], ptr [[SIZE_PTR]]
-// CHECK: [[ALIGN_PTR:%[0-9]+]] = getelementptr inbounds {{.+}} [[VTABLE_PTR]]
+// CHECK: [[ALIGN_PTR:%[0-9]+]] = getelementptr inbounds i8, ptr [[VTABLE_PTR]]
 // CHECK: load [[USIZE]], ptr [[ALIGN_PTR]]
 
 // CHECK: getelementptr inbounds i8, ptr [[DATA_PTR]]
diff --git a/tests/codegen/enum/enum-debug-clike.rs b/tests/codegen/enum/enum-debug-clike.rs
index 205c57d1456..59ad5878443 100644
--- a/tests/codegen/enum/enum-debug-clike.rs
+++ b/tests/codegen/enum/enum-debug-clike.rs
@@ -3,6 +3,7 @@
 
 //
 //@ ignore-msvc
+//@ ignore-wasi wasi codegens the main symbol differently
 
 //@ compile-flags: -g -C no-prepopulate-passes
 
diff --git a/tests/codegen/enum/enum-debug-niche.rs b/tests/codegen/enum/enum-debug-niche.rs
index fc6a73e8472..90de928bced 100644
--- a/tests/codegen/enum/enum-debug-niche.rs
+++ b/tests/codegen/enum/enum-debug-niche.rs
@@ -2,6 +2,7 @@
 // This is ignored for the fallback mode on MSVC due to problems with PDB.
 
 //@ ignore-msvc
+//@ ignore-wasi wasi codegens the main symbol differently
 
 //@ compile-flags: -g -C no-prepopulate-passes
 
diff --git a/tests/codegen/enum/enum-debug-tagged.rs b/tests/codegen/enum/enum-debug-tagged.rs
index 87a6ccae291..f13922ee33b 100644
--- a/tests/codegen/enum/enum-debug-tagged.rs
+++ b/tests/codegen/enum/enum-debug-tagged.rs
@@ -2,6 +2,7 @@
 // This is ignored for the fallback mode on MSVC due to problems with PDB.
 
 //@ ignore-msvc
+//@ ignore-wasi wasi codegens the main symbol differently
 
 //@ compile-flags: -g -C no-prepopulate-passes
 
diff --git a/tests/codegen/enum/enum-u128.rs b/tests/codegen/enum/enum-u128.rs
index 94e80e34068..ecdff3c5ce3 100644
--- a/tests/codegen/enum/enum-u128.rs
+++ b/tests/codegen/enum/enum-u128.rs
@@ -3,6 +3,7 @@
 
 //
 //@ ignore-msvc
+//@ ignore-wasi wasi codegens the main symbol differently
 
 //@ compile-flags: -g -C no-prepopulate-passes
 
diff --git a/tests/codegen/fn-impl-trait-self.rs b/tests/codegen/fn-impl-trait-self.rs
index 9f10762d8fa..5799d23b5a0 100644
--- a/tests/codegen/fn-impl-trait-self.rs
+++ b/tests/codegen/fn-impl-trait-self.rs
@@ -1,4 +1,5 @@
 //@ compile-flags: -g
+//@ ignore-wasi wasi codegens the main symbol differently
 //
 // CHECK-LABEL: @main
 // MSVC: {{.*}}DIDerivedType(tag: DW_TAG_pointer_type, name: "recursive_type$ (*)()",{{.*}}
diff --git a/tests/codegen/function-arguments-noopt.rs b/tests/codegen/function-arguments-noopt.rs
index e99ceddfb72..0d42915893b 100644
--- a/tests/codegen/function-arguments-noopt.rs
+++ b/tests/codegen/function-arguments-noopt.rs
@@ -42,7 +42,7 @@ pub fn borrow_call(x: &i32, f: fn(&i32) -> &i32) -> &i32 {
   f(x)
 }
 
-// CHECK: void @struct_(ptr sret(%S) align 4{{( %_0)?}}, ptr align 4 %x)
+// CHECK: void @struct_(ptr sret([32 x i8]) align 4{{( %_0)?}}, ptr align 4 %x)
 #[no_mangle]
 pub fn struct_(x: S) -> S {
   x
@@ -51,7 +51,7 @@ pub fn struct_(x: S) -> S {
 // CHECK-LABEL: @struct_call
 #[no_mangle]
 pub fn struct_call(x: S, f: fn(S) -> S) -> S {
-  // CHECK: call void %f(ptr sret(%S) align 4{{( %_0)?}}, ptr align 4 %{{.+}})
+  // CHECK: call void %f(ptr sret([32 x i8]) align 4{{( %_0)?}}, ptr align 4 %{{.+}})
   f(x)
 }
 
diff --git a/tests/codegen/function-arguments.rs b/tests/codegen/function-arguments.rs
index e6e2f645714..468ec0a7753 100644
--- a/tests/codegen/function-arguments.rs
+++ b/tests/codegen/function-arguments.rs
@@ -198,7 +198,7 @@ pub fn notunpin_box(x: Box<NotUnpin>) -> Box<NotUnpin> {
   x
 }
 
-// CHECK: @struct_return(ptr noalias nocapture noundef sret(%S) align 4 dereferenceable(32){{( %_0)?}})
+// CHECK: @struct_return(ptr noalias nocapture noundef sret([32 x i8]) align 4 dereferenceable(32){{( %_0)?}})
 #[no_mangle]
 pub fn struct_return() -> S {
   S {
diff --git a/tests/codegen/generic-debug.rs b/tests/codegen/generic-debug.rs
index 87a0ddfea93..0f289026396 100644
--- a/tests/codegen/generic-debug.rs
+++ b/tests/codegen/generic-debug.rs
@@ -1,4 +1,5 @@
 //@ ignore-windows
+//@ ignore-wasi wasi codegens the main symbol differently
 
 //@ compile-flags: -g -C no-prepopulate-passes
 
diff --git a/tests/codegen/link_section.rs b/tests/codegen/link_section.rs
index 6747feba211..281d3fb99d4 100644
--- a/tests/codegen/link_section.rs
+++ b/tests/codegen/link_section.rs
@@ -1,4 +1,4 @@
-//@ ignore-emscripten default visibility is hidden
+//@ ignore-wasm32 custom sections work differently on wasm
 //@ compile-flags: -C no-prepopulate-passes
 
 #![crate_type = "lib"]
diff --git a/tests/codegen/loongarch-abi/loongarch64-lp64d-abi.rs b/tests/codegen/loongarch-abi/loongarch64-lp64d-abi.rs
index 3c895eb9531..c9be4f6d383 100644
--- a/tests/codegen/loongarch-abi/loongarch64-lp64d-abi.rs
+++ b/tests/codegen/loongarch-abi/loongarch64-lp64d-abi.rs
@@ -1,8 +1,14 @@
-//@ compile-flags: -C no-prepopulate-passes
-//@ only-loongarch64
-//@ only-linux
+//@ compile-flags: -O -C no-prepopulate-passes --target loongarch64-unknown-linux-gnu
+//@ needs-llvm-components: loongarch
 
+#![feature(no_core, lang_items)]
 #![crate_type = "lib"]
+#![no_std]
+#![no_core]
+
+#[lang="sized"] trait Sized { }
+#[lang="freeze"] trait Freeze { }
+#[lang="copy"] trait Copy { }
 
 // CHECK: define void @f_fpr_tracking(double %0, double %1, double %2, double %3, double %4, double %5, double %6, double %7, i8 noundef zeroext %i)
 #[no_mangle]
@@ -254,7 +260,7 @@ pub struct IntDoubleInt {
 #[no_mangle]
 pub extern "C" fn f_int_double_int_s_arg(a: IntDoubleInt) {}
 
-// CHECK: define void @f_ret_int_double_int_s(ptr noalias nocapture noundef sret(%IntDoubleInt) align 8 dereferenceable(24) %_0)
+// CHECK: define void @f_ret_int_double_int_s(ptr noalias nocapture noundef sret([24 x i8]) align 8 dereferenceable(24) %_0)
 #[no_mangle]
 pub extern "C" fn f_ret_int_double_int_s() -> IntDoubleInt {
     IntDoubleInt { a: 1, b: 2., c: 3 }
diff --git a/tests/codegen/mainsubprogram.rs b/tests/codegen/mainsubprogram.rs
index 8e173df0e86..c1933b2b390 100644
--- a/tests/codegen/mainsubprogram.rs
+++ b/tests/codegen/mainsubprogram.rs
@@ -3,6 +3,7 @@
 
 //@ ignore-windows
 //@ ignore-macos
+//@ ignore-wasi
 
 //@ compile-flags: -g -C no-prepopulate-passes
 
diff --git a/tests/codegen/mainsubprogramstart.rs b/tests/codegen/mainsubprogramstart.rs
index db2c1466bf5..84d680b9bff 100644
--- a/tests/codegen/mainsubprogramstart.rs
+++ b/tests/codegen/mainsubprogramstart.rs
@@ -1,5 +1,6 @@
 //@ ignore-windows
 //@ ignore-macos
+//@ ignore-wasi wasi codegens the main symbol differently
 
 //@ compile-flags: -g -C no-prepopulate-passes
 
diff --git a/tests/codegen/mem-replace-big-type.rs b/tests/codegen/mem-replace-big-type.rs
index c71cbbd08f9..d5eadda4469 100644
--- a/tests/codegen/mem-replace-big-type.rs
+++ b/tests/codegen/mem-replace-big-type.rs
@@ -23,7 +23,7 @@ pub fn replace_big(dst: &mut Big, src: Big) -> Big {
 // CHECK-NOT: call void @llvm.memcpy
 
 // For a large type, we expect exactly three `memcpy`s
-// CHECK-LABEL: define internal void @{{.+}}mem{{.+}}replace{{.+}}sret(%Big)
+// CHECK-LABEL: define internal void @{{.+}}mem{{.+}}replace{{.+}}sret([56 x i8])
 // CHECK-NOT: call void @llvm.memcpy
 // CHECK: call void @llvm.memcpy.{{.+}}(ptr align 8 %result, ptr align 8 %dest, i{{.*}} 56, i1 false)
 // CHECK-NOT: call void @llvm.memcpy
diff --git a/tests/codegen/personality_lifetimes.rs b/tests/codegen/personality_lifetimes.rs
index 06389688e0e..f2ab9c3bb82 100644
--- a/tests/codegen/personality_lifetimes.rs
+++ b/tests/codegen/personality_lifetimes.rs
@@ -1,5 +1,4 @@
 //@ ignore-msvc
-//@ ignore-wasm32-bare compiled with panic=abort by default
 //@ needs-unwind
 
 //@ compile-flags: -O -C no-prepopulate-passes
diff --git a/tests/codegen/repr/transparent-imm-array.rs b/tests/codegen/repr/transparent-imm-array.rs
index 842e36ca13d..917a2c6ef52 100644
--- a/tests/codegen/repr/transparent-imm-array.rs
+++ b/tests/codegen/repr/transparent-imm-array.rs
@@ -1,22 +1,40 @@
-//@ revisions: arm mips thumb wasm32
-//@ compile-flags: -C no-prepopulate-passes
-//
-//@[arm] only-arm
-//@[mips] only-mips
-//@[thumb] only-thumb
-//@[wasm32] only-wasm32
-//@ ignore-emscripten
+//@ revisions: arm-linux arm-android armv7-linux armv7-android mips thumb sparc
+//@ compile-flags: -O -C no-prepopulate-passes
+
+//@[arm-linux] compile-flags: --target arm-unknown-linux-gnueabi
+//@[arm-linux] needs-llvm-components: arm
+//@[arm-android] compile-flags: --target arm-linux-androideabi
+//@[arm-android] needs-llvm-components: arm
+//@[armv7-linux] compile-flags: --target armv7-unknown-linux-gnueabi
+//@[armv7-linux] needs-llvm-components: arm
+//@[armv7-android] compile-flags: --target armv7-linux-androideabi
+//@[armv7-android] needs-llvm-components: arm
+//@[mips] compile-flags: --target mips-unknown-linux-gnu
+//@[mips] needs-llvm-components: mips
+//@[thumb] compile-flags: --target thumbv7neon-linux-androideabi
+//@[thumb] needs-llvm-components: arm
+//@[sparc] compile-flags: --target sparc-unknown-linux-gnu
+//@[sparc] needs-llvm-components: sparc
+
 // See ./transparent.rs
 // Some platforms pass large aggregates using immediate arrays in LLVMIR
 // Other platforms pass large aggregates using struct pointer in LLVMIR
 // This covers the "immediate array" case.
 
-#![feature(transparent_unions)]
+#![feature(no_core, lang_items, transparent_unions)]
+#![crate_type = "lib"]
+#![no_std]
+#![no_core]
+
+#[lang="sized"] trait Sized { }
+#[lang="freeze"] trait Freeze { }
+#[lang="copy"] trait Copy { }
 
-#![crate_type="lib"]
+impl Copy for [u32; 16] {}
+impl Copy for BigS {}
+impl Copy for BigU {}
 
 
-#[derive(Clone, Copy)]
 #[repr(C)]
 pub struct BigS([u32; 16]);
 
@@ -33,24 +51,23 @@ pub enum TeBigS {
     Variant(BigS),
 }
 
-// CHECK: define void @test_BigS(ptr [[BIGS_RET_ATTRS1:.*]] sret(%BigS) [[BIGS_RET_ATTRS2:.*]], [16 x i32]
+// CHECK: define void @test_BigS(ptr [[BIGS_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGS_RET_ATTRS2:.*]], [16 x i32]
 #[no_mangle]
 pub extern fn test_BigS(_: BigS) -> BigS { loop {} }
 
-// CHECK: define void @test_TsBigS(ptr [[BIGS_RET_ATTRS1]] sret(%TsBigS) [[BIGS_RET_ATTRS2]], [16 x i32]
+// CHECK: define void @test_TsBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], [16 x i32]
 #[no_mangle]
 pub extern fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} }
 
-// CHECK: define void @test_TuBigS(ptr [[BIGS_RET_ATTRS1]] sret(%TuBigS) [[BIGS_RET_ATTRS2]], [16 x i32]
+// CHECK: define void @test_TuBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], [16 x i32]
 #[no_mangle]
 pub extern fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} }
 
-// CHECK: define void @test_TeBigS(ptr [[BIGS_RET_ATTRS1]] sret(%"TeBigS::Variant") [[BIGS_RET_ATTRS2]], [16 x i32]
+// CHECK: define void @test_TeBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], [16 x i32]
 #[no_mangle]
 pub extern fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} }
 
 
-#[derive(Clone, Copy)]
 #[repr(C)]
 pub union BigU {
     foo: [u32; 16],
@@ -69,18 +86,18 @@ pub enum TeBigU {
     Variant(BigU),
 }
 
-// CHECK: define void @test_BigU(ptr [[BIGU_RET_ATTRS1:.*]] sret(%BigU) [[BIGU_RET_ATTRS2:.*]], [16 x i32]
+// CHECK: define void @test_BigU(ptr [[BIGU_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], [16 x i32]
 #[no_mangle]
 pub extern fn test_BigU(_: BigU) -> BigU { loop {} }
 
-// CHECK: define void @test_TsBigU(ptr [[BIGU_RET_ATTRS1]] sret(%TsBigU) [[BIGU_RET_ATTRS2]], [16 x i32]
+// CHECK: define void @test_TsBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2]], [16 x i32]
 #[no_mangle]
 pub extern fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} }
 
-// CHECK: define void @test_TuBigU(ptr [[BIGU_RET_ATTRS1]] sret(%TuBigU) [[BIGU_RET_ATTRS2]], [16 x i32]
+// CHECK: define void @test_TuBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2]], [16 x i32]
 #[no_mangle]
 pub extern fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} }
 
-// CHECK: define void @test_TeBigU(ptr [[BIGU_RET_ATTRS1]] sret(%"TeBigU::Variant") [[BIGU_RET_ATTRS2]], [16 x i32]
+// CHECK: define void @test_TeBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2]], [16 x i32]
 #[no_mangle]
 pub extern fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} }
diff --git a/tests/codegen/repr/transparent-mips64.rs b/tests/codegen/repr/transparent-mips64.rs
index 55090e6bd80..ebed8d7989f 100644
--- a/tests/codegen/repr/transparent-mips64.rs
+++ b/tests/codegen/repr/transparent-mips64.rs
@@ -1,15 +1,26 @@
-//@ compile-flags: -C no-prepopulate-passes
-//
+//@ revisions: mips64 mips64el
+//@ compile-flags: -O -C no-prepopulate-passes
+
+//@[mips64] compile-flags: --target mips64-unknown-linux-gnuabi64
+//@[mips64] needs-llvm-components: mips
+//@[mips64el] compile-flags: --target mips64el-unknown-linux-gnuabi64
+//@[mips64el] needs-llvm-components: mips
 
-//@ only-mips64
 // See ./transparent.rs
 
-#![feature(transparent_unions)]
+#![feature(no_core, lang_items, transparent_unions)]
+#![crate_type = "lib"]
+#![no_std]
+#![no_core]
 
-#![crate_type="lib"]
+#[lang="sized"] trait Sized { }
+#[lang="freeze"] trait Freeze { }
+#[lang="copy"] trait Copy { }
 
+impl Copy for [u32; 16] {}
+impl Copy for BigS {}
+impl Copy for BigU {}
 
-#[derive(Clone, Copy)]
 #[repr(C)]
 pub struct BigS([u32; 16]);
 
@@ -26,24 +37,23 @@ pub enum TeBigS {
     Variant(BigS),
 }
 
-// CHECK: define void @test_BigS(%BigS* [[BIGS_RET_ATTRS1:.*]] sret(%BigS) [[BIGS_RET_ATTRS2:.*]], [8 x i64]
+// CHECK: define void @test_BigS(ptr [[BIGS_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGS_RET_ATTRS2:.*]], [8 x i64]
 #[no_mangle]
 pub extern fn test_BigS(_: BigS) -> BigS { loop {} }
 
-// CHECK: define void @test_TsBigS(%TsBigS* [[BIGS_RET_ATTRS1]] sret(%TsBigS) [[BIGS_RET_ATTRS2]], [8 x i64]
+// CHECK: define void @test_TsBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], [8 x i64]
 #[no_mangle]
 pub extern fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} }
 
-// CHECK: define void @test_TuBigS(%TuBigS* [[BIGS_RET_ATTRS1]] sret(%TuBigS) [[BIGS_RET_ATTRS2]], [8 x i64]
+// CHECK: define void @test_TuBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], [8 x i64]
 #[no_mangle]
 pub extern fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} }
 
-// CHECK: define void @test_TeBigS(%"TeBigS::Variant"* [[BIGS_RET_ATTRS1]] sret(%"TeBigS::Variant") [[BIGS_RET_ATTRS2]], [8 x i64]
+// CHECK: define void @test_TeBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], [8 x i64]
 #[no_mangle]
 pub extern fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} }
 
 
-#[derive(Clone, Copy)]
 #[repr(C)]
 pub union BigU {
     foo: [u32; 16],
@@ -62,18 +72,18 @@ pub enum TeBigU {
     Variant(BigU),
 }
 
-// CHECK: define void @test_BigU(%BigU* [[BIGU_RET_ATTRS1:.*]] sret(%BigU) [[BIGU_RET_ATTRS2:.*]], [8 x i64]
+// CHECK: define void @test_BigU(ptr [[BIGU_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], [8 x i64]
 #[no_mangle]
 pub extern fn test_BigU(_: BigU) -> BigU { loop {} }
 
-// CHECK: define void @test_TsBigU(%TsBigU* [[BIGU_RET_ATTRS1]] sret(%TsBigU) [[BIGU_RET_ATTRS2]], [8 x i64]
+// CHECK: define void @test_TsBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2]], [8 x i64]
 #[no_mangle]
 pub extern fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} }
 
-// CHECK: define void @test_TuBigU(%TuBigU* [[BIGU_RET_ATTRS1]] sret(%TuBigU) [[BIGU_RET_ATTRS2]], [8 x i64]
+// CHECK: define void @test_TuBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2]], [8 x i64]
 #[no_mangle]
 pub extern fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} }
 
-// CHECK: define void @test_TeBigU(%"TeBigU::Variant"* [[BIGU_RET_ATTRS1]] sret(%"TeBigU::Variant") [[BIGU_RET_ATTRS2]], [8 x i64]
+// CHECK: define void @test_TeBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2]], [8 x i64]
 #[no_mangle]
 pub extern fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} }
diff --git a/tests/codegen/repr/transparent-sparc64.rs b/tests/codegen/repr/transparent-sparc64.rs
new file mode 100644
index 00000000000..7005a07f554
--- /dev/null
+++ b/tests/codegen/repr/transparent-sparc64.rs
@@ -0,0 +1,101 @@
+//@ compile-flags: -O -C no-prepopulate-passes --target sparc64-unknown-linux-gnu
+//@ needs-llvm-components: sparc
+
+// See ./transparent.rs
+
+#![feature(no_core, lang_items, transparent_unions)]
+#![crate_type = "lib"]
+#![no_std]
+#![no_core]
+
+#[lang="sized"] trait Sized { }
+#[lang="freeze"] trait Freeze { }
+#[lang="copy"] trait Copy { }
+
+impl Copy for [u32; 16] {}
+impl Copy for BigS {}
+impl Copy for BigU {}
+
+
+#[repr(C)]
+pub struct BigS([u32; 16]);
+
+#[repr(transparent)]
+pub struct TsBigS(BigS);
+
+#[repr(transparent)]
+pub union TuBigS {
+    field: BigS,
+}
+
+#[repr(transparent)]
+pub enum TeBigS {
+    Variant(BigS),
+}
+
+// CHECK: define{{.*}}void @test_BigS(ptr [[BIGS_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGS_RET_ATTRS2:.*]], ptr
+// CHECK-NOT: byval
+// CHECK-SAME: %{{[0-9a-z_]+}})
+#[no_mangle]
+pub extern "C" fn test_BigS(_: BigS) -> BigS { loop {} }
+
+// CHECK: define{{.*}}void @test_TsBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], ptr
+// CHECK-NOT: byval
+// CHECK-SAME: %{{[0-9a-z_]+}})
+#[no_mangle]
+pub extern "C" fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} }
+
+// CHECK: define{{.*}}void @test_TuBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], ptr
+// CHECK-NOT: byval
+// CHECK-SAME: %{{[0-9a-z_]+}})
+#[no_mangle]
+pub extern "C" fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} }
+
+// CHECK: define{{.*}}void @test_TeBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], ptr
+// CHECK-NOT: byval
+// CHECK-SAME: %{{[0-9a-z_]+}})
+#[no_mangle]
+pub extern "C" fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} }
+
+
+#[repr(C)]
+pub union BigU {
+    foo: [u32; 16],
+}
+
+#[repr(transparent)]
+pub struct TsBigU(BigU);
+
+#[repr(transparent)]
+pub union TuBigU {
+    field: BigU,
+}
+
+#[repr(transparent)]
+pub enum TeBigU {
+    Variant(BigU),
+}
+
+// CHECK: define{{.*}}void @test_BigU(ptr [[BIGU_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], ptr
+// CHECK-NOT: byval
+// CHECK-SAME: %{{[0-9a-z_]+}})
+#[no_mangle]
+pub extern "C" fn test_BigU(_: BigU) -> BigU { loop {} }
+
+// CHECK: define{{.*}}void @test_TsBigU(ptr [[BIGU_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], ptr
+// CHECK-NOT: byval
+// CHECK-SAME: %{{[0-9a-z_]+}})
+#[no_mangle]
+pub extern "C" fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} }
+
+// CHECK: define{{.*}}void @test_TuBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], ptr
+// CHECK-NOT: byval
+// CHECK-SAME: %{{[0-9a-z_]+}})
+#[no_mangle]
+pub extern "C" fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} }
+
+// CHECK: define{{.*}}void @test_TeBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], ptr
+// CHECK-NOT: byval
+// CHECK-SAME: %{{[0-9a-z_]+}})
+#[no_mangle]
+pub extern "C" fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} }
diff --git a/tests/codegen/repr/transparent-struct-ptr.rs b/tests/codegen/repr/transparent-struct-ptr.rs
index ff531029e04..26f0120752f 100644
--- a/tests/codegen/repr/transparent-struct-ptr.rs
+++ b/tests/codegen/repr/transparent-struct-ptr.rs
@@ -1,23 +1,36 @@
-//@ revisions: x32 x64 sparc sparc64
+//@ revisions: i686-linux i686-freebsd x64-linux x64-apple wasm32
 //@ compile-flags: -O -C no-prepopulate-passes
-//
-//@[x32] only-x86
-//@[x64] only-x86_64
-//@[sparc] only-sparc
-//@[sparc64] only-sparc64
-//@ ignore-windows
+
+//@[i686-linux] compile-flags: --target i686-unknown-linux-gnu
+//@[i686-linux] needs-llvm-components: x86
+//@[i686-freebsd] compile-flags: --target i686-unknown-freebsd
+//@[i686-freebsd] needs-llvm-components: x86
+//@[x64-linux] compile-flags: --target x86_64-unknown-linux-gnu
+//@[x64-linux] needs-llvm-components: x86
+//@[x64-apple] compile-flags: --target x86_64-apple-darwin
+//@[x64-apple] needs-llvm-components: x86
+//@[wasm32] compile-flags: --target wasm32-wasi
+//@[wasm32] needs-llvm-components: webassembly
+
 // See ./transparent.rs
 // Some platforms pass large aggregates using immediate arrays in LLVMIR
 // Other platforms pass large aggregates using struct pointer in LLVMIR
 // This covers the "struct pointer" case.
 
+#![feature(no_core, lang_items, transparent_unions)]
+#![crate_type = "lib"]
+#![no_std]
+#![no_core]
 
-#![feature(transparent_unions)]
+#[lang="sized"] trait Sized { }
+#[lang="freeze"] trait Freeze { }
+#[lang="copy"] trait Copy { }
 
-#![crate_type="lib"]
+impl Copy for [u32; 16] {}
+impl Copy for BigS {}
+impl Copy for BigU {}
 
 
-#[derive(Clone, Copy)]
 #[repr(C)]
 pub struct BigS([u32; 16]);
 
@@ -34,24 +47,23 @@ pub enum TeBigS {
     Variant(BigS),
 }
 
-// CHECK: define{{.*}}void @test_BigS(ptr [[BIGS_RET_ATTRS1:.*]] sret(%BigS) [[BIGS_RET_ATTRS2:.*]], ptr [[BIGS_ARG_ATTRS1:.*]] byval(%BigS) [[BIGS_ARG_ATTRS2:.*]])
+// CHECK: define{{.*}}void @test_BigS(ptr [[BIGS_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGS_RET_ATTRS2:.*]], ptr [[BIGS_ARG_ATTRS1:.*]] byval([64 x i8]) [[BIGS_ARG_ATTRS2:.*]])
 #[no_mangle]
 pub extern "C" fn test_BigS(_: BigS) -> BigS { loop {} }
 
-// CHECK: define{{.*}}void @test_TsBigS(ptr [[BIGS_RET_ATTRS1]] sret(%TsBigS) [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval(%TsBigS) [[BIGS_ARG_ATTRS2:.*]])
+// CHECK: define{{.*}}void @test_TsBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval([64 x i8]) [[BIGS_ARG_ATTRS2:.*]])
 #[no_mangle]
 pub extern "C" fn test_TsBigS(_: TsBigS) -> TsBigS { loop {} }
 
-// CHECK: define{{.*}}void @test_TuBigS(ptr [[BIGS_RET_ATTRS1]] sret(%TuBigS) [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval(%TuBigS) [[BIGS_ARG_ATTRS2:.*]])
+// CHECK: define{{.*}}void @test_TuBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval([64 x i8]) [[BIGS_ARG_ATTRS2:.*]])
 #[no_mangle]
 pub extern "C" fn test_TuBigS(_: TuBigS) -> TuBigS { loop {} }
 
-// CHECK: define{{.*}}void @test_TeBigS(ptr [[BIGS_RET_ATTRS1]] sret(%"TeBigS::Variant") [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval(%"TeBigS::Variant") [[BIGS_ARG_ATTRS2]])
+// CHECK: define{{.*}}void @test_TeBigS(ptr [[BIGS_RET_ATTRS1]] sret([64 x i8]) [[BIGS_RET_ATTRS2]], ptr [[BIGS_ARG_ATTRS1]] byval([64 x i8]) [[BIGS_ARG_ATTRS2]])
 #[no_mangle]
 pub extern "C" fn test_TeBigS(_: TeBigS) -> TeBigS { loop {} }
 
 
-#[derive(Clone, Copy)]
 #[repr(C)]
 pub union BigU {
     foo: [u32; 16],
@@ -70,18 +82,18 @@ pub enum TeBigU {
     Variant(BigU),
 }
 
-// CHECK: define{{.*}}void @test_BigU(ptr [[BIGU_RET_ATTRS1:.*]] sret(%BigU) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1:.*]] byval(%BigU) [[BIGU_ARG_ATTRS2:.*]])
+// CHECK: define{{.*}}void @test_BigU(ptr [[BIGU_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1:.*]] byval([64 x i8]) [[BIGU_ARG_ATTRS2:.*]])
 #[no_mangle]
 pub extern "C" fn test_BigU(_: BigU) -> BigU { loop {} }
 
-// CHECK: define{{.*}}void @test_TsBigU(ptr [[BIGU_RET_ATTRS1:.*]] sret(%TsBigU) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval(%TsBigU) [[BIGU_ARG_ATTRS2]])
+// CHECK: define{{.*}}void @test_TsBigU(ptr [[BIGU_RET_ATTRS1:.*]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval([64 x i8]) [[BIGU_ARG_ATTRS2]])
 #[no_mangle]
 pub extern "C" fn test_TsBigU(_: TsBigU) -> TsBigU { loop {} }
 
-// CHECK: define{{.*}}void @test_TuBigU(ptr [[BIGU_RET_ATTRS1]] sret(%TuBigU) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval(%TuBigU) [[BIGU_ARG_ATTRS2]])
+// CHECK: define{{.*}}void @test_TuBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval([64 x i8]) [[BIGU_ARG_ATTRS2]])
 #[no_mangle]
 pub extern "C" fn test_TuBigU(_: TuBigU) -> TuBigU { loop {} }
 
-// CHECK: define{{.*}}void @test_TeBigU(ptr [[BIGU_RET_ATTRS1]] sret(%"TeBigU::Variant") [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval(%"TeBigU::Variant") [[BIGU_ARG_ATTRS2]])
+// CHECK: define{{.*}}void @test_TeBigU(ptr [[BIGU_RET_ATTRS1]] sret([64 x i8]) [[BIGU_RET_ATTRS2:.*]], ptr [[BIGU_ARG_ATTRS1]] byval([64 x i8]) [[BIGU_ARG_ATTRS2]])
 #[no_mangle]
 pub extern "C" fn test_TeBigU(_: TeBigU) -> TeBigU { loop {} }
diff --git a/tests/codegen/repr/transparent-sysv64.rs b/tests/codegen/repr/transparent-sysv64.rs
index 10524adf7d7..1c7bca7ee40 100644
--- a/tests/codegen/repr/transparent-sysv64.rs
+++ b/tests/codegen/repr/transparent-sysv64.rs
@@ -1,8 +1,21 @@
-//@ only-x86_64
-
-//@ compile-flags: -C no-prepopulate-passes
-
-#![crate_type="lib"]
+//@ revisions: linux apple windows
+//@ compile-flags: -O -C no-prepopulate-passes
+
+//@[linux] compile-flags: --target x86_64-unknown-linux-gnu
+//@[linux] needs-llvm-components: x86
+//@[apple] compile-flags: --target x86_64-apple-darwin
+//@[apple] needs-llvm-components: x86
+//@[windows] compile-flags: --target x86_64-pc-windows-msvc
+//@[windows] needs-llvm-components: x86
+
+#![feature(no_core, lang_items)]
+#![crate_type = "lib"]
+#![no_std]
+#![no_core]
+
+#[lang="sized"] trait Sized { }
+#[lang="freeze"] trait Freeze { }
+#[lang="copy"] trait Copy { }
 
 #[repr(C)]
 pub struct Rgb8 { r: u8, g: u8, b: u8 }
diff --git a/tests/codegen/simd/unpadded-simd.rs b/tests/codegen/simd/unpadded-simd.rs
index 797bca38ffa..66d9298c006 100644
--- a/tests/codegen/simd/unpadded-simd.rs
+++ b/tests/codegen/simd/unpadded-simd.rs
@@ -3,7 +3,7 @@
 // See #87254.
 
 #![crate_type = "lib"]
-#![feature(repr_simd)]
+#![feature(repr_simd, abi_unadjusted)]
 
 #[derive(Copy, Clone)]
 #[repr(simd)]
@@ -14,6 +14,6 @@ pub struct int16x4x2_t(pub int16x4_t, pub int16x4_t);
 
 // CHECK: %int16x4x2_t = type { <4 x i16>, <4 x i16> }
 #[no_mangle]
-fn takes_int16x4x2_t(t: int16x4x2_t) -> int16x4x2_t {
+extern "unadjusted" fn takes_int16x4x2_t(t: int16x4x2_t) -> int16x4x2_t {
     t
 }
diff --git a/tests/codegen/unwind-abis/nounwind-on-stable-panic-abort.rs b/tests/codegen/unwind-abis/nounwind-on-stable-panic-abort.rs
index 0b3bfd567aa..d27cbd60437 100644
--- a/tests/codegen/unwind-abis/nounwind-on-stable-panic-abort.rs
+++ b/tests/codegen/unwind-abis/nounwind-on-stable-panic-abort.rs
@@ -1,5 +1,4 @@
 //@ compile-flags: -C opt-level=0 -Cpanic=abort
-//@ ignore-wasm32-bare compiled with panic=abort by default
 
 #![crate_type = "lib"]
 
diff --git a/tests/codegen/unwind-abis/nounwind-on-stable-panic-unwind.rs b/tests/codegen/unwind-abis/nounwind-on-stable-panic-unwind.rs
index 1e6f8c9ede9..a7f7f2fb77f 100644
--- a/tests/codegen/unwind-abis/nounwind-on-stable-panic-unwind.rs
+++ b/tests/codegen/unwind-abis/nounwind-on-stable-panic-unwind.rs
@@ -1,5 +1,4 @@
 //@ compile-flags: -C opt-level=0
-//@ ignore-wasm32-bare compiled with panic=abort by default
 //@ needs-unwind
 
 #![crate_type = "lib"]
diff --git a/tests/codegen/unwind-abis/nounwind.rs b/tests/codegen/unwind-abis/nounwind.rs
index ac53cd7bed3..80bf8d67091 100644
--- a/tests/codegen/unwind-abis/nounwind.rs
+++ b/tests/codegen/unwind-abis/nounwind.rs
@@ -1,5 +1,5 @@
 //@ compile-flags: -C opt-level=0 -Cpanic=abort
-//@ ignore-wasm32-bare compiled with panic=abort by default
+//@ needs-unwind
 
 #![crate_type = "lib"]
 #![feature(c_unwind)]
diff --git a/tests/codegen/unwind-extern-exports.rs b/tests/codegen/unwind-extern-exports.rs
index d670a776ac6..ea59748b3bc 100644
--- a/tests/codegen/unwind-extern-exports.rs
+++ b/tests/codegen/unwind-extern-exports.rs
@@ -1,5 +1,4 @@
 //@ compile-flags: -C opt-level=0
-//@ ignore-wasm32-bare compiled with panic=abort by default
 //@ needs-unwind
 
 #![crate_type = "lib"]
diff --git a/tests/codegen/unwind-extern-imports.rs b/tests/codegen/unwind-extern-imports.rs
index 7386704b430..790e4def8b3 100644
--- a/tests/codegen/unwind-extern-imports.rs
+++ b/tests/codegen/unwind-extern-imports.rs
@@ -1,5 +1,4 @@
 //@ compile-flags: -C no-prepopulate-passes
-//@ ignore-wasm32-bare compiled with panic=abort by default
 //@ needs-unwind
 
 #![crate_type = "lib"]
diff --git a/tests/codegen/vtable-upcast.rs b/tests/codegen/vtable-upcast.rs
new file mode 100644
index 00000000000..41a4be26cb4
--- /dev/null
+++ b/tests/codegen/vtable-upcast.rs
@@ -0,0 +1,85 @@
+//! This file tests that we correctly generate GEP instructions for vtable upcasting.
+//@ compile-flags: -C no-prepopulate-passes -Copt-level=0
+
+#![crate_type = "lib"]
+#![feature(trait_upcasting)]
+
+pub trait Base {
+    fn base(&self);
+}
+
+pub trait A : Base {
+    fn a(&self);
+}
+
+pub trait B : Base {
+    fn b(&self);
+}
+
+pub trait Diamond : A + B {
+    fn diamond(&self);
+}
+
+// CHECK-LABEL: upcast_a_to_base
+#[no_mangle]
+pub fn upcast_a_to_base(x: &dyn A) -> &dyn Base {
+    // Requires no adjustment, since its vtable is extended from `Base`.
+
+    // CHECK: start:
+    // CHECK-NEXT: insertvalue
+    // CHECK-NEXT: insertvalue
+    // CHECK-NEXT: ret
+    x as &dyn Base
+}
+
+// CHECK-LABEL: upcast_b_to_base
+#[no_mangle]
+pub fn upcast_b_to_base(x: &dyn B) -> &dyn Base {
+    // Requires no adjustment, since its vtable is extended from `Base`.
+
+    // CHECK: start:
+    // CHECK-NEXT: insertvalue
+    // CHECK-NEXT: insertvalue
+    // CHECK-NEXT: ret
+    x as &dyn Base
+}
+
+// CHECK-LABEL: upcast_diamond_to_a
+#[no_mangle]
+pub fn upcast_diamond_to_a(x: &dyn Diamond) -> &dyn A {
+    // Requires no adjustment, since its vtable is extended from `A` (as the first supertrait).
+
+    // CHECK: start:
+    // CHECK-NEXT: insertvalue
+    // CHECK-NEXT: insertvalue
+    // CHECK-NEXT: ret
+    x as &dyn A
+}
+
+// CHECK-LABEL: upcast_diamond_to_b
+// CHECK-SAME: (ptr align {{[0-9]+}} [[DATA_PTR:%.+]], ptr align {{[0-9]+}} [[VTABLE_PTR:%.+]])
+#[no_mangle]
+pub fn upcast_diamond_to_b(x: &dyn Diamond) -> &dyn B {
+    // Requires adjustment, since it's a non-first supertrait.
+
+    // CHECK: start:
+    // CHECK-NEXT: [[UPCAST_SLOT_PTR:%.+]] = getelementptr inbounds i8, ptr [[VTABLE_PTR]]
+    // CHECK-NEXT: [[UPCAST_VTABLE_PTR:%.+]] = load ptr, ptr [[UPCAST_SLOT_PTR]]
+    // CHECK-NEXT: [[FAT_PTR_1:%.+]] = insertvalue { ptr, ptr } poison, ptr [[DATA_PTR]], 0
+    // CHECK-NEXT: [[FAT_PTR_2:%.+]] = insertvalue { ptr, ptr } [[FAT_PTR_1]], ptr [[UPCAST_VTABLE_PTR]], 1
+    // CHECK-NEXT: ret { ptr, ptr } [[FAT_PTR_2]]
+    x as &dyn B
+}
+
+// CHECK-LABEL: upcast_diamond_to_b
+#[no_mangle]
+pub fn upcast_diamond_to_base(x: &dyn Diamond) -> &dyn Base {
+    // Requires no adjustment, since `Base` is the first supertrait of `A`,
+    // which is the first supertrait of `Diamond`.
+
+    // CHECK: start:
+    // CHECK-NEXT: insertvalue
+    // CHECK-NEXT: insertvalue
+    // CHECK-NEXT: ret
+    x as &dyn Base
+}
diff --git a/tests/codegen/wasm_exceptions.rs b/tests/codegen/wasm_exceptions.rs
index 66d2bbed709..a53722f834c 100644
--- a/tests/codegen/wasm_exceptions.rs
+++ b/tests/codegen/wasm_exceptions.rs
@@ -1,4 +1,4 @@
-//@ only-wasm32-bare
+//@ only-wasm32
 //@ compile-flags: -C panic=unwind
 
 #![crate_type = "lib"]
diff --git a/tests/incremental/change_crate_dep_kind.rs b/tests/incremental/change_crate_dep_kind.rs
index d3408f7ad2b..abca8de4719 100644
--- a/tests/incremental/change_crate_dep_kind.rs
+++ b/tests/incremental/change_crate_dep_kind.rs
@@ -1,7 +1,6 @@
 // Test that we detect changes to the `dep_kind` query. If the change is not
 // detected then -Zincremental-verify-ich will trigger an assertion.
 
-//@ ignore-wasm32-bare compiled with panic=abort by default
 //@ needs-unwind
 //@ revisions:cfail1 cfail2
 //@ compile-flags: -Z query-dep-graph -Cpanic=unwind
diff --git a/tests/incremental/issue-54059.rs b/tests/incremental/issue-54059.rs
index a5408c671b7..bfce4d487db 100644
--- a/tests/incremental/issue-54059.rs
+++ b/tests/incremental/issue-54059.rs
@@ -1,5 +1,4 @@
 //@ aux-build:issue-54059.rs
-//@ ignore-wasm32-bare no libc for ffi testing
 //@ ignore-windows - dealing with weird symbols issues on dylibs isn't worth it
 //@ revisions: rpass1
 
diff --git a/tests/mir-opt/building/custom/consts.consts.built.after.mir b/tests/mir-opt/building/custom/consts.consts.built.after.mir
index 05de272afe4..a011fadcef1 100644
--- a/tests/mir-opt/building/custom/consts.consts.built.after.mir
+++ b/tests/mir-opt/building/custom/consts.consts.built.after.mir
@@ -10,9 +10,9 @@ fn consts() -> () {
 
     bb0: {
         _1 = const 5_u8;
-        _2 = const _;
+        _2 = const consts::<C>::{constant#0};
         _3 = const C;
-        _4 = const _;
+        _4 = const D;
         _5 = consts::<10>;
         return;
     }
diff --git a/tests/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir
index 960b982242d..b4ae8386add 100644
--- a/tests/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir
+++ b/tests/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir
@@ -1,6 +1,6 @@
 // MIR for `BAR::promoted[0]` after SimplifyCfg-elaborate-drops
 
-promoted[0] in BAR: &[&i32; 1] = {
+const BAR::promoted[0]: &[&i32; 1] = {
     let mut _0: &[&i32; 1];
     let mut _1: [&i32; 1];
     let mut _2: &i32;
diff --git a/tests/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff b/tests/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff
index 4a93db3fcaa..f412048b6ec 100644
--- a/tests/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff
+++ b/tests/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff
@@ -20,7 +20,7 @@
 -         _4 = &(*_5);
 -         _3 = [move _4];
 -         _2 = &_3;
-+         _6 = const _;
++         _6 = const BAR::promoted[0];
 +         _2 = &(*_6);
           _1 = move _2 as &[&i32] (PointerCoercion(Unsize));
 -         StorageDead(_4);
diff --git a/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir
index a9c05442764..8d4bfa711e4 100644
--- a/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir
+++ b/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir
@@ -1,6 +1,6 @@
 // MIR for `FOO::promoted[0]` after SimplifyCfg-elaborate-drops
 
-promoted[0] in FOO: &[&i32; 1] = {
+const FOO::promoted[0]: &[&i32; 1] = {
     let mut _0: &[&i32; 1];
     let mut _1: [&i32; 1];
     let mut _2: &i32;
diff --git a/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff b/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
index 21d21b0eee0..3596671f614 100644
--- a/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
+++ b/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
@@ -22,7 +22,7 @@
 -         _4 = &(*_5);
 -         _3 = [move _4];
 -         _2 = &_3;
-+         _6 = const _;
++         _6 = const FOO::promoted[0];
 +         _2 = &(*_6);
           _1 = move _2 as &[&i32] (PointerCoercion(Unsize));
 -         StorageDead(_4);
diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff
index e1a93e31446..20fda589c39 100644
--- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff
+++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-abort.diff
@@ -25,7 +25,7 @@
           StorageLive(_1);
           StorageLive(_2);
           StorageLive(_3);
-          _9 = const _;
+          _9 = const main::promoted[0];
           _3 = &(*_9);
           _2 = &raw const (*_3);
           _1 = move _2 as *const [i32] (PointerCoercion(Unsize));
diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff
index 91999145efb..f1b90c28e72 100644
--- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff
+++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.32bit.panic-unwind.diff
@@ -25,7 +25,7 @@
           StorageLive(_1);
           StorageLive(_2);
           StorageLive(_3);
-          _9 = const _;
+          _9 = const main::promoted[0];
           _3 = &(*_9);
           _2 = &raw const (*_3);
           _1 = move _2 as *const [i32] (PointerCoercion(Unsize));
diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff
index e1a93e31446..20fda589c39 100644
--- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff
+++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-abort.diff
@@ -25,7 +25,7 @@
           StorageLive(_1);
           StorageLive(_2);
           StorageLive(_3);
-          _9 = const _;
+          _9 = const main::promoted[0];
           _3 = &(*_9);
           _2 = &raw const (*_3);
           _1 = move _2 as *const [i32] (PointerCoercion(Unsize));
diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff
index 91999145efb..f1b90c28e72 100644
--- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff
+++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.main.GVN.64bit.panic-unwind.diff
@@ -25,7 +25,7 @@
           StorageLive(_1);
           StorageLive(_2);
           StorageLive(_3);
-          _9 = const _;
+          _9 = const main::promoted[0];
           _3 = &(*_9);
           _2 = &raw const (*_3);
           _1 = move _2 as *const [i32] (PointerCoercion(Unsize));
diff --git a/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-abort.diff b/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-abort.diff
index 803e1d711de..886f9a68dd9 100644
--- a/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-abort.diff
+++ b/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-abort.diff
@@ -8,7 +8,7 @@
   
       bb0: {
           StorageLive(_1);
-          _1 = const _;
+          _1 = const <bool as NeedsDrop>::NEEDS;
 -         switchInt(move _1) -> [0: bb2, otherwise: bb1];
 +         switchInt(const false) -> [0: bb2, otherwise: bb1];
       }
diff --git a/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-unwind.diff
index f40eb38c634..cc53b213397 100644
--- a/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-unwind.diff
+++ b/tests/mir-opt/const_prop/control_flow_simplification.hello.GVN.panic-unwind.diff
@@ -8,7 +8,7 @@
   
       bb0: {
           StorageLive(_1);
-          _1 = const _;
+          _1 = const <bool as NeedsDrop>::NEEDS;
 -         switchInt(move _1) -> [0: bb2, otherwise: bb1];
 +         switchInt(const false) -> [0: bb2, otherwise: bb1];
       }
diff --git a/tests/mir-opt/const_prop/overwrite_with_const_with_params.rs b/tests/mir-opt/const_prop/overwrite_with_const_with_params.rs
index 836f837d15f..535870fdf88 100644
--- a/tests/mir-opt/const_prop/overwrite_with_const_with_params.rs
+++ b/tests/mir-opt/const_prop/overwrite_with_const_with_params.rs
@@ -14,7 +14,7 @@ impl<T> SizeOfConst<T> {
 fn size_of<T>() -> usize {
     // CHECK-LABEL: fn size_of(
     // CHECK: _1 = const 0_usize;
-    // CHECK-NEXT: _1 = const _;
+    // CHECK-NEXT: _1 = const SizeOfConst::<T>::SIZE;
     // CHECK-NEXT: _0 = _1;
     let mut a = 0;
     a = SizeOfConst::<T>::SIZE;
diff --git a/tests/mir-opt/const_prop/overwrite_with_const_with_params.size_of.GVN.diff b/tests/mir-opt/const_prop/overwrite_with_const_with_params.size_of.GVN.diff
index caa78b7316e..1eadffa4f36 100644
--- a/tests/mir-opt/const_prop/overwrite_with_const_with_params.size_of.GVN.diff
+++ b/tests/mir-opt/const_prop/overwrite_with_const_with_params.size_of.GVN.diff
@@ -11,7 +11,7 @@
       bb0: {
           StorageLive(_1);
           _1 = const 0_usize;
-          _1 = const _;
+          _1 = const SizeOfConst::<T>::SIZE;
           _0 = _1;
           StorageDead(_1);
           return;
diff --git a/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-abort.diff b/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-abort.diff
index 4e79b3ad599..596eb1a9966 100644
--- a/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-abort.diff
+++ b/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-abort.diff
@@ -17,7 +17,7 @@
 +         nop;
           StorageLive(_2);
           StorageLive(_3);
-          _3 = const _;
+          _3 = const main::FOO;
           _2 = &raw const (*_3);
           _1 = move _2 as usize (PointerExposeAddress);
           StorageDead(_2);
diff --git a/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-unwind.diff b/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-unwind.diff
index fdc459b457c..995f281ecf5 100644
--- a/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-unwind.diff
+++ b/tests/mir-opt/const_prop/pointer_expose_address.main.GVN.panic-unwind.diff
@@ -17,7 +17,7 @@
 +         nop;
           StorageLive(_2);
           StorageLive(_3);
-          _3 = const _;
+          _3 = const main::FOO;
           _2 = &raw const (*_3);
           _1 = move _2 as usize (PointerExposeAddress);
           StorageDead(_2);
diff --git a/tests/mir-opt/const_prop/pointer_expose_address.rs b/tests/mir-opt/const_prop/pointer_expose_address.rs
index 4d0dfecd324..a6b4f8857c3 100644
--- a/tests/mir-opt/const_prop/pointer_expose_address.rs
+++ b/tests/mir-opt/const_prop/pointer_expose_address.rs
@@ -7,7 +7,7 @@ fn read(_: usize) { }
 // EMIT_MIR pointer_expose_address.main.GVN.diff
 fn main() {
     // CHECK-LABEL: fn main(
-    // CHECK: [[ptr:_.*]] = const _;
+    // CHECK: [[ptr:_.*]] = const main::FOO;
     // CHECK: [[ref:_.*]] = &raw const (*[[ptr]]);
     // CHECK: [[x:_.*]] = move [[ref]] as usize (PointerExposeAddress);
     // CHECK: = read([[x]])
diff --git a/tests/mir-opt/const_prop/ref_deref.main.GVN.diff b/tests/mir-opt/const_prop/ref_deref.main.GVN.diff
index 56cbd00025e..509924a91c5 100644
--- a/tests/mir-opt/const_prop/ref_deref.main.GVN.diff
+++ b/tests/mir-opt/const_prop/ref_deref.main.GVN.diff
@@ -14,7 +14,7 @@
       bb0: {
           StorageLive(_1);
           StorageLive(_2);
-          _4 = const _;
+          _4 = const main::promoted[0];
           _2 = &(*_4);
 -         _1 = (*_2);
 +         _1 = const 4_i32;
diff --git a/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff b/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff
index d75c0c3b286..820c6cc0680 100644
--- a/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff
+++ b/tests/mir-opt/const_prop/ref_deref_project.main.GVN.diff
@@ -14,7 +14,7 @@
       bb0: {
           StorageLive(_1);
           StorageLive(_2);
-          _4 = const _;
+          _4 = const main::promoted[0];
           _2 = &((*_4).1: i32);
 -         _1 = (*_2);
 +         _1 = const 5_i32;
diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff
index 5c21c628f85..ef298dddd5a 100644
--- a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff
+++ b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-abort.diff
@@ -21,7 +21,7 @@
           StorageLive(_2);
           StorageLive(_3);
           StorageLive(_4);
-          _9 = const _;
+          _9 = const main::promoted[0];
 -         _4 = _9;
 -         _3 = _4;
 -         _2 = move _3 as &[u32] (PointerCoercion(Unsize));
diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff
index 470cd9c9d8f..5379df3f60b 100644
--- a/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff
+++ b/tests/mir-opt/const_prop/slice_len.main.GVN.32bit.panic-unwind.diff
@@ -21,7 +21,7 @@
           StorageLive(_2);
           StorageLive(_3);
           StorageLive(_4);
-          _9 = const _;
+          _9 = const main::promoted[0];
 -         _4 = _9;
 -         _3 = _4;
 -         _2 = move _3 as &[u32] (PointerCoercion(Unsize));
diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff
index 5c21c628f85..ef298dddd5a 100644
--- a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff
+++ b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-abort.diff
@@ -21,7 +21,7 @@
           StorageLive(_2);
           StorageLive(_3);
           StorageLive(_4);
-          _9 = const _;
+          _9 = const main::promoted[0];
 -         _4 = _9;
 -         _3 = _4;
 -         _2 = move _3 as &[u32] (PointerCoercion(Unsize));
diff --git a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff
index 470cd9c9d8f..5379df3f60b 100644
--- a/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff
+++ b/tests/mir-opt/const_prop/slice_len.main.GVN.64bit.panic-unwind.diff
@@ -21,7 +21,7 @@
           StorageLive(_2);
           StorageLive(_3);
           StorageLive(_4);
-          _9 = const _;
+          _9 = const main::promoted[0];
 -         _4 = _9;
 -         _3 = _4;
 -         _2 = move _3 as &[u32] (PointerCoercion(Unsize));
diff --git a/tests/mir-opt/const_prop/transmute.invalid_char.GVN.32bit.diff b/tests/mir-opt/const_prop/transmute.invalid_char.GVN.32bit.diff
index a9e32d4d925..03a7706401f 100644
--- a/tests/mir-opt/const_prop/transmute.invalid_char.GVN.32bit.diff
+++ b/tests/mir-opt/const_prop/transmute.invalid_char.GVN.32bit.diff
@@ -7,7 +7,7 @@
       }
   
       bb0: {
--         _0 = const _ as char (Transmute);
+-         _0 = const core::num::<impl i32>::MAX as char (Transmute);
 +         _0 = const {transmute(0x7fffffff): char};
           return;
       }
diff --git a/tests/mir-opt/const_prop/transmute.invalid_char.GVN.64bit.diff b/tests/mir-opt/const_prop/transmute.invalid_char.GVN.64bit.diff
index a9e32d4d925..03a7706401f 100644
--- a/tests/mir-opt/const_prop/transmute.invalid_char.GVN.64bit.diff
+++ b/tests/mir-opt/const_prop/transmute.invalid_char.GVN.64bit.diff
@@ -7,7 +7,7 @@
       }
   
       bb0: {
--         _0 = const _ as char (Transmute);
+-         _0 = const core::num::<impl i32>::MAX as char (Transmute);
 +         _0 = const {transmute(0x7fffffff): char};
           return;
       }
diff --git a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff
index 4569ffe483b..b35538f8972 100644
--- a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff
+++ b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-abort.diff
@@ -53,7 +53,7 @@
           StorageDead(_5);
           StorageDead(_4);
           StorageLive(_7);
-          _7 = const _;
+          _7 = const core::num::<impl i32>::MAX;
           StorageLive(_8);
           StorageLive(_9);
 -         _9 = _7;
diff --git a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff
index aa7e404eb9f..05c96969233 100644
--- a/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff
+++ b/tests/mir-opt/dataflow-const-prop/checked.main.DataflowConstProp.panic-unwind.diff
@@ -53,7 +53,7 @@
           StorageDead(_5);
           StorageDead(_4);
           StorageLive(_7);
-          _7 = const _;
+          _7 = const core::num::<impl i32>::MAX;
           StorageLive(_8);
           StorageLive(_9);
 -         _9 = _7;
diff --git a/tests/mir-opt/dataflow-const-prop/checked.rs b/tests/mir-opt/dataflow-const-prop/checked.rs
index 2c419bc9854..d3d0938168b 100644
--- a/tests/mir-opt/dataflow-const-prop/checked.rs
+++ b/tests/mir-opt/dataflow-const-prop/checked.rs
@@ -23,7 +23,7 @@ fn main() {
     // CHECK: [[c]] = const 3_i32;
     let c = a + b;
 
-    // CHECK: [[d]] = const _;
+    // CHECK: [[d]] = const core::num::<impl i32>::MAX;
     let d = i32::MAX;
 
     // CHECK: assert(!const true,
diff --git a/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.32bit.diff
index fc814f7e7a9..9da1caf9004 100644
--- a/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.32bit.diff
+++ b/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.32bit.diff
@@ -23,7 +23,7 @@
   
       bb0: {
           StorageLive(_1);
-          _1 = const _;
+          _1 = const constant::C;
           StorageLive(_2);
 -         _3 = discriminant(_1);
 -         switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1];
diff --git a/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.64bit.diff
index fc814f7e7a9..9da1caf9004 100644
--- a/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.64bit.diff
+++ b/tests/mir-opt/dataflow-const-prop/enum.constant.DataflowConstProp.64bit.diff
@@ -23,7 +23,7 @@
   
       bb0: {
           StorageLive(_1);
-          _1 = const _;
+          _1 = const constant::C;
           StorageLive(_2);
 -         _3 = discriminant(_1);
 -         switchInt(move _3) -> [0: bb3, 1: bb2, otherwise: bb1];
diff --git a/tests/mir-opt/dataflow-const-prop/enum.rs b/tests/mir-opt/dataflow-const-prop/enum.rs
index b00f2912519..82752750eb1 100644
--- a/tests/mir-opt/dataflow-const-prop/enum.rs
+++ b/tests/mir-opt/dataflow-const-prop/enum.rs
@@ -34,7 +34,7 @@ fn constant() {
     // CHECK: debug x => [[x:_.*]];
     const C: E = E::V1(0);
 
-    // CHECK: [[e]] = const _;
+    // CHECK: [[e]] = const constant::C;
     let e = C;
     // CHECK: switchInt(const 0_isize) -> [0: [[target_bb:bb.*]], 1: bb2, otherwise: bb1];
     // CHECK: [[target_bb]]: {
diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-abort.diff
index e99b413f708..efba4a4646c 100644
--- a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-abort.diff
+++ b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-abort.diff
@@ -29,7 +29,7 @@
           StorageLive(_2);
           StorageLive(_3);
           StorageLive(_4);
-          _14 = const _;
+          _14 = const main::promoted[0];
           _4 = _14;
           _3 = _4;
           _2 = move _3 as &[u32] (PointerCoercion(Unsize));
@@ -52,7 +52,7 @@
           StorageDead(_2);
           StorageLive(_9);
           StorageLive(_10);
-          _10 = const _;
+          _10 = const main::SLICE;
           StorageLive(_11);
           _11 = const 1_usize;
 -         _12 = Len((*_10));
diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-unwind.diff
index 759a793fbf3..bf477d7e041 100644
--- a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-unwind.diff
+++ b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.32bit.panic-unwind.diff
@@ -29,7 +29,7 @@
           StorageLive(_2);
           StorageLive(_3);
           StorageLive(_4);
-          _14 = const _;
+          _14 = const main::promoted[0];
           _4 = _14;
           _3 = _4;
           _2 = move _3 as &[u32] (PointerCoercion(Unsize));
@@ -52,7 +52,7 @@
           StorageDead(_2);
           StorageLive(_9);
           StorageLive(_10);
-          _10 = const _;
+          _10 = const main::SLICE;
           StorageLive(_11);
           _11 = const 1_usize;
 -         _12 = Len((*_10));
diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-abort.diff b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-abort.diff
index e99b413f708..efba4a4646c 100644
--- a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-abort.diff
+++ b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-abort.diff
@@ -29,7 +29,7 @@
           StorageLive(_2);
           StorageLive(_3);
           StorageLive(_4);
-          _14 = const _;
+          _14 = const main::promoted[0];
           _4 = _14;
           _3 = _4;
           _2 = move _3 as &[u32] (PointerCoercion(Unsize));
@@ -52,7 +52,7 @@
           StorageDead(_2);
           StorageLive(_9);
           StorageLive(_10);
-          _10 = const _;
+          _10 = const main::SLICE;
           StorageLive(_11);
           _11 = const 1_usize;
 -         _12 = Len((*_10));
diff --git a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-unwind.diff b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-unwind.diff
index 759a793fbf3..bf477d7e041 100644
--- a/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-unwind.diff
+++ b/tests/mir-opt/dataflow-const-prop/slice_len.main.DataflowConstProp.64bit.panic-unwind.diff
@@ -29,7 +29,7 @@
           StorageLive(_2);
           StorageLive(_3);
           StorageLive(_4);
-          _14 = const _;
+          _14 = const main::promoted[0];
           _4 = _14;
           _3 = _4;
           _2 = move _3 as &[u32] (PointerCoercion(Unsize));
@@ -52,7 +52,7 @@
           StorageDead(_2);
           StorageLive(_9);
           StorageLive(_10);
-          _10 = const _;
+          _10 = const main::SLICE;
           StorageLive(_11);
           _11 = const 1_usize;
 -         _12 = Len((*_10));
diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff
index c486281d6f8..f674169e28b 100644
--- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff
+++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.32bit.diff
@@ -101,7 +101,7 @@
           StorageDead(_6);
           StorageDead(_5);
           StorageLive(_10);
-          _10 = const _;
+          _10 = const main::SMALL_VAL;
           StorageLive(_7);
 -         _7 = (_10.0: f32);
 +         _7 = const 4f32;
@@ -139,7 +139,7 @@
           StorageDead(_17);
           StorageDead(_16);
           StorageLive(_22);
-          _22 = const _;
+          _22 = const main::BIG_VAL;
           StorageLive(_19);
 -         _19 = (_22.0: f32);
 +         _19 = const 25f32;
diff --git a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff
index 7ea53d15733..c2608190a6b 100644
--- a/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff
+++ b/tests/mir-opt/dataflow-const-prop/struct.main.DataflowConstProp.64bit.diff
@@ -101,7 +101,7 @@
           StorageDead(_6);
           StorageDead(_5);
           StorageLive(_10);
-          _10 = const _;
+          _10 = const main::SMALL_VAL;
           StorageLive(_7);
 -         _7 = (_10.0: f32);
 +         _7 = const 4f32;
@@ -139,7 +139,7 @@
           StorageDead(_17);
           StorageDead(_16);
           StorageLive(_22);
-          _22 = const _;
+          _22 = const main::BIG_VAL;
           StorageLive(_19);
 -         _19 = (_22.0: f32);
 +         _19 = const 25f32;
diff --git a/tests/mir-opt/dataflow-const-prop/transmute.invalid_char.DataflowConstProp.32bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.invalid_char.DataflowConstProp.32bit.diff
index 837dabde42a..dd737017ffd 100644
--- a/tests/mir-opt/dataflow-const-prop/transmute.invalid_char.DataflowConstProp.32bit.diff
+++ b/tests/mir-opt/dataflow-const-prop/transmute.invalid_char.DataflowConstProp.32bit.diff
@@ -7,7 +7,7 @@
       }
   
       bb0: {
--         _0 = const _ as char (Transmute);
+-         _0 = const core::num::<impl i32>::MAX as char (Transmute);
 +         _0 = const {transmute(0x7fffffff): char};
           return;
       }
diff --git a/tests/mir-opt/dataflow-const-prop/transmute.invalid_char.DataflowConstProp.64bit.diff b/tests/mir-opt/dataflow-const-prop/transmute.invalid_char.DataflowConstProp.64bit.diff
index 837dabde42a..dd737017ffd 100644
--- a/tests/mir-opt/dataflow-const-prop/transmute.invalid_char.DataflowConstProp.64bit.diff
+++ b/tests/mir-opt/dataflow-const-prop/transmute.invalid_char.DataflowConstProp.64bit.diff
@@ -7,7 +7,7 @@
       }
   
       bb0: {
--         _0 = const _ as char (Transmute);
+-         _0 = const core::num::<impl i32>::MAX as char (Transmute);
 +         _0 = const {transmute(0x7fffffff): char};
           return;
       }
diff --git a/tests/mir-opt/derefer_complex_case.main.Derefer.panic-abort.diff b/tests/mir-opt/derefer_complex_case.main.Derefer.panic-abort.diff
index 6654e710625..4ead50e96d8 100644
--- a/tests/mir-opt/derefer_complex_case.main.Derefer.panic-abort.diff
+++ b/tests/mir-opt/derefer_complex_case.main.Derefer.panic-abort.diff
@@ -28,7 +28,7 @@
       bb0: {
           StorageLive(_1);
           StorageLive(_2);
-          _14 = const _;
+          _14 = const main::promoted[0];
           _2 = &(*_14);
           _1 = <&[i32; 2] as IntoIterator>::into_iter(move _2) -> [return: bb1, unwind: bb8];
       }
diff --git a/tests/mir-opt/derefer_complex_case.main.Derefer.panic-unwind.diff b/tests/mir-opt/derefer_complex_case.main.Derefer.panic-unwind.diff
index 18fc27e7cf7..c7cf5f02e0e 100644
--- a/tests/mir-opt/derefer_complex_case.main.Derefer.panic-unwind.diff
+++ b/tests/mir-opt/derefer_complex_case.main.Derefer.panic-unwind.diff
@@ -28,7 +28,7 @@
       bb0: {
           StorageLive(_1);
           StorageLive(_2);
-          _14 = const _;
+          _14 = const main::promoted[0];
           _2 = &(*_14);
           _1 = <&[i32; 2] as IntoIterator>::into_iter(move _2) -> [return: bb1, unwind continue];
       }
diff --git a/tests/mir-opt/gvn.arithmetic.GVN.panic-abort.diff b/tests/mir-opt/gvn.arithmetic.GVN.panic-abort.diff
index 84eb6c5cfe8..cb87d902015 100644
--- a/tests/mir-opt/gvn.arithmetic.GVN.panic-abort.diff
+++ b/tests/mir-opt/gvn.arithmetic.GVN.panic-abort.diff
@@ -336,7 +336,7 @@
           StorageLive(_54);
           StorageLive(_55);
           _55 = _1;
--         _54 = BitAnd(move _55, const _);
+-         _54 = BitAnd(move _55, const core::num::<impl u64>::MAX);
 +         _54 = _1;
           StorageDead(_55);
 -         _53 = opaque::<u64>(move _54) -> [return: bb23, unwind unreachable];
@@ -364,7 +364,7 @@
           StorageLive(_60);
           StorageLive(_61);
           _61 = _1;
--         _60 = BitOr(move _61, const _);
+-         _60 = BitOr(move _61, const core::num::<impl u64>::MAX);
 +         _60 = const u64::MAX;
           StorageDead(_61);
 -         _59 = opaque::<u64>(move _60) -> [return: bb25, unwind unreachable];
diff --git a/tests/mir-opt/gvn.arithmetic.GVN.panic-unwind.diff b/tests/mir-opt/gvn.arithmetic.GVN.panic-unwind.diff
index 98e92d2a310..fa7536efc8e 100644
--- a/tests/mir-opt/gvn.arithmetic.GVN.panic-unwind.diff
+++ b/tests/mir-opt/gvn.arithmetic.GVN.panic-unwind.diff
@@ -336,7 +336,7 @@
           StorageLive(_54);
           StorageLive(_55);
           _55 = _1;
--         _54 = BitAnd(move _55, const _);
+-         _54 = BitAnd(move _55, const core::num::<impl u64>::MAX);
 +         _54 = _1;
           StorageDead(_55);
 -         _53 = opaque::<u64>(move _54) -> [return: bb23, unwind continue];
@@ -364,7 +364,7 @@
           StorageLive(_60);
           StorageLive(_61);
           _61 = _1;
--         _60 = BitOr(move _61, const _);
+-         _60 = BitOr(move _61, const core::num::<impl u64>::MAX);
 +         _60 = const u64::MAX;
           StorageDead(_61);
 -         _59 = opaque::<u64>(move _60) -> [return: bb25, unwind continue];
diff --git a/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-abort.diff b/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-abort.diff
index 4b1e3379114..c417c51f9b7 100644
--- a/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-abort.diff
+++ b/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-abort.diff
@@ -26,7 +26,7 @@
   
       bb0: {
 -         StorageLive(_2);
--         _2 = const _ as usize (IntToInt);
+-         _2 = const core::num::<impl u64>::MAX as usize (IntToInt);
 +         nop;
 +         _2 = const usize::MAX;
           StorageLive(_3);
diff --git a/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-unwind.diff b/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-unwind.diff
index 8abcd7e9387..7a23fbe7cc0 100644
--- a/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-unwind.diff
+++ b/tests/mir-opt/gvn.constant_index_overflow.GVN.panic-unwind.diff
@@ -26,7 +26,7 @@
   
       bb0: {
 -         StorageLive(_2);
--         _2 = const _ as usize (IntToInt);
+-         _2 = const core::num::<impl u64>::MAX as usize (IntToInt);
 +         nop;
 +         _2 = const usize::MAX;
           StorageLive(_3);
diff --git a/tests/mir-opt/gvn.wide_ptr_provenance.GVN.panic-abort.diff b/tests/mir-opt/gvn.wide_ptr_provenance.GVN.panic-abort.diff
index efb3dbec6f2..629c2225682 100644
--- a/tests/mir-opt/gvn.wide_ptr_provenance.GVN.panic-abort.diff
+++ b/tests/mir-opt/gvn.wide_ptr_provenance.GVN.panic-abort.diff
@@ -61,7 +61,7 @@
           StorageLive(_3);
           StorageLive(_4);
           StorageLive(_5);
-          _44 = const _;
+          _44 = const wide_ptr_provenance::promoted[1];
           _5 = &(*_44);
           _4 = &(*_5);
           _3 = move _4 as &dyn std::marker::Send (PointerCoercion(Unsize));
@@ -79,7 +79,7 @@
           StorageLive(_9);
           StorageLive(_10);
           StorageLive(_11);
-          _43 = const _;
+          _43 = const wide_ptr_provenance::promoted[0];
           _11 = &(*_43);
           _10 = &(*_11);
           _9 = move _10 as &dyn std::marker::Send (PointerCoercion(Unsize));
diff --git a/tests/mir-opt/gvn.wide_ptr_provenance.GVN.panic-unwind.diff b/tests/mir-opt/gvn.wide_ptr_provenance.GVN.panic-unwind.diff
index ce8415e75ea..3380bc84cb8 100644
--- a/tests/mir-opt/gvn.wide_ptr_provenance.GVN.panic-unwind.diff
+++ b/tests/mir-opt/gvn.wide_ptr_provenance.GVN.panic-unwind.diff
@@ -61,7 +61,7 @@
           StorageLive(_3);
           StorageLive(_4);
           StorageLive(_5);
-          _44 = const _;
+          _44 = const wide_ptr_provenance::promoted[1];
           _5 = &(*_44);
           _4 = &(*_5);
           _3 = move _4 as &dyn std::marker::Send (PointerCoercion(Unsize));
@@ -79,7 +79,7 @@
           StorageLive(_9);
           StorageLive(_10);
           StorageLive(_11);
-          _43 = const _;
+          _43 = const wide_ptr_provenance::promoted[0];
           _11 = &(*_43);
           _10 = &(*_11);
           _9 = move _10 as &dyn std::marker::Send (PointerCoercion(Unsize));
diff --git a/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-abort.diff b/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-abort.diff
index ef211ce3da2..da1662615d2 100644
--- a/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-abort.diff
+++ b/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-abort.diff
@@ -64,7 +64,7 @@
   
       bb0: {
           StorageLive(_1);
-          _49 = const _;
+          _49 = const wide_ptr_same_provenance::promoted[0];
           _1 = &(*_49);
           StorageLive(_3);
 -         StorageLive(_4);
diff --git a/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-unwind.diff b/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-unwind.diff
index 31f7371ac33..6c4f3a91264 100644
--- a/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-unwind.diff
+++ b/tests/mir-opt/gvn.wide_ptr_same_provenance.GVN.panic-unwind.diff
@@ -64,7 +64,7 @@
   
       bb0: {
           StorageLive(_1);
-          _49 = const _;
+          _49 = const wide_ptr_same_provenance::promoted[0];
           _1 = &(*_49);
           StorageLive(_3);
 -         StorageLive(_4);
diff --git a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff
index 0b6819ad483..86e6aae1191 100644
--- a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff
+++ b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-abort.diff
@@ -17,7 +17,7 @@
       bb0: {
           StorageLive(_2);
           StorageLive(_3);
-          _5 = const _;
+          _5 = const f::promoted[0];
           _3 = &(*_5);
           _2 = ((*_3).1: E);
           StorageLive(_1);
diff --git a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff
index 0b6819ad483..86e6aae1191 100644
--- a/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff
+++ b/tests/mir-opt/gvn_uninhabited.f.GVN.panic-unwind.diff
@@ -17,7 +17,7 @@
       bb0: {
           StorageLive(_2);
           StorageLive(_3);
-          _5 = const _;
+          _5 = const f::promoted[0];
           _3 = &(*_5);
           _2 = ((*_3).1: E);
           StorageLive(_1);
diff --git a/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir b/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir
index 8c3f3a4589e..dcce4aad444 100644
--- a/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir
+++ b/tests/mir-opt/inline/inline_retag.bar.Inline.after.mir
@@ -29,13 +29,13 @@ fn bar() -> bool {
         _2 = _1;
         StorageLive(_3);
         StorageLive(_4);
-        _10 = const _;
+        _10 = const bar::promoted[1];
         Retag(_10);
         _4 = &(*_10);
         _3 = &(*_4);
         StorageLive(_6);
         StorageLive(_7);
-        _9 = const _;
+        _9 = const bar::promoted[0];
         Retag(_9);
         _7 = &(*_9);
         _6 = &(*_7);
diff --git a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff
index 688ab9c563a..24e5587f963 100644
--- a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-abort.diff
@@ -8,7 +8,7 @@
 +         let mut _2: bool;
 +         let mut _3: bool;
 +         scope 2 {
-+             debug buffer => const _;
++             debug buffer => const inner::promoted[0];
 +             scope 3 {
 +                 debug index => _0;
 +             }
@@ -19,7 +19,7 @@
 -         _0 = inner() -> [return: bb1, unwind unreachable];
 +         StorageLive(_1);
 +         StorageLive(_2);
-+         _1 = const _;
++         _1 = const inner::promoted[0];
 +         _0 = index() -> [return: bb1, unwind unreachable];
       }
   
diff --git a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff
index e4d2b1a7ffb..4eb8a5c9847 100644
--- a/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/issue_106141.outer.Inline.panic-unwind.diff
@@ -8,7 +8,7 @@
 +         let mut _2: bool;
 +         let mut _3: bool;
 +         scope 2 {
-+             debug buffer => const _;
++             debug buffer => const inner::promoted[0];
 +             scope 3 {
 +                 debug index => _0;
 +             }
@@ -19,7 +19,7 @@
 -         _0 = inner() -> [return: bb1, unwind continue];
 +         StorageLive(_1);
 +         StorageLive(_2);
-+         _1 = const _;
++         _1 = const inner::promoted[0];
 +         _0 = index() -> [return: bb1, unwind continue];
       }
   
diff --git a/tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify.diff b/tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify.diff
index be7f9cd4412..17730e66291 100644
--- a/tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify.diff
+++ b/tests/mir-opt/instsimplify/combine_transmutes.adt_transmutes.InstSimplify.diff
@@ -37,7 +37,7 @@
       bb0: {
           StorageLive(_1);
           StorageLive(_2);
-          _2 = Option::<NonZero<u8>>::Some(const _);
+          _2 = Option::<NonZero<u8>>::Some(const std::num::NonZero::<u8>::MAX);
           _1 = move _2 as u8 (Transmute);
           StorageDead(_2);
           StorageLive(_3);
diff --git a/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-abort.diff
index 66aa892c6f3..e955e669014 100644
--- a/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-abort.diff
+++ b/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-abort.diff
@@ -16,7 +16,7 @@
   
       bb0: {
           StorageLive(_4);
-          _4 = const _;
+          _4 = const aggregate::FOO;
           StorageLive(_2);
           _2 = (_4.0: u8);
           StorageLive(_3);
diff --git a/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-unwind.diff
index 66aa892c6f3..e955e669014 100644
--- a/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-unwind.diff
+++ b/tests/mir-opt/jump_threading.aggregate.JumpThreading.panic-unwind.diff
@@ -16,7 +16,7 @@
   
       bb0: {
           StorageLive(_4);
-          _4 = const _;
+          _4 = const aggregate::FOO;
           StorageLive(_2);
           _2 = (_4.0: u8);
           StorageLive(_3);
diff --git a/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.panic-abort.diff b/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.panic-abort.diff
index 4b5275f0f6f..564f07ff26d 100644
--- a/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.panic-abort.diff
+++ b/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.panic-abort.diff
@@ -41,7 +41,7 @@
           StorageLive(_5);
           StorageLive(_6);
           StorageLive(_7);
-          _19 = const _;
+          _19 = const discriminant::<T>::promoted[2];
           _7 = &(*_19);
           _6 = &(*_7);
 -         _5 = discriminant_value::<i32>(move _6) -> [return: bb2, unwind unreachable];
@@ -56,7 +56,7 @@
           StorageLive(_9);
           StorageLive(_10);
           StorageLive(_11);
-          _18 = const _;
+          _18 = const discriminant::<T>::promoted[1];
           _11 = &(*_18);
           _10 = &(*_11);
 -         _9 = discriminant_value::<()>(move _10) -> [return: bb3, unwind unreachable];
@@ -71,7 +71,7 @@
           StorageLive(_13);
           StorageLive(_14);
           StorageLive(_15);
-          _17 = const _;
+          _17 = const discriminant::<T>::promoted[0];
           _15 = &(*_17);
           _14 = &(*_15);
 -         _13 = discriminant_value::<E>(move _14) -> [return: bb4, unwind unreachable];
diff --git a/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.panic-unwind.diff b/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.panic-unwind.diff
index 5848288ecfd..7410af284dc 100644
--- a/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.panic-unwind.diff
+++ b/tests/mir-opt/lower_intrinsics.discriminant.LowerIntrinsics.panic-unwind.diff
@@ -41,7 +41,7 @@
           StorageLive(_5);
           StorageLive(_6);
           StorageLive(_7);
-          _19 = const _;
+          _19 = const discriminant::<T>::promoted[2];
           _7 = &(*_19);
           _6 = &(*_7);
 -         _5 = discriminant_value::<i32>(move _6) -> [return: bb2, unwind unreachable];
@@ -56,7 +56,7 @@
           StorageLive(_9);
           StorageLive(_10);
           StorageLive(_11);
-          _18 = const _;
+          _18 = const discriminant::<T>::promoted[1];
           _11 = &(*_18);
           _10 = &(*_11);
 -         _9 = discriminant_value::<()>(move _10) -> [return: bb3, unwind unreachable];
@@ -71,7 +71,7 @@
           StorageLive(_13);
           StorageLive(_14);
           StorageLive(_15);
-          _17 = const _;
+          _17 = const discriminant::<T>::promoted[0];
           _15 = &(*_17);
           _14 = &(*_15);
 -         _13 = discriminant_value::<E>(move _14) -> [return: bb4, unwind unreachable];
diff --git a/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.mir
index 9c6c30214aa..656934fce42 100644
--- a/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/checked_ops.checked_shl.PreCodegen.after.mir
@@ -40,7 +40,7 @@ fn checked_shl(_1: u32, _2: u32) -> Option<u32> {
         _3 = BitAnd(_2, const 31_u32);
         _4 = ShlUnchecked(_1, _3);
         StorageDead(_3);
-        _5 = Ge(_2, const _);
+        _5 = Ge(_2, const core::num::<impl u32>::BITS);
         StorageLive(_6);
         _6 = unlikely(move _5) -> [return: bb1, unwind unreachable];
     }
diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff
index 84181462f67..2865b829e3e 100644
--- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff
+++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-abort.diff
@@ -81,7 +81,7 @@
           StorageLive(_5);
           StorageLive(_6);
           StorageLive(_7);
-          _9 = const _;
+          _9 = const main::promoted[0];
 -         _7 = _9;
 +         _7 = const {ALLOC1<imm>: &std::alloc::Global};
           StorageLive(_8);
diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff
index 820d02e26cd..603b1405562 100644
--- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff
+++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.32bit.panic-unwind.diff
@@ -85,7 +85,7 @@
           StorageLive(_5);
           StorageLive(_6);
           StorageLive(_7);
-          _9 = const _;
+          _9 = const main::promoted[0];
 -         _7 = _9;
 +         _7 = const {ALLOC1<imm>: &std::alloc::Global};
           StorageLive(_8);
diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff
index f478f7cb903..44964392dd6 100644
--- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff
+++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-abort.diff
@@ -81,7 +81,7 @@
           StorageLive(_5);
           StorageLive(_6);
           StorageLive(_7);
-          _9 = const _;
+          _9 = const main::promoted[0];
 -         _7 = _9;
 +         _7 = const {ALLOC1<imm>: &std::alloc::Global};
           StorageLive(_8);
diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff
index 1fba8b5059a..5fd4af21a11 100644
--- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff
+++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.main.GVN.64bit.panic-unwind.diff
@@ -85,7 +85,7 @@
           StorageLive(_5);
           StorageLive(_6);
           StorageLive(_7);
-          _9 = const _;
+          _9 = const main::promoted[0];
 -         _7 = _9;
 +         _7 = const {ALLOC1<imm>: &std::alloc::Global};
           StorageLive(_8);
diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir
index 1eda1ac1365..f698e15d302 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-abort.mir
@@ -101,7 +101,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
         StorageDead(_5);
         StorageLive(_11);
         StorageLive(_8);
-        _8 = const _;
+        _8 = const <T as std::mem::SizedTypeProperties>::IS_ZST;
         switchInt(move _8) -> [0: bb1, otherwise: bb2];
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
index 3cd79654fac..eae9f5909e6 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.PreCodegen.after.panic-unwind.mir
@@ -101,7 +101,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
         StorageDead(_5);
         StorageLive(_11);
         StorageLive(_8);
-        _8 = const _;
+        _8 = const <T as std::mem::SizedTypeProperties>::IS_ZST;
         switchInt(move _8) -> [0: bb1, otherwise: bb2];
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
index a6995bbcbe3..158ae0de890 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-abort.mir
@@ -91,7 +91,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
         StorageDead(_5);
         StorageLive(_11);
         StorageLive(_8);
-        _8 = const _;
+        _8 = const <T as std::mem::SizedTypeProperties>::IS_ZST;
         switchInt(move _8) -> [0: bb1, otherwise: bb2];
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
index 039b7e1aa47..ac9e31a0da8 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.forward_loop.PreCodegen.after.panic-unwind.mir
@@ -91,7 +91,7 @@ fn forward_loop(_1: &[T], _2: impl Fn(&T)) -> () {
         StorageDead(_5);
         StorageLive(_11);
         StorageLive(_8);
-        _8 = const _;
+        _8 = const <T as std::mem::SizedTypeProperties>::IS_ZST;
         switchInt(move _8) -> [0: bb1, otherwise: bb2];
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
index 2465c2381ad..9550df012f8 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
@@ -103,7 +103,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
         StorageDead(_5);
         StorageLive(_11);
         StorageLive(_8);
-        _8 = const _;
+        _8 = const <T as std::mem::SizedTypeProperties>::IS_ZST;
         switchInt(move _8) -> [0: bb1, otherwise: bb2];
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
index c5219ac3390..d75aabd12fc 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
@@ -103,7 +103,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
         StorageDead(_5);
         StorageLive(_11);
         StorageLive(_8);
-        _8 = const _;
+        _8 = const <T as std::mem::SizedTypeProperties>::IS_ZST;
         switchInt(move _8) -> [0: bb1, otherwise: bb2];
     }
 
diff --git a/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff b/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff
index 84350b0dc51..05ad9dbf3cc 100644
--- a/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff
@@ -59,7 +59,7 @@
           _2 = const 5_u8;
           _1 = &mut _2;
           StorageLive(_3);
-          _28 = const _;
+          _28 = const debuginfo::promoted[2];
           _3 = &((*_28).0: u8);
 -         StorageLive(_5);
 -         _5 = &(*_1);
@@ -76,7 +76,7 @@
   
       bb2: {
           StorageLive(_9);
-          _27 = const _;
+          _27 = const debuginfo::promoted[1];
           _9 = &(((*_27) as Some).0: i32);
 -         _6 = const ();
           StorageDead(_9);
@@ -95,7 +95,7 @@
 -         StorageLive(_11);
 -         StorageLive(_12);
           StorageLive(_13);
-          _26 = const _;
+          _26 = const debuginfo::promoted[0];
           _13 = &(*_26);
           StorageLive(_15);
           _15 = RangeFull;
diff --git a/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-abort.mir b/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-abort.mir
index 9c4d6da296d..0580bf3e2d0 100644
--- a/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-abort.mir
+++ b/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-abort.mir
@@ -109,7 +109,7 @@ fn array_casts() -> () {
         _15 = (*_16);
         _14 = &_15;
         StorageLive(_18);
-        _34 = const _;
+        _34 = const array_casts::promoted[0];
         Retag(_34);
         _18 = &(*_34);
         _13 = (move _14, move _18);
diff --git a/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-unwind.mir b/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-unwind.mir
index ca064ab2b8f..6f3cc9051d3 100644
--- a/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-unwind.mir
+++ b/tests/mir-opt/retag.array_casts.SimplifyCfg-elaborate-drops.after.panic-unwind.mir
@@ -109,7 +109,7 @@ fn array_casts() -> () {
         _15 = (*_16);
         _14 = &_15;
         StorageLive(_18);
-        _34 = const _;
+        _34 = const array_casts::promoted[0];
         Retag(_34);
         _18 = &(*_34);
         _13 = (move _14, move _18);
diff --git a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-abort.mir b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-abort.mir
index ec894fa511a..96a76cc66ab 100644
--- a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-abort.mir
+++ b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-abort.mir
@@ -129,7 +129,7 @@ fn main() -> () {
         _20 = &_21;
         StorageLive(_22);
         StorageLive(_23);
-        _28 = const _;
+        _28 = const main::promoted[0];
         Retag(_28);
         _23 = &(*_28);
         _22 = &(*_23);
diff --git a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir
index d89124f699b..2cedf4c3f5f 100644
--- a/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir
+++ b/tests/mir-opt/retag.main.SimplifyCfg-elaborate-drops.after.panic-unwind.mir
@@ -129,7 +129,7 @@ fn main() -> () {
         _20 = &_21;
         StorageLive(_22);
         StorageLive(_23);
-        _28 = const _;
+        _28 = const main::promoted[0];
         Retag(_28);
         _23 = &(*_28);
         _22 = &(*_23);
diff --git a/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff
index b020d1baafa..0d518f78f6b 100644
--- a/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff
+++ b/tests/mir-opt/sroa/lifetimes.foo.ScalarReplacementOfAggregates.diff
@@ -93,7 +93,7 @@
           StorageLive(_12);
           StorageLive(_13);
           StorageLive(_14);
-          _26 = const _;
+          _26 = const foo::<T>::promoted[0];
           _14 = &(*_26);
           _13 = &(*_14);
           _12 = move _13 as &[&str] (PointerCoercion(Unsize));
diff --git a/tests/mir-opt/sroa/structs.constant.ScalarReplacementOfAggregates.diff b/tests/mir-opt/sroa/structs.constant.ScalarReplacementOfAggregates.diff
index 1330f9b3ac8..5d21e793982 100644
--- a/tests/mir-opt/sroa/structs.constant.ScalarReplacementOfAggregates.diff
+++ b/tests/mir-opt/sroa/structs.constant.ScalarReplacementOfAggregates.diff
@@ -25,7 +25,7 @@
 +         StorageLive(_4);
 +         StorageLive(_5);
 +         nop;
-          _1 = const _;
+          _1 = const constant::U;
 +         _4 = move (_1.0: usize);
 +         _5 = move (_1.1: u8);
           StorageLive(_2);
diff --git a/tests/run-make/min-global-align/min_global_align.rs b/tests/run-make/min-global-align/min_global_align.rs
index 135792e9372..cd1ef8cb351 100644
--- a/tests/run-make/min-global-align/min_global_align.rs
+++ b/tests/run-make/min-global-align/min_global_align.rs
@@ -1,4 +1,4 @@
-#![feature(no_core, lang_items)]
+#![feature(no_core, lang_items, freeze_impls)]
 #![crate_type = "rlib"]
 #![no_core]
 
diff --git a/tests/run-make/wasm-abi/Makefile b/tests/run-make/wasm-abi/Makefile
deleted file mode 100644
index ed95464efef..00000000000
--- a/tests/run-make/wasm-abi/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-include ../tools.mk
-
-# only-wasm32-bare
-
-all:
-	$(RUSTC) foo.rs --target wasm32-unknown-unknown
-	$(NODE) foo.js $(TMPDIR)/foo.wasm
diff --git a/tests/run-make/wasm-abi/foo.js b/tests/run-make/wasm-abi/foo.js
deleted file mode 100644
index 9e9a65401af..00000000000
--- a/tests/run-make/wasm-abi/foo.js
+++ /dev/null
@@ -1,22 +0,0 @@
-const fs = require('fs');
-const process = require('process');
-const assert = require('assert');
-const buffer = fs.readFileSync(process.argv[2]);
-
-const m = new WebAssembly.Module(buffer);
-const i = new WebAssembly.Instance(m, {
-  host: {
-    two_i32: () => [100, 101],
-    two_i64: () => [102n, 103n],
-    two_f32: () => [104, 105],
-    two_f64: () => [106, 107],
-    mishmash: () => [108, 109, 110, 111n, 112, 113],
-  }
-});
-
-assert.deepEqual(i.exports.return_two_i32(), [1, 2])
-assert.deepEqual(i.exports.return_two_i64(), [3, 4])
-assert.deepEqual(i.exports.return_two_f32(), [5, 6])
-assert.deepEqual(i.exports.return_two_f64(), [7, 8])
-assert.deepEqual(i.exports.return_mishmash(), [9, 10, 11, 12, 13, 14])
-i.exports.call_imports();
diff --git a/tests/run-make/wasm-abi/host.wat b/tests/run-make/wasm-abi/host.wat
new file mode 100644
index 00000000000..e87097ac8a1
--- /dev/null
+++ b/tests/run-make/wasm-abi/host.wat
@@ -0,0 +1,22 @@
+(module
+  (func (export "two_i32") (result i32 i32)
+      i32.const 100
+      i32.const 101)
+  (func (export "two_i64") (result i64 i64)
+      i64.const 102
+      i64.const 103)
+  (func (export "two_f32") (result f32 f32)
+      f32.const 104
+      f32.const 105)
+  (func (export "two_f64") (result f64 f64)
+      f64.const 106
+      f64.const 107)
+
+  (func (export "mishmash") (result f64 f32 i32 i64 i32 i32)
+      f64.const 108
+      f32.const 109
+      i32.const 110
+      i64.const 111
+      i32.const 112
+      i32.const 113)
+)
diff --git a/tests/run-make/wasm-abi/rmake.rs b/tests/run-make/wasm-abi/rmake.rs
new file mode 100644
index 00000000000..07b826ae6fe
--- /dev/null
+++ b/tests/run-make/wasm-abi/rmake.rs
@@ -0,0 +1,43 @@
+extern crate run_make_support;
+
+use run_make_support::{out_dir, rustc};
+use std::path::Path;
+use std::process::Command;
+
+fn main() {
+    if std::env::var("TARGET").unwrap() != "wasm32-wasip1" {
+        return;
+    }
+
+    rustc().arg("foo.rs").arg("--target=wasm32-wasip1").run();
+    let file = out_dir().join("foo.wasm");
+
+    let has_wasmtime = match Command::new("wasmtime").arg("--version").output() {
+        Ok(s) => s.status.success(),
+        _ => false,
+    };
+    if !has_wasmtime {
+        println!("skipping test, wasmtime isn't available");
+        return;
+    }
+
+    run(&file, "return_two_i32", "1\n2\n");
+    run(&file, "return_two_i64", "3\n4\n");
+    run(&file, "return_two_f32", "5\n6\n");
+    run(&file, "return_two_f64", "7\n8\n");
+    run(&file, "return_mishmash", "9\n10\n11\n12\n13\n14\n");
+    run(&file, "call_imports", "");
+}
+
+fn run(file: &Path, method: &str, expected_output: &str) {
+    let output = Command::new("wasmtime")
+        .arg("run")
+        .arg("--preload=host=host.wat")
+        .arg("--invoke")
+        .arg(method)
+        .arg(file)
+        .output()
+        .unwrap();
+    assert!(output.status.success());
+    assert_eq!(expected_output, String::from_utf8_lossy(&output.stdout));
+}
diff --git a/tests/run-make/wasm-custom-section/Makefile b/tests/run-make/wasm-custom-section/Makefile
deleted file mode 100644
index 2f7d38c2736..00000000000
--- a/tests/run-make/wasm-custom-section/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-include ../tools.mk
-
-# only-wasm32-bare
-
-all:
-	$(RUSTC) foo.rs --target wasm32-unknown-unknown
-	$(RUSTC) bar.rs -C lto -O --target wasm32-unknown-unknown
-	$(NODE) foo.js $(TMPDIR)/bar.wasm
diff --git a/tests/run-make/wasm-custom-section/foo.js b/tests/run-make/wasm-custom-section/foo.js
deleted file mode 100644
index 57a0f50732d..00000000000
--- a/tests/run-make/wasm-custom-section/foo.js
+++ /dev/null
@@ -1,36 +0,0 @@
-const fs = require('fs');
-const process = require('process');
-const assert = require('assert');
-const buffer = fs.readFileSync(process.argv[2]);
-
-let m = new WebAssembly.Module(buffer);
-let sections = WebAssembly.Module.customSections(m, "baz");
-console.log('section baz', sections);
-assert.strictEqual(sections.length, 1);
-let section = new Uint8Array(sections[0]);
-console.log('contents', section);
-assert.strictEqual(section.length, 2);
-assert.strictEqual(section[0], 7);
-assert.strictEqual(section[1], 8);
-
-sections = WebAssembly.Module.customSections(m, "bar");
-console.log('section bar', sections);
-assert.strictEqual(sections.length, 1, "didn't pick up `bar` section from dependency");
-section = new Uint8Array(sections[0]);
-console.log('contents', section);
-assert.strictEqual(section.length, 2);
-assert.strictEqual(section[0], 3);
-assert.strictEqual(section[1], 4);
-
-sections = WebAssembly.Module.customSections(m, "foo");
-console.log('section foo', sections);
-assert.strictEqual(sections.length, 1, "didn't create `foo` section");
-section = new Uint8Array(sections[0]);
-console.log('contents', section);
-assert.strictEqual(section.length, 4, "didn't concatenate `foo` sections");
-assert.strictEqual(section[0], 5);
-assert.strictEqual(section[1], 6);
-assert.strictEqual(section[2], 1);
-assert.strictEqual(section[3], 2);
-
-process.exit(0);
diff --git a/tests/run-make/wasm-custom-section/rmake.rs b/tests/run-make/wasm-custom-section/rmake.rs
new file mode 100644
index 00000000000..9ad152695ec
--- /dev/null
+++ b/tests/run-make/wasm-custom-section/rmake.rs
@@ -0,0 +1,28 @@
+extern crate run_make_support;
+
+use run_make_support::{out_dir, rustc, wasmparser};
+use std::collections::HashMap;
+
+fn main() {
+    if std::env::var("TARGET").unwrap() != "wasm32-wasip1" {
+        return;
+    }
+
+    rustc().arg("foo.rs").arg("--target=wasm32-wasip1").run();
+    rustc().arg("bar.rs").arg("--target=wasm32-wasip1").arg("-Clto").arg("-O").run();
+
+    let file = std::fs::read(&out_dir().join("bar.wasm")).unwrap();
+
+    let mut custom = HashMap::new();
+    for payload in wasmparser::Parser::new(0).parse_all(&file) {
+        let payload = payload.unwrap();
+        if let wasmparser::Payload::CustomSection(s) = payload {
+            let prev = custom.insert(s.name(), s.data());
+            assert!(prev.is_none());
+        }
+    }
+
+    assert_eq!(custom.remove("foo"), Some(&[5, 6, 1, 2][..]));
+    assert_eq!(custom.remove("bar"), Some(&[3, 4][..]));
+    assert_eq!(custom.remove("baz"), Some(&[7, 8][..]));
+}
diff --git a/tests/run-make/wasm-custom-sections-opt/Makefile b/tests/run-make/wasm-custom-sections-opt/Makefile
deleted file mode 100644
index a0d4378131b..00000000000
--- a/tests/run-make/wasm-custom-sections-opt/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-include ../tools.mk
-
-# only-wasm32-bare
-
-all:
-	$(RUSTC) foo.rs -O --target wasm32-unknown-unknown
-	$(NODE) foo.js $(TMPDIR)/foo.wasm
diff --git a/tests/run-make/wasm-custom-sections-opt/foo.js b/tests/run-make/wasm-custom-sections-opt/foo.js
deleted file mode 100644
index 9663f377ef4..00000000000
--- a/tests/run-make/wasm-custom-sections-opt/foo.js
+++ /dev/null
@@ -1,15 +0,0 @@
-const fs = require('fs');
-const process = require('process');
-const assert = require('assert');
-const buffer = fs.readFileSync(process.argv[2]);
-
-let m = new WebAssembly.Module(buffer);
-
-sections = WebAssembly.Module.customSections(m, "foo");
-console.log('section foo', sections);
-assert.strictEqual(sections.length, 1, "didn't create `foo` section");
-section = new Uint8Array(sections[0]);
-console.log('contents', section);
-assert.strictEqual(section.length, 4, "didn't concatenate `foo` sections");
-
-process.exit(0);
diff --git a/tests/run-make/wasm-custom-sections-opt/rmake.rs b/tests/run-make/wasm-custom-sections-opt/rmake.rs
new file mode 100644
index 00000000000..db31d6b7163
--- /dev/null
+++ b/tests/run-make/wasm-custom-sections-opt/rmake.rs
@@ -0,0 +1,30 @@
+extern crate run_make_support;
+
+use run_make_support::{out_dir, rustc, wasmparser};
+use std::collections::HashMap;
+use std::path::Path;
+
+fn main() {
+    if std::env::var("TARGET").unwrap() != "wasm32-wasip1" {
+        return;
+    }
+
+    rustc().arg("foo.rs").arg("--target=wasm32-wasip1").arg("-O").run();
+    verify(&out_dir().join("foo.wasm"));
+}
+
+fn verify(path: &Path) {
+    eprintln!("verify {path:?}");
+    let file = std::fs::read(&path).unwrap();
+
+    let mut custom = HashMap::new();
+    for payload in wasmparser::Parser::new(0).parse_all(&file) {
+        let payload = payload.unwrap();
+        if let wasmparser::Payload::CustomSection(s) = payload {
+            let prev = custom.insert(s.name(), s.data());
+            assert!(prev.is_none());
+        }
+    }
+
+    assert_eq!(custom.remove("foo"), Some(&[1, 2, 3, 4][..]));
+}
diff --git a/tests/run-make/wasm-export-all-symbols/Makefile b/tests/run-make/wasm-export-all-symbols/Makefile
deleted file mode 100644
index 86713bc80b8..00000000000
--- a/tests/run-make/wasm-export-all-symbols/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-include ../tools.mk
-
-# only-wasm32-bare
-
-all:
-	$(RUSTC) bar.rs --target wasm32-unknown-unknown
-	$(RUSTC) foo.rs --target wasm32-unknown-unknown
-	$(NODE) verify.js $(TMPDIR)/foo.wasm
-	$(RUSTC) main.rs --target wasm32-unknown-unknown
-	$(NODE) verify.js $(TMPDIR)/main.wasm
-	$(RUSTC) bar.rs --target wasm32-unknown-unknown -O
-	$(RUSTC) foo.rs --target wasm32-unknown-unknown -O
-	$(NODE) verify.js $(TMPDIR)/foo.wasm
-	$(RUSTC) main.rs --target wasm32-unknown-unknown -O
-	$(NODE) verify.js $(TMPDIR)/main.wasm
-	$(RUSTC) foo.rs --target wasm32-unknown-unknown -C lto
-	$(NODE) verify.js $(TMPDIR)/foo.wasm
-	$(RUSTC) main.rs --target wasm32-unknown-unknown -C lto
-	$(NODE) verify.js $(TMPDIR)/main.wasm
diff --git a/tests/run-make/wasm-export-all-symbols/rmake.rs b/tests/run-make/wasm-export-all-symbols/rmake.rs
new file mode 100644
index 00000000000..e3b118279b7
--- /dev/null
+++ b/tests/run-make/wasm-export-all-symbols/rmake.rs
@@ -0,0 +1,60 @@
+extern crate run_make_support;
+
+use run_make_support::{out_dir, rustc, wasmparser};
+use std::collections::HashMap;
+use std::path::Path;
+use wasmparser::ExternalKind::*;
+
+fn main() {
+    if std::env::var("TARGET").unwrap() != "wasm32-wasip1" {
+        return;
+    }
+
+    test(&[]);
+    test(&["-O"]);
+    test(&["-Clto"]);
+}
+
+fn test(args: &[&str]) {
+    eprintln!("running with {args:?}");
+    rustc().arg("bar.rs").arg("--target=wasm32-wasip1").args(args).run();
+    rustc().arg("foo.rs").arg("--target=wasm32-wasip1").args(args).run();
+    rustc().arg("main.rs").arg("--target=wasm32-wasip1").args(args).run();
+
+    verify_exports(
+        &out_dir().join("foo.wasm"),
+        &[("foo", Func), ("FOO", Global), ("memory", Memory)],
+    );
+    verify_exports(
+        &out_dir().join("main.wasm"),
+        &[
+            ("foo", Func),
+            ("FOO", Global),
+            ("_start", Func),
+            ("__main_void", Func),
+            ("memory", Memory),
+        ],
+    );
+}
+
+fn verify_exports(path: &Path, exports: &[(&str, wasmparser::ExternalKind)]) {
+    println!("verify {path:?}");
+    let file = std::fs::read(path).unwrap();
+    let mut wasm_exports = HashMap::new();
+    for payload in wasmparser::Parser::new(0).parse_all(&file) {
+        let payload = payload.unwrap();
+        if let wasmparser::Payload::ExportSection(s) = payload {
+            for export in s {
+                let export = export.unwrap();
+                wasm_exports.insert(export.name, export.kind);
+            }
+        }
+    }
+
+    eprintln!("found exports {wasm_exports:?}");
+
+    assert_eq!(exports.len(), wasm_exports.len());
+    for (export, expected_kind) in exports {
+        assert_eq!(wasm_exports[export], *expected_kind);
+    }
+}
diff --git a/tests/run-make/wasm-export-all-symbols/verify.js b/tests/run-make/wasm-export-all-symbols/verify.js
deleted file mode 100644
index 72db3356f56..00000000000
--- a/tests/run-make/wasm-export-all-symbols/verify.js
+++ /dev/null
@@ -1,32 +0,0 @@
-const fs = require('fs');
-const process = require('process');
-const assert = require('assert');
-const buffer = fs.readFileSync(process.argv[2]);
-
-let m = new WebAssembly.Module(buffer);
-let list = WebAssembly.Module.exports(m);
-console.log('exports', list);
-
-const my_exports = {};
-let nexports = 0;
-
-for (const entry of list) {
-  if (entry.kind == 'function'){
-    nexports += 1;
-  }
-  my_exports[entry.name] = entry.kind;
-}
-
-if (my_exports.foo != "function")
-  throw new Error("`foo` wasn't defined");
-
-if (my_exports.FOO != "global")
-  throw new Error("`FOO` wasn't defined");
-
-if (my_exports.main === undefined) {
-  if (nexports != 1)
-    throw new Error("should only have one function export");
-} else {
-  if (nexports != 2)
-    throw new Error("should only have two function exports");
-}
diff --git a/tests/run-make/wasm-import-module/Makefile b/tests/run-make/wasm-import-module/Makefile
deleted file mode 100644
index a0b4d920b3d..00000000000
--- a/tests/run-make/wasm-import-module/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-include ../tools.mk
-
- # only-wasm32-bare
-
-all:
-	$(RUSTC) foo.rs --target wasm32-unknown-unknown
-	$(RUSTC) bar.rs -C lto -O --target wasm32-unknown-unknown
-	$(NODE) foo.js $(TMPDIR)/bar.wasm
diff --git a/tests/run-make/wasm-import-module/foo.js b/tests/run-make/wasm-import-module/foo.js
deleted file mode 100644
index 3ea47fcc930..00000000000
--- a/tests/run-make/wasm-import-module/foo.js
+++ /dev/null
@@ -1,18 +0,0 @@
-const fs = require('fs');
-const process = require('process');
-const assert = require('assert');
-const buffer = fs.readFileSync(process.argv[2]);
-
-let m = new WebAssembly.Module(buffer);
-let imports = WebAssembly.Module.imports(m);
-console.log('imports', imports);
-assert.strictEqual(imports.length, 2);
-
-assert.strictEqual(imports[0].kind, 'function');
-assert.strictEqual(imports[1].kind, 'function');
-
-let modules = [imports[0].module, imports[1].module];
-modules.sort();
-
-assert.strictEqual(modules[0], './dep');
-assert.strictEqual(modules[1], './me');
diff --git a/tests/run-make/wasm-import-module/rmake.rs b/tests/run-make/wasm-import-module/rmake.rs
new file mode 100644
index 00000000000..e521b5b0983
--- /dev/null
+++ b/tests/run-make/wasm-import-module/rmake.rs
@@ -0,0 +1,32 @@
+extern crate run_make_support;
+
+use run_make_support::{out_dir, rustc, wasmparser};
+use std::collections::HashMap;
+use wasmparser::TypeRef::Func;
+
+fn main() {
+    if std::env::var("TARGET").unwrap() != "wasm32-wasip1" {
+        return;
+    }
+
+    rustc().arg("foo.rs").arg("--target=wasm32-wasip1").run();
+    rustc().arg("bar.rs").arg("--target=wasm32-wasip1").arg("-Clto").arg("-O").run();
+
+    let file = std::fs::read(&out_dir().join("bar.wasm")).unwrap();
+
+    let mut imports = HashMap::new();
+    for payload in wasmparser::Parser::new(0).parse_all(&file) {
+        let payload = payload.unwrap();
+        if let wasmparser::Payload::ImportSection(s) = payload {
+            for i in s {
+                let i = i.unwrap();
+                imports.entry(i.module).or_insert(Vec::new()).push((i.name, i.ty));
+            }
+        }
+    }
+
+    let import = imports.remove("./dep");
+    assert!(matches!(import.as_deref(), Some([("dep", Func(_))])), "bad import {:?}", import);
+    let import = imports.remove("./me");
+    assert!(matches!(import.as_deref(), Some([("me_in_dep", Func(_))])), "bad import {:?}", import);
+}
diff --git a/tests/run-make/wasm-panic-small/Makefile b/tests/run-make/wasm-panic-small/Makefile
deleted file mode 100644
index 16f54521855..00000000000
--- a/tests/run-make/wasm-panic-small/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-include ../tools.mk
-
-# only-wasm32-bare
-
-all:
-	$(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown --cfg a
-	wc -c < $(TMPDIR)/foo.wasm
-	[ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "1024" ]
-	$(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown --cfg b
-	wc -c < $(TMPDIR)/foo.wasm
-	[ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "5120" ]
-	$(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown --cfg c
-	wc -c < $(TMPDIR)/foo.wasm
-	[ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "5120" ]
-	$(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown --cfg d
-	wc -c < $(TMPDIR)/foo.wasm
-	[ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "5120" ]
diff --git a/tests/run-make/wasm-panic-small/rmake.rs b/tests/run-make/wasm-panic-small/rmake.rs
new file mode 100644
index 00000000000..0260485f744
--- /dev/null
+++ b/tests/run-make/wasm-panic-small/rmake.rs
@@ -0,0 +1,32 @@
+#![deny(warnings)]
+
+extern crate run_make_support;
+
+use run_make_support::{out_dir, rustc};
+
+fn main() {
+    if std::env::var("TARGET").unwrap() != "wasm32-wasip1" {
+        return;
+    }
+
+    test("a");
+    test("b");
+    test("c");
+    test("d");
+}
+
+fn test(cfg: &str) {
+    eprintln!("running cfg {cfg:?}");
+    rustc()
+        .arg("foo.rs")
+        .arg("--target=wasm32-wasip1")
+        .arg("-Clto")
+        .arg("-O")
+        .arg("--cfg")
+        .arg(cfg)
+        .run();
+
+    let bytes = std::fs::read(&out_dir().join("foo.wasm")).unwrap();
+    println!("{}", bytes.len());
+    assert!(bytes.len() < 40_000);
+}
diff --git a/tests/run-make/wasm-spurious-import/Makefile b/tests/run-make/wasm-spurious-import/Makefile
deleted file mode 100644
index ff9dfeac6d0..00000000000
--- a/tests/run-make/wasm-spurious-import/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-include ../tools.mk
-
-# only-wasm32-bare
-
-all:
-	$(RUSTC) main.rs -C overflow-checks=yes -C panic=abort -C lto -C opt-level=z --target wasm32-unknown-unknown
-	$(NODE) verify.js $(TMPDIR)/main.wasm
diff --git a/tests/run-make/wasm-spurious-import/rmake.rs b/tests/run-make/wasm-spurious-import/rmake.rs
new file mode 100644
index 00000000000..0ac9104bfb4
--- /dev/null
+++ b/tests/run-make/wasm-spurious-import/rmake.rs
@@ -0,0 +1,35 @@
+extern crate run_make_support;
+
+use run_make_support::{out_dir, rustc, wasmparser};
+use std::collections::HashMap;
+use wasmparser::TypeRef::Func;
+
+fn main() {
+    if std::env::var("TARGET").unwrap() != "wasm32-wasip1" {
+        return;
+    }
+
+    rustc()
+        .arg("main.rs")
+        .arg("--target=wasm32-wasip1")
+        .arg("-Coverflow-checks=yes")
+        .arg("-Cpanic=abort")
+        .arg("-Clto")
+        .arg("-Copt-level=z")
+        .run();
+
+    let file = std::fs::read(&out_dir().join("main.wasm")).unwrap();
+
+    let mut imports = HashMap::new();
+    for payload in wasmparser::Parser::new(0).parse_all(&file) {
+        let payload = payload.unwrap();
+        if let wasmparser::Payload::ImportSection(s) = payload {
+            for i in s {
+                let i = i.unwrap();
+                imports.entry(i.module).or_insert(Vec::new()).push((i.name, i.ty));
+            }
+        }
+    }
+
+    assert!(imports.is_empty(), "imports are not empty {:?}", imports);
+}
diff --git a/tests/run-make/wasm-spurious-import/verify.js b/tests/run-make/wasm-spurious-import/verify.js
deleted file mode 100644
index d3b2101b662..00000000000
--- a/tests/run-make/wasm-spurious-import/verify.js
+++ /dev/null
@@ -1,9 +0,0 @@
-const fs = require('fs');
-const process = require('process');
-const assert = require('assert');
-const buffer = fs.readFileSync(process.argv[2]);
-
-let m = new WebAssembly.Module(buffer);
-let imports = WebAssembly.Module.imports(m);
-console.log('imports', imports);
-assert.strictEqual(imports.length, 0);
diff --git a/tests/run-make/wasm-stringify-ints-small/Makefile b/tests/run-make/wasm-stringify-ints-small/Makefile
deleted file mode 100644
index f959dbd426b..00000000000
--- a/tests/run-make/wasm-stringify-ints-small/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-include ../tools.mk
-
-ifeq ($(TARGET),wasm32-unknown-unknown)
-all:
-	$(RUSTC) foo.rs -C lto -O --target wasm32-unknown-unknown
-	wc -c < $(TMPDIR)/foo.wasm
-	[ "`wc -c < $(TMPDIR)/foo.wasm`" -lt "25000" ]
-else
-all:
-endif
diff --git a/tests/run-make/wasm-stringify-ints-small/rmake.rs b/tests/run-make/wasm-stringify-ints-small/rmake.rs
new file mode 100644
index 00000000000..80cff7acdf4
--- /dev/null
+++ b/tests/run-make/wasm-stringify-ints-small/rmake.rs
@@ -0,0 +1,17 @@
+#![deny(warnings)]
+
+extern crate run_make_support;
+
+use run_make_support::{out_dir, rustc};
+
+fn main() {
+    if std::env::var("TARGET").unwrap() != "wasm32-wasip1" {
+        return;
+    }
+
+    rustc().arg("foo.rs").arg("--target=wasm32-wasip1").arg("-Clto").arg("-O").run();
+
+    let bytes = std::fs::read(&out_dir().join("foo.wasm")).unwrap();
+    println!("{}", bytes.len());
+    assert!(bytes.len() < 50_000);
+}
diff --git a/tests/run-make/wasm-symbols-different-module/Makefile b/tests/run-make/wasm-symbols-different-module/Makefile
deleted file mode 100644
index 0f86914c7b1..00000000000
--- a/tests/run-make/wasm-symbols-different-module/Makefile
+++ /dev/null
@@ -1,28 +0,0 @@
-include ../tools.mk
-
-# only-wasm32-bare
-
-all:
-	$(RUSTC) foo.rs --target wasm32-unknown-unknown
-	$(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo
-	$(RUSTC) foo.rs --target wasm32-unknown-unknown -C lto
-	$(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo
-	$(RUSTC) foo.rs --target wasm32-unknown-unknown -O
-	$(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo
-	$(RUSTC) foo.rs --target wasm32-unknown-unknown -O -C lto
-	$(NODE) verify-imports.js $(TMPDIR)/foo.wasm a/foo b/foo
-
-	$(RUSTC) bar.rs --target wasm32-unknown-unknown
-	$(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f
-	$(RUSTC) bar.rs --target wasm32-unknown-unknown -C lto
-	$(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f
-	$(RUSTC) bar.rs --target wasm32-unknown-unknown -O
-	$(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f
-	$(RUSTC) bar.rs --target wasm32-unknown-unknown -O -C lto
-	$(NODE) verify-imports.js $(TMPDIR)/bar.wasm m1/f m1/g m2/f
-
-	$(RUSTC) baz.rs --target wasm32-unknown-unknown
-	$(NODE) verify-imports.js $(TMPDIR)/baz.wasm sqlite/allocate sqlite/deallocate
-
-	$(RUSTC) log.rs --target wasm32-unknown-unknown
-	$(NODE) verify-imports.js $(TMPDIR)/log.wasm test/log
diff --git a/tests/run-make/wasm-symbols-different-module/rmake.rs b/tests/run-make/wasm-symbols-different-module/rmake.rs
new file mode 100644
index 00000000000..c3cc1e0c32b
--- /dev/null
+++ b/tests/run-make/wasm-symbols-different-module/rmake.rs
@@ -0,0 +1,52 @@
+extern crate run_make_support;
+
+use run_make_support::{out_dir, rustc, wasmparser};
+use std::collections::{HashMap, HashSet};
+
+fn main() {
+    if std::env::var("TARGET").unwrap() != "wasm32-wasip1" {
+        return;
+    }
+
+    test_file("foo.rs", &[("a", &["foo"]), ("b", &["foo"])]);
+    test_file("bar.rs", &[("m1", &["f", "g"]), ("m2", &["f"])]);
+    test_file("baz.rs", &[("sqlite", &["allocate", "deallocate"])]);
+    test_file("log.rs", &[("test", &["log"])]);
+}
+
+fn test_file(file: &str, expected_imports: &[(&str, &[&str])]) {
+    test(file, &[], expected_imports);
+    test(file, &["-Clto"], expected_imports);
+    test(file, &["-O"], expected_imports);
+    test(file, &["-Clto", "-O"], expected_imports);
+}
+
+fn test(file: &str, args: &[&str], expected_imports: &[(&str, &[&str])]) {
+    println!("test {file:?} {args:?} for {expected_imports:?}");
+
+    rustc().arg(file).arg("--target=wasm32-wasip1").args(args).run();
+
+    let file = std::fs::read(&out_dir().join(file).with_extension("wasm")).unwrap();
+
+    let mut imports = HashMap::new();
+    for payload in wasmparser::Parser::new(0).parse_all(&file) {
+        let payload = payload.unwrap();
+        if let wasmparser::Payload::ImportSection(s) = payload {
+            for i in s {
+                let i = i.unwrap();
+                imports.entry(i.module).or_insert(HashSet::new()).insert(i.name);
+            }
+        }
+    }
+
+    eprintln!("imports {imports:?}");
+
+    for (expected_module, expected_names) in expected_imports {
+        let names = imports.remove(expected_module).unwrap();
+        assert_eq!(names.len(), expected_names.len());
+        for name in *expected_names {
+            assert!(names.contains(name));
+        }
+    }
+    assert!(imports.is_empty());
+}
diff --git a/tests/run-make/wasm-symbols-different-module/verify-imports.js b/tests/run-make/wasm-symbols-different-module/verify-imports.js
deleted file mode 100644
index 7e9f90cf8bd..00000000000
--- a/tests/run-make/wasm-symbols-different-module/verify-imports.js
+++ /dev/null
@@ -1,32 +0,0 @@
-const fs = require('fs');
-const process = require('process');
-const assert = require('assert');
-const buffer = fs.readFileSync(process.argv[2]);
-
-let m = new WebAssembly.Module(buffer);
-let list = WebAssembly.Module.imports(m);
-console.log('imports', list);
-if (list.length !== process.argv.length - 3)
-  throw new Error("wrong number of imports")
-
-const imports = new Map();
-for (let i = 3; i < process.argv.length; i++) {
-  const [module, name] = process.argv[i].split('/');
-  if (!imports.has(module))
-    imports.set(module, new Map());
-  imports.get(module).set(name, true);
-}
-
-for (let i of list) {
-  if (imports.get(i.module) === undefined || imports.get(i.module).get(i.name) === undefined)
-    throw new Error(`didn't find import of ${i.module}::${i.name}`);
-  imports.get(i.module).delete(i.name);
-
-  if (imports.get(i.module).size === 0)
-    imports.delete(i.module);
-}
-
-console.log(imports);
-if (imports.size !== 0) {
-  throw new Error('extra imports');
-}
diff --git a/tests/run-make/wasm-symbols-not-exported/Makefile b/tests/run-make/wasm-symbols-not-exported/Makefile
deleted file mode 100644
index 024ad779748..00000000000
--- a/tests/run-make/wasm-symbols-not-exported/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-include ../tools.mk
-
-# only-wasm32-bare
-
-all:
-	$(RUSTC) foo.rs --target wasm32-unknown-unknown
-	$(NODE) verify-exported-symbols.js $(TMPDIR)/foo.wasm
-	$(RUSTC) foo.rs --target wasm32-unknown-unknown -O
-	$(NODE) verify-exported-symbols.js $(TMPDIR)/foo.wasm
-	$(RUSTC) bar.rs --target wasm32-unknown-unknown
-	$(NODE) verify-exported-symbols.js $(TMPDIR)/bar.wasm
-	$(RUSTC) bar.rs --target wasm32-unknown-unknown -O
-	$(NODE) verify-exported-symbols.js $(TMPDIR)/bar.wasm
diff --git a/tests/run-make/wasm-symbols-not-exported/rmake.rs b/tests/run-make/wasm-symbols-not-exported/rmake.rs
new file mode 100644
index 00000000000..5ff0dc578b3
--- /dev/null
+++ b/tests/run-make/wasm-symbols-not-exported/rmake.rs
@@ -0,0 +1,41 @@
+extern crate run_make_support;
+
+use run_make_support::{out_dir, rustc, wasmparser};
+use std::path::Path;
+
+fn main() {
+    if std::env::var("TARGET").unwrap() != "wasm32-wasip1" {
+        return;
+    }
+
+    rustc().arg("foo.rs").arg("--target=wasm32-wasip1").run();
+    verify_symbols(&out_dir().join("foo.wasm"));
+    rustc().arg("foo.rs").arg("--target=wasm32-wasip1").arg("-O").run();
+    verify_symbols(&out_dir().join("foo.wasm"));
+
+    rustc().arg("bar.rs").arg("--target=wasm32-wasip1").run();
+    verify_symbols(&out_dir().join("bar.wasm"));
+    rustc().arg("bar.rs").arg("--target=wasm32-wasip1").arg("-O").run();
+    verify_symbols(&out_dir().join("bar.wasm"));
+}
+
+fn verify_symbols(path: &Path) {
+    eprintln!("verify {path:?}");
+    let file = std::fs::read(&path).unwrap();
+
+    for payload in wasmparser::Parser::new(0).parse_all(&file) {
+        let payload = payload.unwrap();
+        if let wasmparser::Payload::ExportSection(s) = payload {
+            for e in s {
+                let e = e.unwrap();
+                if e.kind != wasmparser::ExternalKind::Func {
+                    continue;
+                }
+                if e.name == "foo" {
+                    continue;
+                }
+                panic!("unexpected export {e:?}");
+            }
+        }
+    }
+}
diff --git a/tests/run-make/wasm-symbols-not-exported/verify-exported-symbols.js b/tests/run-make/wasm-symbols-not-exported/verify-exported-symbols.js
deleted file mode 100644
index afc8a7241f5..00000000000
--- a/tests/run-make/wasm-symbols-not-exported/verify-exported-symbols.js
+++ /dev/null
@@ -1,21 +0,0 @@
-const fs = require('fs');
-const process = require('process');
-const assert = require('assert');
-const buffer = fs.readFileSync(process.argv[2]);
-
-let m = new WebAssembly.Module(buffer);
-let list = WebAssembly.Module.exports(m);
-console.log('exports', list);
-
-let bad = false;
-for (let i = 0; i < list.length; i++) {
-  const e = list[i];
-  if (e.name == "foo" || e.kind != "function")
-    continue;
-
-  console.log('unexpected exported symbol:', e.name);
-  bad = true;
-}
-
-if (bad)
-  process.exit(1);
diff --git a/tests/run-make/wasm-symbols-not-imported/Makefile b/tests/run-make/wasm-symbols-not-imported/Makefile
deleted file mode 100644
index 38440a8b025..00000000000
--- a/tests/run-make/wasm-symbols-not-imported/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-include ../tools.mk
-
-# only-wasm32-bare
-
-all:
-	$(RUSTC) foo.rs --target wasm32-unknown-unknown
-	$(NODE) verify-no-imports.js $(TMPDIR)/foo.wasm
-	$(RUSTC) foo.rs --target wasm32-unknown-unknown -C lto
-	$(NODE) verify-no-imports.js $(TMPDIR)/foo.wasm
-	$(RUSTC) foo.rs --target wasm32-unknown-unknown -O
-	$(NODE) verify-no-imports.js $(TMPDIR)/foo.wasm
-	$(RUSTC) foo.rs --target wasm32-unknown-unknown -O -C lto
-	$(NODE) verify-no-imports.js $(TMPDIR)/foo.wasm
diff --git a/tests/run-make/wasm-symbols-not-imported/rmake.rs b/tests/run-make/wasm-symbols-not-imported/rmake.rs
new file mode 100644
index 00000000000..974f415166b
--- /dev/null
+++ b/tests/run-make/wasm-symbols-not-imported/rmake.rs
@@ -0,0 +1,31 @@
+extern crate run_make_support;
+
+use run_make_support::{out_dir, rustc, wasmparser};
+use std::path::Path;
+
+fn main() {
+    if std::env::var("TARGET").unwrap() != "wasm32-wasip1" {
+        return;
+    }
+
+    rustc().arg("foo.rs").arg("--target=wasm32-wasip1").run();
+    verify_symbols(&out_dir().join("foo.wasm"));
+    rustc().arg("foo.rs").arg("--target=wasm32-wasip1").arg("-Clto").run();
+    verify_symbols(&out_dir().join("foo.wasm"));
+    rustc().arg("foo.rs").arg("--target=wasm32-wasip1").arg("-O").run();
+    verify_symbols(&out_dir().join("foo.wasm"));
+    rustc().arg("foo.rs").arg("--target=wasm32-wasip1").arg("-Clto").arg("-O").run();
+    verify_symbols(&out_dir().join("foo.wasm"));
+}
+
+fn verify_symbols(path: &Path) {
+    eprintln!("verify {path:?}");
+    let file = std::fs::read(&path).unwrap();
+
+    for payload in wasmparser::Parser::new(0).parse_all(&file) {
+        let payload = payload.unwrap();
+        if let wasmparser::Payload::ImportSection(_) = payload {
+            panic!("import section found");
+        }
+    }
+}
diff --git a/tests/run-make/wasm-symbols-not-imported/verify-no-imports.js b/tests/run-make/wasm-symbols-not-imported/verify-no-imports.js
deleted file mode 100644
index 90e3df1d98d..00000000000
--- a/tests/run-make/wasm-symbols-not-imported/verify-no-imports.js
+++ /dev/null
@@ -1,10 +0,0 @@
-const fs = require('fs');
-const process = require('process');
-const assert = require('assert');
-const buffer = fs.readFileSync(process.argv[2]);
-
-let m = new WebAssembly.Module(buffer);
-let list = WebAssembly.Module.imports(m);
-console.log('imports', list);
-if (list.length !== 0)
-  throw new Error("there are some imports");
diff --git a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh
index a36ad916beb..a7c4ae13ecb 100644
--- a/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh
+++ b/tests/run-make/x86_64-fortanix-unknown-sgx-lvi/script.sh
@@ -1,20 +1,20 @@
-#!/bin/sh
+#!/bin/bash
 set -exuo pipefail
 
 function build {
     CRATE=enclave
 
-    mkdir -p $WORK_DIR
-    pushd $WORK_DIR
-        rm -rf $CRATE
-        cp -a $TEST_DIR/enclave .
+    mkdir -p "${WORK_DIR}"
+    pushd "${WORK_DIR}"
+        rm -rf "${CRATE}"
+        cp -a "${TEST_DIR}"/enclave .
         pushd $CRATE
-            echo ${WORK_DIR}
+            echo "${WORK_DIR}"
             # HACK(eddyb) sets `RUSTC_BOOTSTRAP=1` so Cargo can accept nightly features.
             # These come from the top-level Rust workspace, that this crate is not a
             # member of, but Cargo tries to load the workspace `Cargo.toml` anyway.
             env RUSTC_BOOTSTRAP=1
-                cargo -v run --target $TARGET
+                cargo -v run --target "${TARGET}"
         popd
     popd
 }
@@ -22,17 +22,18 @@ function build {
 function check {
     local func_re="$1"
     local checks="${TEST_DIR}/$2"
-    local asm=$(mktemp)
+    local asm=""
     local objdump="${LLVM_BIN_DIR}/llvm-objdump"
     local filecheck="${LLVM_BIN_DIR}/FileCheck"
     local enclave=${WORK_DIR}/enclave/target/x86_64-fortanix-unknown-sgx/debug/enclave
 
-    func="$(${objdump} --syms --demangle ${enclave} | \
+    asm=$(mktemp)
+    func="$(${objdump} --syms --demangle "${enclave}" | \
             grep --only-matching -E "[[:blank:]]+${func_re}\$" | \
             sed -e 's/^[[:space:]]*//' )"
     ${objdump} --disassemble-symbols="${func}" --demangle \
-      ${enclave} > ${asm}
-    ${filecheck} --input-file ${asm} ${checks}
+      "${enclave}" > "${asm}"
+    ${filecheck} --input-file "${asm}" "${checks}"
 
     if [ "${func_re}" != "rust_plus_one_global_asm" ] &&
          [ "${func_re}" != "cmake_plus_one_c_global_asm" ] &&
@@ -41,7 +42,7 @@ function check {
         # of `shlq $0x0, (%rsp); lfence; retq` are used instead.
         # https://www.intel.com/content/www/us/en/developer/articles/technical/
         #     software-security-guidance/technical-documentation/load-value-injection.html
-        ${filecheck} --implicit-check-not ret --input-file ${asm} ${checks}
+        ${filecheck} --implicit-check-not ret --input-file "${asm}" "${checks}"
     fi
 }
 
diff --git a/tests/run-pass-valgrind/exit-flushes.rs b/tests/run-pass-valgrind/exit-flushes.rs
index c54f9243950..fa9196a3eec 100644
--- a/tests/run-pass-valgrind/exit-flushes.rs
+++ b/tests/run-pass-valgrind/exit-flushes.rs
@@ -1,4 +1,4 @@
-//@ ignore-emscripten
+//@ ignore-wasm32 no subprocess support
 //@ ignore-sgx no processes
 //@ ignore-macos this needs valgrind 3.11 or higher; see
 // https://github.com/rust-lang/rust/pull/30365#issuecomment-165763679
diff --git a/tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs b/tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs
index 0663ed5fc81..7d9133b85a6 100644
--- a/tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs
+++ b/tests/rustdoc/auto-trait-bounds-by-associated-type-50159.rs
@@ -1,5 +1,5 @@
 // https://github.com/rust-lang/rust/issues/50159
-#![crate_name="foo"]
+#![crate_name = "foo"]
 
 pub trait Signal {
     type Item;
@@ -9,7 +9,10 @@ pub trait Signal2 {
     type Item2;
 }
 
-impl<B, C> Signal2 for B where B: Signal<Item = C> {
+impl<B, C> Signal2 for B
+where
+    B: Signal<Item = C>,
+{
     type Item2 = C;
 }
 
@@ -17,7 +20,7 @@ impl<B, C> Signal2 for B where B: Signal<Item = C> {
 // @has - '//h3[@class="code-header"]' 'impl<B> Send for Switch<B>where <B as Signal>::Item: Send'
 // @has - '//h3[@class="code-header"]' 'impl<B> Sync for Switch<B>where <B as Signal>::Item: Sync'
 // @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0
-// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 5
+// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 6
 pub struct Switch<B: Signal> {
     pub inner: <B as Signal2>::Item2,
 }
diff --git a/tests/rustdoc/empty-section.rs b/tests/rustdoc/empty-section.rs
index d8241ab96f6..0d6afb0e444 100644
--- a/tests/rustdoc/empty-section.rs
+++ b/tests/rustdoc/empty-section.rs
@@ -1,6 +1,5 @@
 #![crate_name = "foo"]
-
-#![feature(negative_impls)]
+#![feature(negative_impls, freeze_impls, freeze)]
 
 pub struct Foo;
 
@@ -8,6 +7,7 @@ pub struct Foo;
 // @!hasraw - 'Auto Trait Implementations'
 impl !Send for Foo {}
 impl !Sync for Foo {}
+impl !std::marker::Freeze for Foo {}
 impl !std::marker::Unpin for Foo {}
 impl !std::panic::RefUnwindSafe for Foo {}
 impl !std::panic::UnwindSafe for Foo {}
diff --git a/tests/rustdoc/synthetic_auto/basic.rs b/tests/rustdoc/synthetic_auto/basic.rs
index 043ac241488..16b8cce490c 100644
--- a/tests/rustdoc/synthetic_auto/basic.rs
+++ b/tests/rustdoc/synthetic_auto/basic.rs
@@ -2,7 +2,7 @@
 // @has - '//h3[@class="code-header"]' 'impl<T> Send for Foo<T>where T: Send'
 // @has - '//h3[@class="code-header"]' 'impl<T> Sync for Foo<T>where T: Sync'
 // @count - '//*[@id="implementations-list"]//*[@class="impl"]' 0
-// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 5
+// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 6
 pub struct Foo<T> {
     field: T,
 }
diff --git a/tests/rustdoc/synthetic_auto/manual.rs b/tests/rustdoc/synthetic_auto/manual.rs
index 7fc8447df3e..692d68294a7 100644
--- a/tests/rustdoc/synthetic_auto/manual.rs
+++ b/tests/rustdoc/synthetic_auto/manual.rs
@@ -6,7 +6,7 @@
 // 'impl<T> Send for Foo<T>'
 //
 // @count - '//*[@id="trait-implementations-list"]//*[@class="impl"]' 1
-// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 4
+// @count - '//*[@id="synthetic-implementations-list"]//*[@class="impl"]' 5
 pub struct Foo<T> {
     field: T,
 }
diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.rs b/tests/ui-fulldeps/internal-lints/diagnostics.rs
index f73fdc0882f..1d7417be58c 100644
--- a/tests/ui-fulldeps/internal-lints/diagnostics.rs
+++ b/tests/ui-fulldeps/internal-lints/diagnostics.rs
@@ -14,8 +14,8 @@ extern crate rustc_session;
 extern crate rustc_span;
 
 use rustc_errors::{
-    AddToDiagnostic, DecorateLint, Diag, DiagCtxt, DiagInner, DiagMessage, EmissionGuarantee,
-    IntoDiagnostic, Level, SubdiagMessageOp,
+    Diag, DiagCtxt, DiagInner, DiagMessage, Diagnostic, EmissionGuarantee, Level, LintDiagnostic,
+    SubdiagMessageOp, SubdiagMessage, Subdiagnostic,
 };
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::Span;
@@ -36,27 +36,27 @@ struct Note {
     span: Span,
 }
 
-pub struct UntranslatableInIntoDiagnostic;
+pub struct UntranslatableInDiagnostic;
 
-impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for UntranslatableInIntoDiagnostic {
-    fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
+impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for UntranslatableInDiagnostic {
+    fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
         Diag::new(dcx, level, "untranslatable diagnostic")
         //~^ ERROR diagnostics should be created using translatable messages
     }
 }
 
-pub struct TranslatableInIntoDiagnostic;
+pub struct TranslatableInDiagnostic;
 
-impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for TranslatableInIntoDiagnostic {
-    fn into_diagnostic(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
+impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for TranslatableInDiagnostic {
+    fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> {
         Diag::new(dcx, level, crate::fluent_generated::no_crate_example)
     }
 }
 
-pub struct UntranslatableInAddToDiagnostic;
+pub struct UntranslatableInAddtoDiag;
 
-impl AddToDiagnostic for UntranslatableInAddToDiagnostic {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for UntranslatableInAddtoDiag {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         f: F,
@@ -66,10 +66,10 @@ impl AddToDiagnostic for UntranslatableInAddToDiagnostic {
     }
 }
 
-pub struct TranslatableInAddToDiagnostic;
+pub struct TranslatableInAddtoDiag;
 
-impl AddToDiagnostic for TranslatableInAddToDiagnostic {
-    fn add_to_diagnostic_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
+impl Subdiagnostic for TranslatableInAddtoDiag {
+    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         f: F,
@@ -78,9 +78,9 @@ impl AddToDiagnostic for TranslatableInAddToDiagnostic {
     }
 }
 
-pub struct UntranslatableInDecorateLint;
+pub struct UntranslatableInLintDiagnostic;
 
-impl<'a> DecorateLint<'a, ()> for UntranslatableInDecorateLint {
+impl<'a> LintDiagnostic<'a, ()> for UntranslatableInLintDiagnostic {
     fn decorate_lint<'b, >(self, diag: &'b mut Diag<'a, ()>) {
         diag.note("untranslatable diagnostic");
         //~^ ERROR diagnostics should be created using translatable messages
@@ -91,9 +91,9 @@ impl<'a> DecorateLint<'a, ()> for UntranslatableInDecorateLint {
     }
 }
 
-pub struct TranslatableInDecorateLint;
+pub struct TranslatableInLintDiagnostic;
 
-impl<'a> DecorateLint<'a, ()> for TranslatableInDecorateLint {
+impl<'a> LintDiagnostic<'a, ()> for TranslatableInLintDiagnostic {
     fn decorate_lint<'b>(self, diag: &'b mut Diag<'a, ()>) {
         diag.note(crate::fluent_generated::no_crate_note);
     }
@@ -105,18 +105,24 @@ impl<'a> DecorateLint<'a, ()> for TranslatableInDecorateLint {
 
 pub fn make_diagnostics<'a>(dcx: &'a DiagCtxt) {
     let _diag = dcx.struct_err(crate::fluent_generated::no_crate_example);
-    //~^ ERROR diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
+    //~^ ERROR diagnostics should only be created in `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls
 
     let _diag = dcx.struct_err("untranslatable diagnostic");
-    //~^ ERROR diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
+    //~^ ERROR diagnostics should only be created in `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls
     //~^^ ERROR diagnostics should be created using translatable messages
 }
 
 // Check that `rustc_lint_diagnostics`-annotated functions aren't themselves linted for
 // `diagnostic_outside_of_impl`.
-
 #[rustc_lint_diagnostics]
 pub fn skipped_because_of_annotation<'a>(dcx: &'a DiagCtxt) {
     #[allow(rustc::untranslatable_diagnostic)]
     let _diag = dcx.struct_err("untranslatable diagnostic"); // okay!
 }
+
+// Check that multiple translatable params are allowed in a single function (at one point they
+// weren't).
+fn f(_x: impl Into<DiagMessage>, _y: impl Into<SubdiagMessage>) {}
+fn g() {
+    f(crate::fluent_generated::no_crate_example, crate::fluent_generated::no_crate_example);
+}
diff --git a/tests/ui-fulldeps/internal-lints/diagnostics.stderr b/tests/ui-fulldeps/internal-lints/diagnostics.stderr
index b8fbee1ff00..ee5400f6f95 100644
--- a/tests/ui-fulldeps/internal-lints/diagnostics.stderr
+++ b/tests/ui-fulldeps/internal-lints/diagnostics.stderr
@@ -22,7 +22,7 @@ error: diagnostics should be created using translatable messages
 LL |         diag.note("untranslatable diagnostic");
    |              ^^^^
 
-error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
+error: diagnostics should only be created in `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls
   --> $DIR/diagnostics.rs:107:21
    |
 LL |     let _diag = dcx.struct_err(crate::fluent_generated::no_crate_example);
@@ -34,7 +34,7 @@ note: the lint level is defined here
 LL | #![deny(rustc::diagnostic_outside_of_impl)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: diagnostics should only be created in `IntoDiagnostic`/`AddToDiagnostic` impls
+error: diagnostics should only be created in `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls
   --> $DIR/diagnostics.rs:110:21
    |
 LL |     let _diag = dcx.struct_err("untranslatable diagnostic");
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs
index 40df9cc5dca..432ede89826 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs
@@ -1,6 +1,6 @@
 //@ check-fail
 // Tests that a doc comment will not preclude a field from being considered a diagnostic argument
-//@ normalize-stderr-test "the following other types implement trait `IntoDiagnosticArg`:(?:.*\n){0,9}\s+and \d+ others" -> "normalized in stderr"
+//@ normalize-stderr-test "the following other types implement trait `IntoDiagArg`:(?:.*\n){0,9}\s+and \d+ others" -> "normalized in stderr"
 //@ normalize-stderr-test "(COMPILER_DIR/.*\.rs):[0-9]+:[0-9]+" -> "$1:LL:CC"
 
 // The proc_macro2 crate handles spans differently when on beta/stable release rather than nightly,
@@ -25,7 +25,7 @@ use rustc_span::Span;
 
 rustc_fluent_macro::fluent_messages! { "./example.ftl" }
 
-struct NotIntoDiagnosticArg;
+struct NotIntoDiagArg;
 
 #[derive(Diagnostic)]
 #[diag(no_crate_example)]
@@ -33,8 +33,8 @@ struct Test {
     #[primary_span]
     span: Span,
     /// A doc comment
-    arg: NotIntoDiagnosticArg,
-    //~^ ERROR the trait bound `NotIntoDiagnosticArg: IntoDiagnosticArg` is not satisfied
+    arg: NotIntoDiagArg,
+    //~^ ERROR the trait bound `NotIntoDiagArg: IntoDiagArg` is not satisfied
 }
 
 #[derive(Subdiagnostic)]
@@ -43,6 +43,6 @@ struct SubTest {
     #[primary_span]
     span: Span,
     /// A doc comment
-    arg: NotIntoDiagnosticArg,
-    //~^ ERROR the trait bound `NotIntoDiagnosticArg: IntoDiagnosticArg` is not satisfied
+    arg: NotIntoDiagArg,
+    //~^ ERROR the trait bound `NotIntoDiagArg: IntoDiagArg` is not satisfied
 }
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr
index 98600d28229..7377b0dfd0a 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr
@@ -1,25 +1,25 @@
-error[E0277]: the trait bound `NotIntoDiagnosticArg: IntoDiagnosticArg` is not satisfied
+error[E0277]: the trait bound `NotIntoDiagArg: IntoDiagArg` is not satisfied
   --> $DIR/diagnostic-derive-doc-comment-field.rs:36:10
    |
 LL | #[derive(Diagnostic)]
    |          ---------- required by a bound introduced by this call
 ...
-LL |     arg: NotIntoDiagnosticArg,
-   |          ^^^^^^^^^^^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `NotIntoDiagnosticArg`
+LL |     arg: NotIntoDiagArg,
+   |          ^^^^^^^^^^^^^^ the trait `IntoDiagArg` is not implemented for `NotIntoDiagArg`
    |
    = help: normalized in stderr
 note: required by a bound in `Diag::<'a, G>::arg`
   --> $COMPILER_DIR/rustc_errors/src/diagnostic.rs:LL:CC
    = note: this error originates in the macro `with_fn` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0277]: the trait bound `NotIntoDiagnosticArg: IntoDiagnosticArg` is not satisfied
+error[E0277]: the trait bound `NotIntoDiagArg: IntoDiagArg` is not satisfied
   --> $DIR/diagnostic-derive-doc-comment-field.rs:46:10
    |
 LL | #[derive(Subdiagnostic)]
    |          ------------- required by a bound introduced by this call
 ...
-LL |     arg: NotIntoDiagnosticArg,
-   |          ^^^^^^^^^^^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `NotIntoDiagnosticArg`
+LL |     arg: NotIntoDiagArg,
+   |          ^^^^^^^^^^^^^^ the trait `IntoDiagArg` is not implemented for `NotIntoDiagArg`
    |
    = help: normalized in stderr
 note: required by a bound in `Diag::<'a, G>::arg`
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
index 11070972394..043c7c16654 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
@@ -1,6 +1,6 @@
 //@ check-fail
 // Tests error conditions for specifying diagnostics using #[derive(Diagnostic)]
-//@ normalize-stderr-test "the following other types implement trait `IntoDiagnosticArg`:(?:.*\n){0,9}\s+and \d+ others" -> "normalized in stderr"
+//@ normalize-stderr-test "the following other types implement trait `IntoDiagArg`:(?:.*\n){0,9}\s+and \d+ others" -> "normalized in stderr"
 //@ normalize-stderr-test "(COMPILER_DIR/.*\.rs):[0-9]+:[0-9]+" -> "$1:LL:CC"
 
 // The proc_macro2 crate handles spans differently when on beta/stable release rather than nightly,
@@ -347,7 +347,7 @@ struct ArgFieldWithoutSkip {
     #[primary_span]
     span: Span,
     other: Hello,
-    //~^ ERROR the trait bound `Hello: IntoDiagnosticArg` is not satisfied
+    //~^ ERROR the trait bound `Hello: IntoDiagArg` is not satisfied
 }
 
 #[derive(Diagnostic)]
@@ -355,7 +355,7 @@ struct ArgFieldWithoutSkip {
 struct ArgFieldWithSkip {
     #[primary_span]
     span: Span,
-    // `Hello` does not implement `IntoDiagnosticArg` so this would result in an error if
+    // `Hello` does not implement `IntoDiagArg` so this would result in an error if
     // not for `#[skip_arg]`.
     #[skip_arg]
     other: Hello,
diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
index 058c88d315b..1266430e2f7 100644
--- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
+++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
@@ -618,14 +618,14 @@ LL | #[derive(Diagnostic)]
    |
    = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied
+error[E0277]: the trait bound `Hello: IntoDiagArg` is not satisfied
   --> $DIR/diagnostic-derive.rs:349:12
    |
 LL | #[derive(Diagnostic)]
    |          ---------- required by a bound introduced by this call
 ...
 LL |     other: Hello,
-   |            ^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello`
+   |            ^^^^^ the trait `IntoDiagArg` is not implemented for `Hello`
    |
    = help: normalized in stderr
 note: required by a bound in `Diag::<'a, G>::arg`
diff --git a/tests/ui/abi/anon-extern-mod.rs b/tests/ui/abi/anon-extern-mod.rs
index 692cb0850b9..a424f93f637 100644
--- a/tests/ui/abi/anon-extern-mod.rs
+++ b/tests/ui/abi/anon-extern-mod.rs
@@ -1,6 +1,5 @@
 //@ run-pass
 //@ pretty-expanded FIXME #23616
-//@ ignore-wasm32-bare no libc to test ffi with
 
 #![feature(rustc_private)]
 
diff --git a/tests/ui/abi/c-stack-as-value.rs b/tests/ui/abi/c-stack-as-value.rs
index 5b9b6e566f9..6ea2051b05b 100644
--- a/tests/ui/abi/c-stack-as-value.rs
+++ b/tests/ui/abi/c-stack-as-value.rs
@@ -1,6 +1,5 @@
 //@ run-pass
 //@ pretty-expanded FIXME #23616
-//@ ignore-wasm32-bare no libc to test ffi with
 
 #![feature(rustc_private)]
 
diff --git a/tests/ui/abi/c-stack-returning-int64.rs b/tests/ui/abi/c-stack-returning-int64.rs
index 5caa395d7a5..1fd7fe417a5 100644
--- a/tests/ui/abi/c-stack-returning-int64.rs
+++ b/tests/ui/abi/c-stack-returning-int64.rs
@@ -1,5 +1,4 @@
 //@ run-pass
-//@ ignore-wasm32-bare no libc to test with
 //@ ignore-sgx no libc
 
 #![feature(rustc_private)]
diff --git a/tests/ui/abi/cabi-int-widening.rs b/tests/ui/abi/cabi-int-widening.rs
index 61298082449..e211b989837 100644
--- a/tests/ui/abi/cabi-int-widening.rs
+++ b/tests/ui/abi/cabi-int-widening.rs
@@ -1,5 +1,4 @@
 //@ run-pass
-//@ ignore-wasm32-bare no libc to test ffi with
 
 #[link(name = "rust_test_helpers", kind = "static")]
 extern "C" {
diff --git a/tests/ui/abi/cross-crate/anon-extern-mod-cross-crate-2.rs b/tests/ui/abi/cross-crate/anon-extern-mod-cross-crate-2.rs
index 47402acc93a..95bf4df68df 100644
--- a/tests/ui/abi/cross-crate/anon-extern-mod-cross-crate-2.rs
+++ b/tests/ui/abi/cross-crate/anon-extern-mod-cross-crate-2.rs
@@ -1,7 +1,6 @@
 //@ run-pass
 //@ aux-build:anon-extern-mod-cross-crate-1.rs
 //@ pretty-expanded FIXME #23616
-//@ ignore-wasm32-bare no libc to test ffi with
 
 extern crate anonexternmod;
 
diff --git a/tests/ui/abi/cross-crate/duplicated-external-mods.rs b/tests/ui/abi/cross-crate/duplicated-external-mods.rs
index d1fc3b7c910..2a3875d2773 100644
--- a/tests/ui/abi/cross-crate/duplicated-external-mods.rs
+++ b/tests/ui/abi/cross-crate/duplicated-external-mods.rs
@@ -2,7 +2,6 @@
 //@ aux-build:anon-extern-mod-cross-crate-1.rs
 //@ aux-build:anon-extern-mod-cross-crate-1.rs
 //@ pretty-expanded FIXME #23616
-//@ ignore-wasm32-bare no libc to test ffi with
 
 extern crate anonexternmod;
 
diff --git a/tests/ui/abi/extern/extern-call-deep.rs b/tests/ui/abi/extern/extern-call-deep.rs
index 0c549e6222b..062e70b1b6e 100644
--- a/tests/ui/abi/extern/extern-call-deep.rs
+++ b/tests/ui/abi/extern/extern-call-deep.rs
@@ -1,5 +1,4 @@
 //@ run-pass
-//@ ignore-wasm32-bare no libc to test ffi with
 //@ ignore-emscripten blows the JS stack
 
 #![feature(rustc_private)]
diff --git a/tests/ui/abi/extern/extern-call-indirect.rs b/tests/ui/abi/extern/extern-call-indirect.rs
index 3e874e26542..18fb07d8c8b 100644
--- a/tests/ui/abi/extern/extern-call-indirect.rs
+++ b/tests/ui/abi/extern/extern-call-indirect.rs
@@ -1,5 +1,4 @@
 //@ run-pass
-//@ ignore-wasm32-bare no libc to test ffi with
 
 #![feature(rustc_private)]
 
diff --git a/tests/ui/abi/extern/extern-crosscrate.rs b/tests/ui/abi/extern/extern-crosscrate.rs
index 5a4a339882d..c283cbe3216 100644
--- a/tests/ui/abi/extern/extern-crosscrate.rs
+++ b/tests/ui/abi/extern/extern-crosscrate.rs
@@ -1,6 +1,5 @@
 //@ run-pass
 //@ aux-build:extern-crosscrate-source.rs
-//@ ignore-wasm32-bare no libc to test ffi with
 
 #![feature(rustc_private)]
 
diff --git a/tests/ui/abi/extern/extern-pass-TwoU16s.rs b/tests/ui/abi/extern/extern-pass-TwoU16s.rs
index 69afe7b2532..8bde553050a 100644
--- a/tests/ui/abi/extern/extern-pass-TwoU16s.rs
+++ b/tests/ui/abi/extern/extern-pass-TwoU16s.rs
@@ -1,8 +1,6 @@
 //@ run-pass
 #![allow(improper_ctypes)]
 
-//@ ignore-wasm32-bare no libc for ffi testing
-
 // Test a foreign function that accepts and returns a struct
 // by value.
 
diff --git a/tests/ui/abi/extern/extern-pass-TwoU32s.rs b/tests/ui/abi/extern/extern-pass-TwoU32s.rs
index ca7630fe421..fc90eb6945c 100644
--- a/tests/ui/abi/extern/extern-pass-TwoU32s.rs
+++ b/tests/ui/abi/extern/extern-pass-TwoU32s.rs
@@ -1,8 +1,6 @@
 //@ run-pass
 #![allow(improper_ctypes)]
 
-//@ ignore-wasm32-bare no libc for ffi testing
-
 // Test a foreign function that accepts and returns a struct
 // by value.
 
diff --git a/tests/ui/abi/extern/extern-pass-TwoU64s.rs b/tests/ui/abi/extern/extern-pass-TwoU64s.rs
index a8f629f0906..603de2e49ab 100644
--- a/tests/ui/abi/extern/extern-pass-TwoU64s.rs
+++ b/tests/ui/abi/extern/extern-pass-TwoU64s.rs
@@ -1,8 +1,6 @@
 //@ run-pass
 #![allow(improper_ctypes)]
 
-//@ ignore-wasm32-bare no libc for ffi testing
-
 // Test a foreign function that accepts and returns a struct
 // by value.
 
diff --git a/tests/ui/abi/extern/extern-pass-TwoU8s.rs b/tests/ui/abi/extern/extern-pass-TwoU8s.rs
index 2bf913e4e4f..a712d79a98d 100644
--- a/tests/ui/abi/extern/extern-pass-TwoU8s.rs
+++ b/tests/ui/abi/extern/extern-pass-TwoU8s.rs
@@ -1,8 +1,6 @@
 //@ run-pass
 #![allow(improper_ctypes)]
 
-//@ ignore-wasm32-bare no libc for ffi testing
-
 // Test a foreign function that accepts and returns a struct
 // by value.
 
diff --git a/tests/ui/abi/extern/extern-pass-char.rs b/tests/ui/abi/extern/extern-pass-char.rs
index a0ebd43e076..24196c54b50 100644
--- a/tests/ui/abi/extern/extern-pass-char.rs
+++ b/tests/ui/abi/extern/extern-pass-char.rs
@@ -1,5 +1,4 @@
 //@ run-pass
-//@ ignore-wasm32-bare no libc for ffi testing
 
 // Test a function that takes/returns a u8.
 
diff --git a/tests/ui/abi/extern/extern-pass-double.rs b/tests/ui/abi/extern/extern-pass-double.rs
index 11e23abb782..e883ebe9815 100644
--- a/tests/ui/abi/extern/extern-pass-double.rs
+++ b/tests/ui/abi/extern/extern-pass-double.rs
@@ -1,5 +1,4 @@
 //@ run-pass
-//@ ignore-wasm32-bare no libc for ffi testing
 
 #[link(name = "rust_test_helpers", kind = "static")]
 extern "C" {
diff --git a/tests/ui/abi/extern/extern-pass-u32.rs b/tests/ui/abi/extern/extern-pass-u32.rs
index 69570fc9358..0daff4e9f42 100644
--- a/tests/ui/abi/extern/extern-pass-u32.rs
+++ b/tests/ui/abi/extern/extern-pass-u32.rs
@@ -1,5 +1,4 @@
 //@ run-pass
-//@ ignore-wasm32-bare no libc for ffi testing
 
 // Test a function that takes/returns a u32.
 
diff --git a/tests/ui/abi/extern/extern-pass-u64.rs b/tests/ui/abi/extern/extern-pass-u64.rs
index 43880b96c2d..f1cd6bf59c2 100644
--- a/tests/ui/abi/extern/extern-pass-u64.rs
+++ b/tests/ui/abi/extern/extern-pass-u64.rs
@@ -1,5 +1,4 @@
 //@ run-pass
-//@ ignore-wasm32-bare no libc for ffi testing
 
 // Test a call to a function that takes/returns a u64.
 
diff --git a/tests/ui/abi/extern/extern-return-TwoU16s.rs b/tests/ui/abi/extern/extern-return-TwoU16s.rs
index 723933cd7e7..bf909a8db24 100644
--- a/tests/ui/abi/extern/extern-return-TwoU16s.rs
+++ b/tests/ui/abi/extern/extern-return-TwoU16s.rs
@@ -1,8 +1,6 @@
 //@ run-pass
 #![allow(improper_ctypes)]
 
-//@ ignore-wasm32-bare no libc to test ffi with
-
 pub struct TwoU16s {
     one: u16,
     two: u16,
diff --git a/tests/ui/abi/extern/extern-return-TwoU32s.rs b/tests/ui/abi/extern/extern-return-TwoU32s.rs
index 7795e4f0401..c528da8cfc4 100644
--- a/tests/ui/abi/extern/extern-return-TwoU32s.rs
+++ b/tests/ui/abi/extern/extern-return-TwoU32s.rs
@@ -1,8 +1,6 @@
 //@ run-pass
 #![allow(improper_ctypes)]
 
-//@ ignore-wasm32-bare no libc to test ffi with
-
 pub struct TwoU32s {
     one: u32,
     two: u32,
diff --git a/tests/ui/abi/extern/extern-return-TwoU64s.rs b/tests/ui/abi/extern/extern-return-TwoU64s.rs
index a980b7f1cde..d4f9540ec7b 100644
--- a/tests/ui/abi/extern/extern-return-TwoU64s.rs
+++ b/tests/ui/abi/extern/extern-return-TwoU64s.rs
@@ -1,8 +1,6 @@
 //@ run-pass
 #![allow(improper_ctypes)]
 
-//@ ignore-wasm32-bare no libc to test ffi with
-
 pub struct TwoU64s {
     one: u64,
     two: u64,
diff --git a/tests/ui/abi/extern/extern-return-TwoU8s.rs b/tests/ui/abi/extern/extern-return-TwoU8s.rs
index 73263a9da04..228b2739624 100644
--- a/tests/ui/abi/extern/extern-return-TwoU8s.rs
+++ b/tests/ui/abi/extern/extern-return-TwoU8s.rs
@@ -1,8 +1,6 @@
 //@ run-pass
 #![allow(improper_ctypes)]
 
-//@ ignore-wasm32-bare no libc to test ffi with
-
 pub struct TwoU8s {
     one: u8,
     two: u8,
diff --git a/tests/ui/abi/foreign/foreign-dupe.rs b/tests/ui/abi/foreign/foreign-dupe.rs
index 6469f5d2ce7..1b6df0892c7 100644
--- a/tests/ui/abi/foreign/foreign-dupe.rs
+++ b/tests/ui/abi/foreign/foreign-dupe.rs
@@ -1,6 +1,5 @@
 //@ run-pass
 //@ aux-build:foreign_lib.rs
-//@ ignore-wasm32-bare no libc to test ffi with
 
 // Check that we can still call duplicated extern (imported) functions
 // which were declared in another crate. See issues #32740 and #32783.
diff --git a/tests/ui/abi/foreign/foreign-fn-with-byval.rs b/tests/ui/abi/foreign/foreign-fn-with-byval.rs
index 89bbf406693..9908ec2d2c0 100644
--- a/tests/ui/abi/foreign/foreign-fn-with-byval.rs
+++ b/tests/ui/abi/foreign/foreign-fn-with-byval.rs
@@ -1,8 +1,6 @@
 //@ run-pass
 #![allow(improper_ctypes, improper_ctypes_definitions)]
 
-//@ ignore-wasm32-bare no libc to test ffi with
-
 #[derive(Copy, Clone)]
 pub struct S {
     x: u64,
diff --git a/tests/ui/abi/foreign/foreign-no-abi.rs b/tests/ui/abi/foreign/foreign-no-abi.rs
index 84e21660f1c..4ac47df29a7 100644
--- a/tests/ui/abi/foreign/foreign-no-abi.rs
+++ b/tests/ui/abi/foreign/foreign-no-abi.rs
@@ -1,7 +1,6 @@
 //@ run-pass
 // ABI is cdecl by default
 
-//@ ignore-wasm32-bare no libc to test ffi with
 //@ pretty-expanded FIXME #23616
 
 #![feature(rustc_private)]
diff --git a/tests/ui/abi/foreign/invoke-external-foreign.rs b/tests/ui/abi/foreign/invoke-external-foreign.rs
index 5eccfaf204b..78cc84804bf 100644
--- a/tests/ui/abi/foreign/invoke-external-foreign.rs
+++ b/tests/ui/abi/foreign/invoke-external-foreign.rs
@@ -1,6 +1,5 @@
 //@ run-pass
 //@ aux-build:foreign_lib.rs
-//@ ignore-wasm32-bare no libc to test ffi with
 
 // The purpose of this test is to check that we can
 // successfully (and safely) invoke external, cdecl
diff --git a/tests/ui/abi/homogenous-floats-target-feature-mixup.rs b/tests/ui/abi/homogenous-floats-target-feature-mixup.rs
index 34d3b91d404..3a8540a825c 100644
--- a/tests/ui/abi/homogenous-floats-target-feature-mixup.rs
+++ b/tests/ui/abi/homogenous-floats-target-feature-mixup.rs
@@ -5,7 +5,7 @@
 // without #[repr(simd)]
 
 //@ run-pass
-//@ ignore-emscripten
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 
 #![feature(avx512_target_feature)]
diff --git a/tests/ui/abi/issue-28676.rs b/tests/ui/abi/issue-28676.rs
index 2457d1d7957..8640f5aad21 100644
--- a/tests/ui/abi/issue-28676.rs
+++ b/tests/ui/abi/issue-28676.rs
@@ -2,8 +2,6 @@
 #![allow(dead_code)]
 #![allow(improper_ctypes)]
 
-//@ ignore-wasm32-bare no libc to test ffi with
-
 #[derive(Copy, Clone)]
 pub struct Quad {
     a: u64,
diff --git a/tests/ui/abi/issues/issue-62350-sysv-neg-reg-counts.rs b/tests/ui/abi/issues/issue-62350-sysv-neg-reg-counts.rs
index 21720db5143..314db42280d 100644
--- a/tests/ui/abi/issues/issue-62350-sysv-neg-reg-counts.rs
+++ b/tests/ui/abi/issues/issue-62350-sysv-neg-reg-counts.rs
@@ -2,8 +2,6 @@
 #![allow(dead_code)]
 #![allow(improper_ctypes)]
 
-//@ ignore-wasm32-bare no libc to test ffi with
-
 #[derive(Copy, Clone)]
 pub struct QuadFloats {
     a: f32,
diff --git a/tests/ui/abi/issues/issue-97463-broken-abi-leaked-uninit-data.rs b/tests/ui/abi/issues/issue-97463-broken-abi-leaked-uninit-data.rs
index 316ac7a4880..f6942051748 100644
--- a/tests/ui/abi/issues/issue-97463-broken-abi-leaked-uninit-data.rs
+++ b/tests/ui/abi/issues/issue-97463-broken-abi-leaked-uninit-data.rs
@@ -1,5 +1,4 @@
 //@ run-pass
-//@ ignore-wasm
 #![allow(dead_code)]
 #![allow(improper_ctypes)]
 
diff --git a/tests/ui/abi/lib-defaults.rs b/tests/ui/abi/lib-defaults.rs
index e3caccee62c..2c2cad4f82d 100644
--- a/tests/ui/abi/lib-defaults.rs
+++ b/tests/ui/abi/lib-defaults.rs
@@ -1,8 +1,6 @@
 //@ run-pass
 //@ dont-check-compiler-stderr (rust-lang/rust#54222)
 
-//@ ignore-wasm32-bare no libc to test ffi with
-
 //@ compile-flags: -lrust_test_helpers
 
 #[link(name = "rust_test_helpers", kind = "static")]
diff --git a/tests/ui/abi/mir/mir_codegen_calls_variadic.rs b/tests/ui/abi/mir/mir_codegen_calls_variadic.rs
index ff515b66269..0c1a59b38d3 100644
--- a/tests/ui/abi/mir/mir_codegen_calls_variadic.rs
+++ b/tests/ui/abi/mir/mir_codegen_calls_variadic.rs
@@ -1,5 +1,4 @@
 //@ run-pass
-//@ ignore-wasm32-bare no libc to test ffi with
 
 #[link(name = "rust_test_helpers", kind = "static")]
 extern "C" {
diff --git a/tests/ui/abi/segfault-no-out-of-stack.rs b/tests/ui/abi/segfault-no-out-of-stack.rs
index d03cff80098..fb1f8303f9f 100644
--- a/tests/ui/abi/segfault-no-out-of-stack.rs
+++ b/tests/ui/abi/segfault-no-out-of-stack.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 
 #![allow(unused_imports)]
-//@ ignore-emscripten can't run commands
+//@ ignore-wasm32 can't run commands
 //@ ignore-sgx no processes
 //@ ignore-fuchsia must translate zircon signal to SIGSEGV/SIGBUS, FIXME (#58590)
 #![feature(rustc_private)]
diff --git a/tests/ui/abi/statics/static-mut-foreign.rs b/tests/ui/abi/statics/static-mut-foreign.rs
index f32ce8cf085..33a7194c102 100644
--- a/tests/ui/abi/statics/static-mut-foreign.rs
+++ b/tests/ui/abi/statics/static-mut-foreign.rs
@@ -3,8 +3,6 @@
 // statics cannot. This ensures that there's some form of error if this is
 // attempted.
 
-//@ ignore-wasm32-bare no libc to test ffi with
-
 #![feature(rustc_private)]
 
 extern crate libc;
diff --git a/tests/ui/abi/statics/static-mut-foreign.stderr b/tests/ui/abi/statics/static-mut-foreign.stderr
index f393088ff9f..4d5f26ac08c 100644
--- a/tests/ui/abi/statics/static-mut-foreign.stderr
+++ b/tests/ui/abi/statics/static-mut-foreign.stderr
@@ -1,5 +1,5 @@
 warning: creating a shared reference to mutable static is discouraged
-  --> $DIR/static-mut-foreign.rs:35:18
+  --> $DIR/static-mut-foreign.rs:33:18
    |
 LL |     static_bound(&rust_dbg_static_mut);
    |                  ^^^^^^^^^^^^^^^^^^^^ shared reference to mutable static
@@ -14,7 +14,7 @@ LL |     static_bound(addr_of!(rust_dbg_static_mut));
    |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
 warning: creating a mutable reference to mutable static is discouraged
-  --> $DIR/static-mut-foreign.rs:37:22
+  --> $DIR/static-mut-foreign.rs:35:22
    |
 LL |     static_bound_set(&mut rust_dbg_static_mut);
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^ mutable reference to mutable static
diff --git a/tests/ui/abi/struct-enums/struct-return.rs b/tests/ui/abi/struct-enums/struct-return.rs
index b00f8d8cc2e..5b39c0de454 100644
--- a/tests/ui/abi/struct-enums/struct-return.rs
+++ b/tests/ui/abi/struct-enums/struct-return.rs
@@ -1,6 +1,5 @@
 //@ run-pass
 #![allow(dead_code)]
-//@ ignore-wasm32-bare no libc to test ffi with
 
 #[repr(C)]
 #[derive(Copy, Clone)]
diff --git a/tests/ui/abi/union/union-c-interop.rs b/tests/ui/abi/union/union-c-interop.rs
index 508b07a9833..05eac446a91 100644
--- a/tests/ui/abi/union/union-c-interop.rs
+++ b/tests/ui/abi/union/union-c-interop.rs
@@ -1,8 +1,6 @@
 //@ run-pass
 #![allow(non_snake_case)]
 
-//@ ignore-wasm32-bare no libc to test ffi with
-
 #[derive(Clone, Copy)]
 #[repr(C)]
 struct LARGE_INTEGER_U {
diff --git a/tests/ui/abi/variadic-ffi.rs b/tests/ui/abi/variadic-ffi.rs
index 6b42f268bb9..de4844ac860 100644
--- a/tests/ui/abi/variadic-ffi.rs
+++ b/tests/ui/abi/variadic-ffi.rs
@@ -1,5 +1,4 @@
 //@ run-pass
-//@ ignore-wasm32-bare no libc to test ffi with
 #![feature(c_variadic)]
 
 use std::ffi::VaList;
diff --git a/tests/ui/alloc-error/default-alloc-error-hook.rs b/tests/ui/alloc-error/default-alloc-error-hook.rs
index a8a2027cc45..5f977460b8c 100644
--- a/tests/ui/alloc-error/default-alloc-error-hook.rs
+++ b/tests/ui/alloc-error/default-alloc-error-hook.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 
 use std::alloc::{Layout, handle_alloc_error};
diff --git a/tests/ui/allocator/no_std-alloc-error-handler-custom.rs b/tests/ui/allocator/no_std-alloc-error-handler-custom.rs
index f4825a910b0..6bbfb72510d 100644
--- a/tests/ui/allocator/no_std-alloc-error-handler-custom.rs
+++ b/tests/ui/allocator/no_std-alloc-error-handler-custom.rs
@@ -2,7 +2,6 @@
 //@ ignore-android no libc
 //@ ignore-emscripten no libc
 //@ ignore-sgx no libc
-//@ ignore-wasm32 no libc
 //@ only-linux
 //@ compile-flags:-C panic=abort
 //@ aux-build:helper.rs
diff --git a/tests/ui/allocator/no_std-alloc-error-handler-default.rs b/tests/ui/allocator/no_std-alloc-error-handler-default.rs
index 1fa1797bf9c..8bcf054ac85 100644
--- a/tests/ui/allocator/no_std-alloc-error-handler-default.rs
+++ b/tests/ui/allocator/no_std-alloc-error-handler-default.rs
@@ -2,7 +2,6 @@
 //@ ignore-android no libc
 //@ ignore-emscripten no libc
 //@ ignore-sgx no libc
-//@ ignore-wasm32 no libc
 //@ only-linux
 //@ compile-flags:-C panic=abort
 //@ aux-build:helper.rs
diff --git a/tests/ui/asm/issue-87802.rs b/tests/ui/asm/issue-87802.rs
index d93de9ee57f..569eb384e15 100644
--- a/tests/ui/asm/issue-87802.rs
+++ b/tests/ui/asm/issue-87802.rs
@@ -1,7 +1,6 @@
 //@ needs-asm-support
 //@ ignore-nvptx64
 //@ ignore-spirv
-//@ ignore-wasm32
 // Make sure rustc doesn't ICE on asm! when output type is !.
 
 use std::arch::asm;
diff --git a/tests/ui/asm/issue-87802.stderr b/tests/ui/asm/issue-87802.stderr
index 762f3d02a41..64e91662919 100644
--- a/tests/ui/asm/issue-87802.stderr
+++ b/tests/ui/asm/issue-87802.stderr
@@ -1,5 +1,5 @@
 error: cannot use value of type `!` for inline assembly
-  --> $DIR/issue-87802.rs:12:36
+  --> $DIR/issue-87802.rs:11:36
    |
 LL |         asm!("/* {0} */", out(reg) x);
    |                                    ^
diff --git a/tests/ui/asm/naked-functions.rs b/tests/ui/asm/naked-functions.rs
index 41d6393996d..1619ebfcf39 100644
--- a/tests/ui/asm/naked-functions.rs
+++ b/tests/ui/asm/naked-functions.rs
@@ -1,7 +1,6 @@
 //@ needs-asm-support
 //@ ignore-nvptx64
 //@ ignore-spirv
-//@ ignore-wasm32
 
 #![feature(naked_functions)]
 #![feature(asm_const, asm_unwind)]
diff --git a/tests/ui/asm/naked-functions.stderr b/tests/ui/asm/naked-functions.stderr
index 6613c3dfdba..77bc80a101f 100644
--- a/tests/ui/asm/naked-functions.stderr
+++ b/tests/ui/asm/naked-functions.stderr
@@ -1,53 +1,53 @@
 error: asm with the `pure` option must have at least one output
-  --> $DIR/naked-functions.rs:113:14
+  --> $DIR/naked-functions.rs:112:14
    |
 LL |     asm!("", options(readonly, nostack), options(pure));
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^  ^^^^^^^^^^^^^
 
 error: this is a user specified error
-  --> $DIR/naked-functions.rs:205:5
+  --> $DIR/naked-functions.rs:204:5
    |
 LL |     compile_error!("this is a user specified error")
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: this is a user specified error
-  --> $DIR/naked-functions.rs:211:5
+  --> $DIR/naked-functions.rs:210:5
    |
 LL |     compile_error!("this is a user specified error");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: asm template must be a string literal
-  --> $DIR/naked-functions.rs:218:10
+  --> $DIR/naked-functions.rs:217:10
    |
 LL |     asm!(invalid_syntax)
    |          ^^^^^^^^^^^^^^
 
 error: patterns not allowed in naked function parameters
-  --> $DIR/naked-functions.rs:20:5
+  --> $DIR/naked-functions.rs:19:5
    |
 LL |     mut a: u32,
    |     ^^^^^
 
 error: patterns not allowed in naked function parameters
-  --> $DIR/naked-functions.rs:22:5
+  --> $DIR/naked-functions.rs:21:5
    |
 LL |     &b: &i32,
    |     ^^
 
 error: patterns not allowed in naked function parameters
-  --> $DIR/naked-functions.rs:24:6
+  --> $DIR/naked-functions.rs:23:6
    |
 LL |     (None | Some(_)): Option<std::ptr::NonNull<u8>>,
    |      ^^^^^^^^^^^^^^
 
 error: patterns not allowed in naked function parameters
-  --> $DIR/naked-functions.rs:26:5
+  --> $DIR/naked-functions.rs:25:5
    |
 LL |     P { x, y }: P,
    |     ^^^^^^^^^^
 
 error: referencing function parameters is not allowed in naked functions
-  --> $DIR/naked-functions.rs:35:5
+  --> $DIR/naked-functions.rs:34:5
    |
 LL |     a + 1
    |     ^
@@ -55,7 +55,7 @@ LL |     a + 1
    = help: follow the calling convention in asm block to use parameters
 
 error[E0787]: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:33:1
+  --> $DIR/naked-functions.rs:32:1
    |
 LL | pub unsafe extern "C" fn inc(a: u32) -> u32 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -64,7 +64,7 @@ LL |     a + 1
    |     ----- non-asm is unsupported in naked functions
 
 error: referencing function parameters is not allowed in naked functions
-  --> $DIR/naked-functions.rs:42:31
+  --> $DIR/naked-functions.rs:41:31
    |
 LL |     asm!("/* {0} */", in(reg) a, options(noreturn));
    |                               ^
@@ -72,13 +72,13 @@ LL |     asm!("/* {0} */", in(reg) a, options(noreturn));
    = help: follow the calling convention in asm block to use parameters
 
 error[E0787]: only `const` and `sym` operands are supported in naked functions
-  --> $DIR/naked-functions.rs:42:23
+  --> $DIR/naked-functions.rs:41:23
    |
 LL |     asm!("/* {0} */", in(reg) a, options(noreturn));
    |                       ^^^^^^^^^
 
 error[E0787]: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:48:1
+  --> $DIR/naked-functions.rs:47:1
    |
 LL | pub unsafe extern "C" fn inc_closure(a: u32) -> u32 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -87,7 +87,7 @@ LL |     (|| a + 1)()
    |     ------------ non-asm is unsupported in naked functions
 
 error[E0787]: only `const` and `sym` operands are supported in naked functions
-  --> $DIR/naked-functions.rs:65:10
+  --> $DIR/naked-functions.rs:64:10
    |
 LL |          in(reg) a,
    |          ^^^^^^^^^
@@ -102,7 +102,7 @@ LL |          out(reg) e,
    |          ^^^^^^^^^^
 
 error[E0787]: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:63:5
+  --> $DIR/naked-functions.rs:62:5
    |
 LL | /     asm!("/* {0} {1} {2} {3} {4} {5} {6} */",
 LL | |
@@ -119,7 +119,7 @@ LL |          sym G, options(noreturn),
    |               +++++++++++++++++++
 
 error[E0787]: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:54:1
+  --> $DIR/naked-functions.rs:53:1
    |
 LL | pub unsafe extern "C" fn unsupported_operands() {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -136,13 +136,13 @@ LL |     let mut e = 0usize;
    |     ------------------- non-asm is unsupported in naked functions
 
 error[E0787]: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:77:1
+  --> $DIR/naked-functions.rs:76:1
    |
 LL | pub extern "C" fn missing_assembly() {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0787]: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:85:9
+  --> $DIR/naked-functions.rs:84:9
    |
 LL |         asm!("");
    |         ^^^^^^^^
@@ -153,7 +153,7 @@ LL |         asm!("", options(noreturn));
    |                +++++++++++++++++++
 
 error[E0787]: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:87:9
+  --> $DIR/naked-functions.rs:86:9
    |
 LL |         asm!("");
    |         ^^^^^^^^
@@ -164,7 +164,7 @@ LL |         asm!("", options(noreturn));
    |                +++++++++++++++++++
 
 error[E0787]: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:89:9
+  --> $DIR/naked-functions.rs:88:9
    |
 LL |         asm!("");
    |         ^^^^^^^^
@@ -175,7 +175,7 @@ LL |         asm!("", options(noreturn));
    |                +++++++++++++++++++
 
 error[E0787]: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:82:1
+  --> $DIR/naked-functions.rs:81:1
    |
 LL | pub extern "C" fn too_many_asm_blocks() {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -190,7 +190,7 @@ LL |         asm!("", options(noreturn));
    |         --------------------------- multiple asm blocks are unsupported in naked functions
 
 error: referencing function parameters is not allowed in naked functions
-  --> $DIR/naked-functions.rs:99:11
+  --> $DIR/naked-functions.rs:98:11
    |
 LL |         *&y
    |           ^
@@ -198,7 +198,7 @@ LL |         *&y
    = help: follow the calling convention in asm block to use parameters
 
 error[E0787]: naked functions must contain a single asm block
-  --> $DIR/naked-functions.rs:97:5
+  --> $DIR/naked-functions.rs:96:5
    |
 LL |     pub extern "C" fn inner(y: usize) -> usize {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -207,19 +207,19 @@ LL |         *&y
    |         --- non-asm is unsupported in naked functions
 
 error[E0787]: asm options unsupported in naked functions: `nomem`, `preserves_flags`
-  --> $DIR/naked-functions.rs:107:5
+  --> $DIR/naked-functions.rs:106:5
    |
 LL |     asm!("", options(nomem, preserves_flags, noreturn));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0787]: asm options unsupported in naked functions: `nostack`, `pure`, `readonly`
-  --> $DIR/naked-functions.rs:113:5
+  --> $DIR/naked-functions.rs:112:5
    |
 LL |     asm!("", options(readonly, nostack), options(pure));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0787]: asm in naked functions must use `noreturn` option
-  --> $DIR/naked-functions.rs:113:5
+  --> $DIR/naked-functions.rs:112:5
    |
 LL |     asm!("", options(readonly, nostack), options(pure));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -230,13 +230,13 @@ LL |     asm!("", options(noreturn), options(readonly, nostack), options(pure));
    |            +++++++++++++++++++
 
 error[E0787]: asm options unsupported in naked functions: `may_unwind`
-  --> $DIR/naked-functions.rs:121:5
+  --> $DIR/naked-functions.rs:120:5
    |
 LL |     asm!("", options(noreturn, may_unwind));
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: Rust ABI is unsupported in naked functions
-  --> $DIR/naked-functions.rs:126:1
+  --> $DIR/naked-functions.rs:125:1
    |
 LL | pub unsafe fn default_abi() {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -244,43 +244,43 @@ LL | pub unsafe fn default_abi() {
    = note: `#[warn(undefined_naked_function_abi)]` on by default
 
 warning: Rust ABI is unsupported in naked functions
-  --> $DIR/naked-functions.rs:132:1
+  --> $DIR/naked-functions.rs:131:1
    |
 LL | pub unsafe fn rust_abi() {
    | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:172:1
+  --> $DIR/naked-functions.rs:171:1
    |
 LL | #[inline]
    | ^^^^^^^^^
 
 error: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:179:1
+  --> $DIR/naked-functions.rs:178:1
    |
 LL | #[inline(always)]
    | ^^^^^^^^^^^^^^^^^
 
 error: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:186:1
+  --> $DIR/naked-functions.rs:185:1
    |
 LL | #[inline(never)]
    | ^^^^^^^^^^^^^^^^
 
 error: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:193:1
+  --> $DIR/naked-functions.rs:192:1
    |
 LL | #[inline]
    | ^^^^^^^^^
 
 error: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:195:1
+  --> $DIR/naked-functions.rs:194:1
    |
 LL | #[inline(always)]
    | ^^^^^^^^^^^^^^^^^
 
 error: naked functions cannot be inlined
-  --> $DIR/naked-functions.rs:197:1
+  --> $DIR/naked-functions.rs:196:1
    |
 LL | #[inline(never)]
    | ^^^^^^^^^^^^^^^^
diff --git a/tests/ui/asm/named-asm-labels.rs b/tests/ui/asm/named-asm-labels.rs
index 2e21d56e323..96ccdef75b0 100644
--- a/tests/ui/asm/named-asm-labels.rs
+++ b/tests/ui/asm/named-asm-labels.rs
@@ -1,7 +1,6 @@
 //@ needs-asm-support
 //@ ignore-nvptx64
 //@ ignore-spirv
-//@ ignore-wasm32
 
 // Tests that the use of named labels in the `asm!` macro are linted against
 // except for in `#[naked]` fns.
diff --git a/tests/ui/asm/named-asm-labels.stderr b/tests/ui/asm/named-asm-labels.stderr
index 89c05849967..36fd6983951 100644
--- a/tests/ui/asm/named-asm-labels.stderr
+++ b/tests/ui/asm/named-asm-labels.stderr
@@ -1,5 +1,5 @@
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:24:15
+  --> $DIR/named-asm-labels.rs:23:15
    |
 LL |         asm!("bar: nop");
    |               ^^^
@@ -9,7 +9,7 @@ LL |         asm!("bar: nop");
    = note: `#[deny(named_asm_labels)]` on by default
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:27:15
+  --> $DIR/named-asm-labels.rs:26:15
    |
 LL |         asm!("abcd:");
    |               ^^^^
@@ -18,7 +18,7 @@ LL |         asm!("abcd:");
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:30:15
+  --> $DIR/named-asm-labels.rs:29:15
    |
 LL |         asm!("foo: bar1: nop");
    |               ^^^  ^^^^
@@ -27,7 +27,7 @@ LL |         asm!("foo: bar1: nop");
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:34:15
+  --> $DIR/named-asm-labels.rs:33:15
    |
 LL |         asm!("foo1: nop", "nop");
    |               ^^^^
@@ -36,7 +36,7 @@ LL |         asm!("foo1: nop", "nop");
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:35:15
+  --> $DIR/named-asm-labels.rs:34:15
    |
 LL |         asm!("foo2: foo3: nop", "nop");
    |               ^^^^  ^^^^
@@ -45,7 +45,7 @@ LL |         asm!("foo2: foo3: nop", "nop");
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:37:22
+  --> $DIR/named-asm-labels.rs:36:22
    |
 LL |         asm!("nop", "foo4: nop");
    |                      ^^^^
@@ -54,7 +54,7 @@ LL |         asm!("nop", "foo4: nop");
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:38:15
+  --> $DIR/named-asm-labels.rs:37:15
    |
 LL |         asm!("foo5: nop", "foo6: nop");
    |               ^^^^
@@ -63,7 +63,7 @@ LL |         asm!("foo5: nop", "foo6: nop");
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:38:28
+  --> $DIR/named-asm-labels.rs:37:28
    |
 LL |         asm!("foo5: nop", "foo6: nop");
    |                            ^^^^
@@ -72,7 +72,7 @@ LL |         asm!("foo5: nop", "foo6: nop");
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:43:15
+  --> $DIR/named-asm-labels.rs:42:15
    |
 LL |         asm!("foo7: nop; foo8: nop");
    |               ^^^^       ^^^^
@@ -81,7 +81,7 @@ LL |         asm!("foo7: nop; foo8: nop");
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:45:15
+  --> $DIR/named-asm-labels.rs:44:15
    |
 LL |         asm!("foo9: nop; nop");
    |               ^^^^
@@ -90,7 +90,7 @@ LL |         asm!("foo9: nop; nop");
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:46:20
+  --> $DIR/named-asm-labels.rs:45:20
    |
 LL |         asm!("nop; foo10: nop");
    |                    ^^^^^
@@ -99,7 +99,7 @@ LL |         asm!("nop; foo10: nop");
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:49:15
+  --> $DIR/named-asm-labels.rs:48:15
    |
 LL |         asm!("bar2: nop\n bar3: nop");
    |               ^^^^        ^^^^
@@ -108,7 +108,7 @@ LL |         asm!("bar2: nop\n bar3: nop");
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:51:15
+  --> $DIR/named-asm-labels.rs:50:15
    |
 LL |         asm!("bar4: nop\n nop");
    |               ^^^^
@@ -117,7 +117,7 @@ LL |         asm!("bar4: nop\n nop");
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:52:21
+  --> $DIR/named-asm-labels.rs:51:21
    |
 LL |         asm!("nop\n bar5: nop");
    |                     ^^^^
@@ -126,7 +126,7 @@ LL |         asm!("nop\n bar5: nop");
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:53:21
+  --> $DIR/named-asm-labels.rs:52:21
    |
 LL |         asm!("nop\n bar6: bar7: nop");
    |                     ^^^^  ^^^^
@@ -135,7 +135,7 @@ LL |         asm!("nop\n bar6: bar7: nop");
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:59:13
+  --> $DIR/named-asm-labels.rs:58:13
    |
 LL |             blah2: nop
    |             ^^^^^
@@ -146,7 +146,7 @@ LL |             blah3: nop
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:68:19
+  --> $DIR/named-asm-labels.rs:67:19
    |
 LL |             nop ; blah4: nop
    |                   ^^^^^
@@ -155,7 +155,7 @@ LL |             nop ; blah4: nop
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:82:15
+  --> $DIR/named-asm-labels.rs:81:15
    |
 LL |         asm!("blah1: 2bar: nop");
    |               ^^^^^
@@ -164,7 +164,7 @@ LL |         asm!("blah1: 2bar: nop");
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:85:15
+  --> $DIR/named-asm-labels.rs:84:15
    |
 LL |         asm!("def: def: nop");
    |               ^^^
@@ -173,7 +173,7 @@ LL |         asm!("def: def: nop");
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:86:15
+  --> $DIR/named-asm-labels.rs:85:15
    |
 LL |         asm!("def: nop\ndef: nop");
    |               ^^^
@@ -182,7 +182,7 @@ LL |         asm!("def: nop\ndef: nop");
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:87:15
+  --> $DIR/named-asm-labels.rs:86:15
    |
 LL |         asm!("def: nop; def: nop");
    |               ^^^
@@ -191,7 +191,7 @@ LL |         asm!("def: nop; def: nop");
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:95:15
+  --> $DIR/named-asm-labels.rs:94:15
    |
 LL |         asm!("fooo\u{003A} nop");
    |               ^^^^^^^^^^^^^^^^
@@ -200,7 +200,7 @@ LL |         asm!("fooo\u{003A} nop");
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:96:15
+  --> $DIR/named-asm-labels.rs:95:15
    |
 LL |         asm!("foooo\x3A nop");
    |               ^^^^^^^^^^^^^
@@ -209,7 +209,7 @@ LL |         asm!("foooo\x3A nop");
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:99:15
+  --> $DIR/named-asm-labels.rs:98:15
    |
 LL |         asm!("fooooo:\u{000A} nop");
    |               ^^^^^^
@@ -218,7 +218,7 @@ LL |         asm!("fooooo:\u{000A} nop");
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:100:15
+  --> $DIR/named-asm-labels.rs:99:15
    |
 LL |         asm!("foooooo:\x0A nop");
    |               ^^^^^^^
@@ -227,7 +227,7 @@ LL |         asm!("foooooo:\x0A nop");
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:104:14
+  --> $DIR/named-asm-labels.rs:103:14
    |
 LL |         asm!("\x41\x42\x43\x3A\x20\x6E\x6F\x70");
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -236,7 +236,7 @@ LL |         asm!("\x41\x42\x43\x3A\x20\x6E\x6F\x70");
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:112:13
+  --> $DIR/named-asm-labels.rs:111:13
    |
 LL |             ab: nop // ab: does foo
    |             ^^
@@ -245,7 +245,7 @@ LL |             ab: nop // ab: does foo
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:132:19
+  --> $DIR/named-asm-labels.rs:131:19
    |
 LL |             asm!("test_{}: nop", in(reg) 10);
    |                   ^^^^^^^
@@ -254,7 +254,7 @@ LL |             asm!("test_{}: nop", in(reg) 10);
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:134:15
+  --> $DIR/named-asm-labels.rs:133:15
    |
 LL |         asm!("test_{}: nop", const 10);
    |               ^^^^^^^
@@ -263,7 +263,7 @@ LL |         asm!("test_{}: nop", const 10);
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:135:15
+  --> $DIR/named-asm-labels.rs:134:15
    |
 LL |         asm!("test_{}: nop", sym main);
    |               ^^^^^^^
@@ -272,7 +272,7 @@ LL |         asm!("test_{}: nop", sym main);
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:136:15
+  --> $DIR/named-asm-labels.rs:135:15
    |
 LL |         asm!("{}_test: nop", const 10);
    |               ^^^^^^^
@@ -281,7 +281,7 @@ LL |         asm!("{}_test: nop", const 10);
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:137:15
+  --> $DIR/named-asm-labels.rs:136:15
    |
 LL |         asm!("test_{}_test: nop", const 10);
    |               ^^^^^^^^^^^^
@@ -290,7 +290,7 @@ LL |         asm!("test_{}_test: nop", const 10);
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:138:15
+  --> $DIR/named-asm-labels.rs:137:15
    |
 LL |         asm!("{}: nop", const 10);
    |               ^^
@@ -299,7 +299,7 @@ LL |         asm!("{}: nop", const 10);
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:140:15
+  --> $DIR/named-asm-labels.rs:139:15
    |
 LL |         asm!("{uwu}: nop", uwu = const 10);
    |               ^^^^^
@@ -308,7 +308,7 @@ LL |         asm!("{uwu}: nop", uwu = const 10);
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:141:15
+  --> $DIR/named-asm-labels.rs:140:15
    |
 LL |         asm!("{0}: nop", const 10);
    |               ^^^
@@ -317,7 +317,7 @@ LL |         asm!("{0}: nop", const 10);
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:142:15
+  --> $DIR/named-asm-labels.rs:141:15
    |
 LL |         asm!("{1}: nop", "/* {0} */", const 10, const 20);
    |               ^^^
@@ -326,7 +326,7 @@ LL |         asm!("{1}: nop", "/* {0} */", const 10, const 20);
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:145:14
+  --> $DIR/named-asm-labels.rs:144:14
    |
 LL |         asm!(include_str!("named-asm-labels.s"));
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -335,7 +335,7 @@ LL |         asm!(include_str!("named-asm-labels.s"));
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 warning: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:155:19
+  --> $DIR/named-asm-labels.rs:154:19
    |
 LL |             asm!("warned: nop");
    |                   ^^^^^^
@@ -343,13 +343,13 @@ LL |             asm!("warned: nop");
    = help: only local labels of the form `<number>:` should be used in inline asm
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 note: the lint level is defined here
-  --> $DIR/named-asm-labels.rs:153:16
+  --> $DIR/named-asm-labels.rs:152:16
    |
 LL |         #[warn(named_asm_labels)]
    |                ^^^^^^^^^^^^^^^^
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:164:20
+  --> $DIR/named-asm-labels.rs:163:20
    |
 LL |     unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noreturn)) }
    |                    ^^^^^
@@ -358,7 +358,7 @@ LL |     unsafe { asm!(".Lfoo: mov rax, {}; ret;", "nop", const 1, options(noret
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:170:20
+  --> $DIR/named-asm-labels.rs:169:20
    |
 LL |     unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noreturn)) }
    |                    ^^^^^
@@ -367,7 +367,7 @@ LL |     unsafe { asm!(".Lbar: mov rax, {}; ret;", "nop", const 1, options(noret
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:178:20
+  --> $DIR/named-asm-labels.rs:177:20
    |
 LL |     unsafe { asm!(".Laaa: nop; ret;", options(noreturn)) }
    |                    ^^^^^
@@ -376,7 +376,7 @@ LL |     unsafe { asm!(".Laaa: nop; ret;", options(noreturn)) }
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:188:24
+  --> $DIR/named-asm-labels.rs:187:24
    |
 LL |         unsafe { asm!(".Lbbb: nop; ret;", options(noreturn)) }
    |                        ^^^^^
@@ -385,7 +385,7 @@ LL |         unsafe { asm!(".Lbbb: nop; ret;", options(noreturn)) }
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:197:15
+  --> $DIR/named-asm-labels.rs:196:15
    |
 LL |         asm!("closure1: nop");
    |               ^^^^^^^^
@@ -394,7 +394,7 @@ LL |         asm!("closure1: nop");
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:201:15
+  --> $DIR/named-asm-labels.rs:200:15
    |
 LL |         asm!("closure2: nop");
    |               ^^^^^^^^
@@ -403,7 +403,7 @@ LL |         asm!("closure2: nop");
    = note: see the asm section of Rust By Example <https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html#labels> for more information
 
 error: avoid using named labels in inline assembly
-  --> $DIR/named-asm-labels.rs:211:19
+  --> $DIR/named-asm-labels.rs:210:19
    |
 LL |             asm!("closure3: nop");
    |                   ^^^^^^^^
diff --git a/tests/ui/asm/type-check-1.rs b/tests/ui/asm/type-check-1.rs
index b18c487fc4b..b0f1362f543 100644
--- a/tests/ui/asm/type-check-1.rs
+++ b/tests/ui/asm/type-check-1.rs
@@ -1,7 +1,6 @@
 //@ needs-asm-support
 //@ ignore-nvptx64
 //@ ignore-spirv
-//@ ignore-wasm32
 
 #![feature(asm_const)]
 
diff --git a/tests/ui/asm/type-check-1.stderr b/tests/ui/asm/type-check-1.stderr
index 1845139659d..07a609c5213 100644
--- a/tests/ui/asm/type-check-1.stderr
+++ b/tests/ui/asm/type-check-1.stderr
@@ -1,5 +1,5 @@
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/type-check-1.rs:42:26
+  --> $DIR/type-check-1.rs:41:26
    |
 LL |         let x = 0;
    |         ----- help: consider using `const` instead of `let`: `const x`
@@ -8,7 +8,7 @@ LL |         asm!("{}", const x);
    |                          ^ non-constant value
 
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/type-check-1.rs:45:36
+  --> $DIR/type-check-1.rs:44:36
    |
 LL |         let x = 0;
    |         ----- help: consider using `const` instead of `let`: `const x`
@@ -17,7 +17,7 @@ LL |         asm!("{}", const const_foo(x));
    |                                    ^ non-constant value
 
 error[E0435]: attempt to use a non-constant value in a constant
-  --> $DIR/type-check-1.rs:48:36
+  --> $DIR/type-check-1.rs:47:36
    |
 LL |         let x = 0;
    |         ----- help: consider using `const` instead of `let`: `const x`
@@ -26,7 +26,7 @@ LL |         asm!("{}", const const_bar(x));
    |                                    ^ non-constant value
 
 error: invalid `sym` operand
-  --> $DIR/type-check-1.rs:50:24
+  --> $DIR/type-check-1.rs:49:24
    |
 LL |         asm!("{}", sym x);
    |                        ^ is a local variable
@@ -34,19 +34,19 @@ LL |         asm!("{}", sym x);
    = help: `sym` operands must refer to either a function or a static
 
 error: invalid asm output
-  --> $DIR/type-check-1.rs:15:29
+  --> $DIR/type-check-1.rs:14:29
    |
 LL |         asm!("{}", out(reg) 1 + 2);
    |                             ^^^^^ cannot assign to this expression
 
 error: invalid asm output
-  --> $DIR/type-check-1.rs:17:31
+  --> $DIR/type-check-1.rs:16:31
    |
 LL |         asm!("{}", inout(reg) 1 + 2);
    |                               ^^^^^ cannot assign to this expression
 
 error[E0277]: the size for values of type `[u64]` cannot be known at compilation time
-  --> $DIR/type-check-1.rs:23:28
+  --> $DIR/type-check-1.rs:22:28
    |
 LL |         asm!("{}", in(reg) v[..]);
    |                            ^^^^^ doesn't have a size known at compile-time
@@ -55,7 +55,7 @@ LL |         asm!("{}", in(reg) v[..]);
    = note: all inline asm arguments must have a statically known size
 
 error[E0277]: the size for values of type `[u64]` cannot be known at compilation time
-  --> $DIR/type-check-1.rs:26:29
+  --> $DIR/type-check-1.rs:25:29
    |
 LL |         asm!("{}", out(reg) v[..]);
    |                             ^^^^^ doesn't have a size known at compile-time
@@ -64,7 +64,7 @@ LL |         asm!("{}", out(reg) v[..]);
    = note: all inline asm arguments must have a statically known size
 
 error[E0277]: the size for values of type `[u64]` cannot be known at compilation time
-  --> $DIR/type-check-1.rs:29:31
+  --> $DIR/type-check-1.rs:28:31
    |
 LL |         asm!("{}", inout(reg) v[..]);
    |                               ^^^^^ doesn't have a size known at compile-time
@@ -73,7 +73,7 @@ LL |         asm!("{}", inout(reg) v[..]);
    = note: all inline asm arguments must have a statically known size
 
 error: cannot use value of type `[u64]` for inline assembly
-  --> $DIR/type-check-1.rs:23:28
+  --> $DIR/type-check-1.rs:22:28
    |
 LL |         asm!("{}", in(reg) v[..]);
    |                            ^^^^^
@@ -81,7 +81,7 @@ LL |         asm!("{}", in(reg) v[..]);
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `[u64]` for inline assembly
-  --> $DIR/type-check-1.rs:26:29
+  --> $DIR/type-check-1.rs:25:29
    |
 LL |         asm!("{}", out(reg) v[..]);
    |                             ^^^^^
@@ -89,7 +89,7 @@ LL |         asm!("{}", out(reg) v[..]);
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error: cannot use value of type `[u64]` for inline assembly
-  --> $DIR/type-check-1.rs:29:31
+  --> $DIR/type-check-1.rs:28:31
    |
 LL |         asm!("{}", inout(reg) v[..]);
    |                               ^^^^^
@@ -97,13 +97,13 @@ LL |         asm!("{}", inout(reg) v[..]);
    = note: only integers, floats, SIMD vectors, pointers and function pointers can be used as arguments for inline assembly
 
 error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:58:26
+  --> $DIR/type-check-1.rs:57:26
    |
 LL |         asm!("{}", const 0f32);
    |                          ^^^^ expected integer, found `f32`
 
 error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:60:26
+  --> $DIR/type-check-1.rs:59:26
    |
 LL |         asm!("{}", const 0 as *mut u8);
    |                          ^^^^^^^^^^^^ expected integer, found `*mut u8`
@@ -112,7 +112,7 @@ LL |         asm!("{}", const 0 as *mut u8);
            found raw pointer `*mut u8`
 
 error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:62:26
+  --> $DIR/type-check-1.rs:61:26
    |
 LL |         asm!("{}", const &0);
    |                          ^^ expected integer, found `&{integer}`
@@ -124,13 +124,13 @@ LL +         asm!("{}", const 0);
    |
 
 error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:76:25
+  --> $DIR/type-check-1.rs:75:25
    |
 LL | global_asm!("{}", const 0f32);
    |                         ^^^^ expected integer, found `f32`
 
 error[E0308]: mismatched types
-  --> $DIR/type-check-1.rs:78:25
+  --> $DIR/type-check-1.rs:77:25
    |
 LL | global_asm!("{}", const 0 as *mut u8);
    |                         ^^^^^^^^^^^^ expected integer, found `*mut u8`
diff --git a/tests/ui/asm/type-check-4.rs b/tests/ui/asm/type-check-4.rs
index 0529811d3ba..a5b5e29294b 100644
--- a/tests/ui/asm/type-check-4.rs
+++ b/tests/ui/asm/type-check-4.rs
@@ -1,7 +1,6 @@
 //@ needs-asm-support
 //@ ignore-nvptx64
 //@ ignore-spirv
-//@ ignore-wasm32
 
 use std::arch::asm;
 
diff --git a/tests/ui/asm/type-check-4.stderr b/tests/ui/asm/type-check-4.stderr
index b5ecb3e1b56..5c328a184c8 100644
--- a/tests/ui/asm/type-check-4.stderr
+++ b/tests/ui/asm/type-check-4.stderr
@@ -1,5 +1,5 @@
 error[E0506]: cannot assign to `a` because it is borrowed
-  --> $DIR/type-check-4.rs:14:9
+  --> $DIR/type-check-4.rs:13:9
    |
 LL |         let p = &a;
    |                 -- `a` is borrowed here
@@ -10,7 +10,7 @@ LL |         println!("{}", p);
    |                        - borrow later used here
 
 error[E0503]: cannot use `a` because it was mutably borrowed
-  --> $DIR/type-check-4.rs:22:28
+  --> $DIR/type-check-4.rs:21:28
    |
 LL |         let p = &mut a;
    |                 ------ `a` is borrowed here
diff --git a/tests/ui/associated-consts/assoc-const-eq-supertraits.rs b/tests/ui/associated-consts/assoc-const-eq-supertraits.rs
new file mode 100644
index 00000000000..d5d724c9b15
--- /dev/null
+++ b/tests/ui/associated-consts/assoc-const-eq-supertraits.rs
@@ -0,0 +1,16 @@
+// Regression test for issue #118040.
+// Ensure that we support assoc const eq bounds where the assoc const comes from a supertrait.
+
+//@ check-pass
+
+#![feature(associated_const_equality)]
+
+trait Trait: SuperTrait {}
+trait SuperTrait: SuperSuperTrait<i32> {}
+trait SuperSuperTrait<T> {
+    const K: T;
+}
+
+fn take(_: impl Trait<K = 0>) {}
+
+fn main() {}
diff --git a/tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs b/tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs
index 4ff05112897..76df014ccd9 100644
--- a/tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs
+++ b/tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs
@@ -1,21 +1,25 @@
 // Regression test for issue #112560.
 // Respect the fact that (associated) types and constants live in different namespaces and
 // therefore equality bounds involving identically named associated items don't conflict if
-// their kind (type vs. const) differs.
-
-// FIXME(fmease): Extend this test to cover supertraits again
-// once #118040 is fixed. See initial version of PR #118360.
+// their kind (type vs. const) differs. This obviously extends to supertraits.
 
 //@ check-pass
 
 #![feature(associated_const_equality)]
 
-trait Trait {
+trait Trait: SuperTrait {
     type N;
+    type Q;
 
     const N: usize;
 }
 
-fn take(_: impl Trait<N = 0, N = ()>) {}
+trait SuperTrait {
+    const Q: &'static str;
+}
+
+fn take0(_: impl Trait<N = 0, N = ()>) {}
+
+fn take1(_: impl Trait<Q = "...", Q = [()]>) {}
 
 fn main() {}
diff --git a/tests/ui/associated-consts/freeze.rs b/tests/ui/associated-consts/freeze.rs
new file mode 100644
index 00000000000..2364ee1f495
--- /dev/null
+++ b/tests/ui/associated-consts/freeze.rs
@@ -0,0 +1,12 @@
+#![feature(freeze)]
+
+//@ check-pass
+
+use std::marker::Freeze;
+
+trait Trait<T: Freeze + 'static> {
+    const VALUE: T;
+    const VALUE_REF: &'static T = &Self::VALUE;
+}
+
+fn main() {}
diff --git a/tests/ui/associated-inherent-types/bugs/wf-check-skipped.next.stderr b/tests/ui/associated-inherent-types/bugs/wf-check-skipped.next.stderr
new file mode 100644
index 00000000000..77fbaf52934
--- /dev/null
+++ b/tests/ui/associated-inherent-types/bugs/wf-check-skipped.next.stderr
@@ -0,0 +1,8 @@
+error: the type `Foo::Bar<Vec<[u32]>>` is not well-formed
+  --> $DIR/wf-check-skipped.rs:17:14
+   |
+LL | fn main() -> Foo::Bar::<Vec<[u32]>> {}
+   |              ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/associated-inherent-types/bugs/wf-check-skipped.rs b/tests/ui/associated-inherent-types/bugs/wf-check-skipped.rs
index 3159500393e..5b812a2295e 100644
--- a/tests/ui/associated-inherent-types/bugs/wf-check-skipped.rs
+++ b/tests/ui/associated-inherent-types/bugs/wf-check-skipped.rs
@@ -1,11 +1,13 @@
-//@ known-bug: #100041
-//@ check-pass
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[current] known-bug: #100041
+//@[current] check-pass
+// FIXME(inherent_associated_types): This should fail.
 
 #![feature(inherent_associated_types)]
 #![allow(incomplete_features)]
 
-// FIXME(inherent_associated_types): This should fail.
-
 struct Foo;
 
 impl Foo {
@@ -13,3 +15,4 @@ impl Foo {
 }
 
 fn main() -> Foo::Bar::<Vec<[u32]>> {}
+//[next]~^ ERROR the type `Foo::Bar<Vec<[u32]>>` is not well-formed
diff --git a/tests/ui/associated-inherent-types/inference.rs b/tests/ui/associated-inherent-types/inference.rs
index f520c610685..31016f1091b 100644
--- a/tests/ui/associated-inherent-types/inference.rs
+++ b/tests/ui/associated-inherent-types/inference.rs
@@ -1,6 +1,7 @@
 // Testing inference capabilities.
 //@ check-pass
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 #![feature(inherent_associated_types)]
diff --git a/tests/ui/associated-types/defaults-unsound-62211-2.stderr b/tests/ui/associated-types/defaults-unsound-62211-1.current.stderr
index 89319bb7563..9d52e923ade 100644
--- a/tests/ui/associated-types/defaults-unsound-62211-2.stderr
+++ b/tests/ui/associated-types/defaults-unsound-62211-1.current.stderr
@@ -1,12 +1,12 @@
 error[E0277]: `Self` doesn't implement `std::fmt::Display`
-  --> $DIR/defaults-unsound-62211-2.rs:20:96
+  --> $DIR/defaults-unsound-62211-1.rs:26:96
    |
 LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
    |                                                                                                ^^^^ `Self` cannot be formatted with the default formatter
    |
    = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
 note: required by a bound in `UncheckedCopy::Output`
-  --> $DIR/defaults-unsound-62211-2.rs:20:86
+  --> $DIR/defaults-unsound-62211-1.rs:26:86
    |
 LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
    |                                                                                      ^^^^^^^ required by this bound in `UncheckedCopy::Output`
@@ -16,13 +16,13 @@ LL | trait UncheckedCopy: Sized + std::fmt::Display {
    |                            +++++++++++++++++++
 
 error[E0277]: cannot add-assign `&'static str` to `Self`
-  --> $DIR/defaults-unsound-62211-2.rs:20:96
+  --> $DIR/defaults-unsound-62211-1.rs:26:96
    |
 LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
    |                                                                                                ^^^^ no implementation for `Self += &'static str`
    |
 note: required by a bound in `UncheckedCopy::Output`
-  --> $DIR/defaults-unsound-62211-2.rs:20:47
+  --> $DIR/defaults-unsound-62211-1.rs:26:47
    |
 LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
@@ -32,13 +32,13 @@ LL | trait UncheckedCopy: Sized + AddAssign<&'static str> {
    |                            +++++++++++++++++++++++++
 
 error[E0277]: the trait bound `Self: Deref` is not satisfied
-  --> $DIR/defaults-unsound-62211-2.rs:20:96
+  --> $DIR/defaults-unsound-62211-1.rs:26:96
    |
 LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
    |                                                                                                ^^^^ the trait `Deref` is not implemented for `Self`
    |
 note: required by a bound in `UncheckedCopy::Output`
-  --> $DIR/defaults-unsound-62211-2.rs:20:25
+  --> $DIR/defaults-unsound-62211-1.rs:26:25
    |
 LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
    |                         ^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
@@ -48,13 +48,13 @@ LL | trait UncheckedCopy: Sized + Deref {
    |                            +++++++
 
 error[E0277]: the trait bound `Self: Copy` is not satisfied
-  --> $DIR/defaults-unsound-62211-2.rs:20:96
+  --> $DIR/defaults-unsound-62211-1.rs:26:96
    |
 LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
    |                                                                                                ^^^^ the trait `Copy` is not implemented for `Self`
    |
 note: required by a bound in `UncheckedCopy::Output`
-  --> $DIR/defaults-unsound-62211-2.rs:20:18
+  --> $DIR/defaults-unsound-62211-1.rs:26:18
    |
 LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
    |                  ^^^^ required by this bound in `UncheckedCopy::Output`
diff --git a/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr b/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr
new file mode 100644
index 00000000000..834ae00a8d8
--- /dev/null
+++ b/tests/ui/associated-types/defaults-unsound-62211-1.next.stderr
@@ -0,0 +1,13 @@
+warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing
+  --> $DIR/defaults-unsound-62211-1.rs:52:5
+   |
+LL |     drop(origin);
+   |     ^^^^^------^
+   |          |
+   |          argument has type `<T as UncheckedCopy>::Output`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+   = note: `#[warn(dropping_copy_types)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/associated-types/defaults-unsound-62211-1.rs b/tests/ui/associated-types/defaults-unsound-62211-1.rs
index fa6a208b4f1..d9cf5aa97ac 100644
--- a/tests/ui/associated-types/defaults-unsound-62211-1.rs
+++ b/tests/ui/associated-types/defaults-unsound-62211-1.rs
@@ -1,3 +1,9 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] known-bug: rust-lang/trait-system-refactor-initiative#46
+//@[next] check-pass
+
 //! Regression test for https://github.com/rust-lang/rust/issues/62211
 //!
 //! The old implementation of defaults did not check whether the provided
@@ -18,10 +24,10 @@ trait UncheckedCopy: Sized {
     // This Output is said to be Copy. Yet we default to Self
     // and it's accepted, not knowing if Self ineed is Copy
     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
-    //~^ ERROR the trait bound `Self: Copy` is not satisfied
-    //~| ERROR the trait bound `Self: Deref` is not satisfied
-    //~| ERROR cannot add-assign `&'static str` to `Self`
-    //~| ERROR `Self` doesn't implement `std::fmt::Display`
+    //[current]~^ ERROR the trait bound `Self: Copy` is not satisfied
+    //[current]~| ERROR the trait bound `Self: Deref` is not satisfied
+    //[current]~| ERROR cannot add-assign `&'static str` to `Self`
+    //[current]~| ERROR `Self` doesn't implement `std::fmt::Display`
 
     // We said the Output type was Copy, so we can Copy it freely!
     fn unchecked_copy(other: &Self::Output) -> Self::Output {
diff --git a/tests/ui/associated-types/defaults-unsound-62211-1.stderr b/tests/ui/associated-types/defaults-unsound-62211-2.current.stderr
index 5cd1cb4a1a7..4fd2ca6408a 100644
--- a/tests/ui/associated-types/defaults-unsound-62211-1.stderr
+++ b/tests/ui/associated-types/defaults-unsound-62211-2.current.stderr
@@ -1,12 +1,12 @@
 error[E0277]: `Self` doesn't implement `std::fmt::Display`
-  --> $DIR/defaults-unsound-62211-1.rs:20:96
+  --> $DIR/defaults-unsound-62211-2.rs:26:96
    |
 LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
    |                                                                                                ^^^^ `Self` cannot be formatted with the default formatter
    |
    = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
 note: required by a bound in `UncheckedCopy::Output`
-  --> $DIR/defaults-unsound-62211-1.rs:20:86
+  --> $DIR/defaults-unsound-62211-2.rs:26:86
    |
 LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
    |                                                                                      ^^^^^^^ required by this bound in `UncheckedCopy::Output`
@@ -16,13 +16,13 @@ LL | trait UncheckedCopy: Sized + std::fmt::Display {
    |                            +++++++++++++++++++
 
 error[E0277]: cannot add-assign `&'static str` to `Self`
-  --> $DIR/defaults-unsound-62211-1.rs:20:96
+  --> $DIR/defaults-unsound-62211-2.rs:26:96
    |
 LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
    |                                                                                                ^^^^ no implementation for `Self += &'static str`
    |
 note: required by a bound in `UncheckedCopy::Output`
-  --> $DIR/defaults-unsound-62211-1.rs:20:47
+  --> $DIR/defaults-unsound-62211-2.rs:26:47
    |
 LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
    |                                               ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
@@ -32,13 +32,13 @@ LL | trait UncheckedCopy: Sized + AddAssign<&'static str> {
    |                            +++++++++++++++++++++++++
 
 error[E0277]: the trait bound `Self: Deref` is not satisfied
-  --> $DIR/defaults-unsound-62211-1.rs:20:96
+  --> $DIR/defaults-unsound-62211-2.rs:26:96
    |
 LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
    |                                                                                                ^^^^ the trait `Deref` is not implemented for `Self`
    |
 note: required by a bound in `UncheckedCopy::Output`
-  --> $DIR/defaults-unsound-62211-1.rs:20:25
+  --> $DIR/defaults-unsound-62211-2.rs:26:25
    |
 LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
    |                         ^^^^^^^^^^^^^^^^^^^ required by this bound in `UncheckedCopy::Output`
@@ -48,13 +48,13 @@ LL | trait UncheckedCopy: Sized + Deref {
    |                            +++++++
 
 error[E0277]: the trait bound `Self: Copy` is not satisfied
-  --> $DIR/defaults-unsound-62211-1.rs:20:96
+  --> $DIR/defaults-unsound-62211-2.rs:26:96
    |
 LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
    |                                                                                                ^^^^ the trait `Copy` is not implemented for `Self`
    |
 note: required by a bound in `UncheckedCopy::Output`
-  --> $DIR/defaults-unsound-62211-1.rs:20:18
+  --> $DIR/defaults-unsound-62211-2.rs:26:18
    |
 LL |     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
    |                  ^^^^ required by this bound in `UncheckedCopy::Output`
diff --git a/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr b/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr
new file mode 100644
index 00000000000..0f944a18ed5
--- /dev/null
+++ b/tests/ui/associated-types/defaults-unsound-62211-2.next.stderr
@@ -0,0 +1,13 @@
+warning: calls to `std::mem::drop` with a value that implements `Copy` does nothing
+  --> $DIR/defaults-unsound-62211-2.rs:52:5
+   |
+LL |     drop(origin);
+   |     ^^^^^------^
+   |          |
+   |          argument has type `<T as UncheckedCopy>::Output`
+   |
+   = note: use `let _ = ...` to ignore the expression or result
+   = note: `#[warn(dropping_copy_types)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/associated-types/defaults-unsound-62211-2.rs b/tests/ui/associated-types/defaults-unsound-62211-2.rs
index c13ec776afe..6cbac1bf236 100644
--- a/tests/ui/associated-types/defaults-unsound-62211-2.rs
+++ b/tests/ui/associated-types/defaults-unsound-62211-2.rs
@@ -1,3 +1,9 @@
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] known-bug: rust-lang/trait-system-refactor-initiative#46
+//@[next] check-pass
+
 //! Regression test for https://github.com/rust-lang/rust/issues/62211
 //!
 //! The old implementation of defaults did not check whether the provided
@@ -18,10 +24,10 @@ trait UncheckedCopy: Sized {
     // This Output is said to be Copy. Yet we default to Self
     // and it's accepted, not knowing if Self ineed is Copy
     type Output: Copy + Deref<Target = str> + AddAssign<&'static str> + From<Self> + Display = Self;
-    //~^ ERROR the trait bound `Self: Copy` is not satisfied
-    //~| ERROR the trait bound `Self: Deref` is not satisfied
-    //~| ERROR cannot add-assign `&'static str` to `Self`
-    //~| ERROR `Self` doesn't implement `std::fmt::Display`
+    //[current]~^ ERROR the trait bound `Self: Copy` is not satisfied
+    //[current]~| ERROR the trait bound `Self: Deref` is not satisfied
+    //[current]~| ERROR cannot add-assign `&'static str` to `Self`
+    //[current]~| ERROR `Self` doesn't implement `std::fmt::Display`
 
     // We said the Output type was Copy, so we can Copy it freely!
     fn unchecked_copy(other: &Self::Output) -> Self::Output {
diff --git a/tests/ui/async-await/async-closures/is-fn.rs b/tests/ui/async-await/async-closures/is-fn.rs
index 64cc28e425f..89c3a96bbbe 100644
--- a/tests/ui/async-await/async-closures/is-fn.rs
+++ b/tests/ui/async-await/async-closures/is-fn.rs
@@ -2,6 +2,7 @@
 //@ edition:2021
 //@ build-pass
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 #![feature(async_closure)]
diff --git a/tests/ui/async-await/async-closures/once.rs b/tests/ui/async-await/async-closures/once.rs
index 761df3de444..7009e0d132f 100644
--- a/tests/ui/async-await/async-closures/once.rs
+++ b/tests/ui/async-await/async-closures/once.rs
@@ -2,6 +2,7 @@
 //@ edition:2021
 //@ build-pass
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 #![feature(async_closure)]
diff --git a/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs b/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs
index 5680c057737..be338ddeb7d 100644
--- a/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs
+++ b/tests/ui/async-await/async-fn/higher-ranked-async-fn.rs
@@ -1,6 +1,7 @@
 //@ aux-build:block-on.rs
 //@ edition:2018
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@ build-pass (since it ICEs during mono)
 
diff --git a/tests/ui/async-await/async-fn/project.rs b/tests/ui/async-await/async-fn/project.rs
index 302564bb951..5cbdc378dda 100644
--- a/tests/ui/async-await/async-fn/project.rs
+++ b/tests/ui/async-await/async-fn/project.rs
@@ -1,5 +1,6 @@
 //@ edition:2018
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@ check-pass
 
diff --git a/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-completion.rs b/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-completion.rs
index a6e53c06e31..a8b05a4befa 100644
--- a/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-completion.rs
+++ b/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-completion.rs
@@ -5,8 +5,6 @@
 //@ error-pattern: thread 'main' panicked
 //@ error-pattern: `async fn` resumed after completion
 //@ edition:2018
-//@ ignore-wasm no panic or subprocess support
-//@ ignore-emscripten no panic or subprocess support
 
 #![feature(coroutines, coroutine_trait)]
 
diff --git a/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs b/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs
index d64184c1012..94366e66263 100644
--- a/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs
+++ b/tests/ui/async-await/issues/issue-65419/issue-65419-async-fn-resume-after-panic.rs
@@ -6,7 +6,6 @@
 //@ error-pattern: thread 'main' panicked
 //@ error-pattern: `async fn` resumed after panicking
 //@ edition:2018
-//@ ignore-wasm no panic or subprocess support
 
 #![feature(coroutines, coroutine_trait)]
 
diff --git a/tests/ui/async-await/issues/issue-65419/issue-65419-coroutine-resume-after-completion.rs b/tests/ui/async-await/issues/issue-65419/issue-65419-coroutine-resume-after-completion.rs
index 7a23457e62a..f937311a5a0 100644
--- a/tests/ui/async-await/issues/issue-65419/issue-65419-coroutine-resume-after-completion.rs
+++ b/tests/ui/async-await/issues/issue-65419/issue-65419-coroutine-resume-after-completion.rs
@@ -5,8 +5,6 @@
 //@ run-fail
 //@ error-pattern:coroutine resumed after completion
 //@ edition:2018
-//@ ignore-wasm no panic or subprocess support
-//@ ignore-emscripten no panic or subprocess support
 
 #![feature(coroutines, coroutine_trait)]
 
diff --git a/tests/ui/async-await/normalize-output-in-signature-deduction.rs b/tests/ui/async-await/normalize-output-in-signature-deduction.rs
index 177e8625531..19d70c2c6ee 100644
--- a/tests/ui/async-await/normalize-output-in-signature-deduction.rs
+++ b/tests/ui/async-await/normalize-output-in-signature-deduction.rs
@@ -1,5 +1,6 @@
 //@ edition:2021
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@ check-pass
 
diff --git a/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.current.stderr b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.current.stderr
index 2e82a3fcdb4..4837815fad4 100644
--- a/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.current.stderr
+++ b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.current.stderr
@@ -1,5 +1,5 @@
 warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/normalizing-self-auto-trait-issue-109924.rs:6:12
+  --> $DIR/normalizing-self-auto-trait-issue-109924.rs:7:12
    |
 LL | #![feature(return_type_notation)]
    |            ^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.next.stderr b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.next.stderr
index 2e82a3fcdb4..4837815fad4 100644
--- a/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.next.stderr
+++ b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.next.stderr
@@ -1,5 +1,5 @@
 warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/normalizing-self-auto-trait-issue-109924.rs:6:12
+  --> $DIR/normalizing-self-auto-trait-issue-109924.rs:7:12
    |
 LL | #![feature(return_type_notation)]
    |            ^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.rs b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.rs
index 0e167b149f3..bee9ad2516e 100644
--- a/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.rs
+++ b/tests/ui/async-await/return-type-notation/normalizing-self-auto-trait-issue-109924.rs
@@ -1,5 +1,6 @@
 //@ check-pass
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@ edition:2021
 
diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-bare.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-bare.rs
index 7bf1c7350c3..5d95fc70e78 100644
--- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-bare.rs
+++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-bare.rs
@@ -1,4 +1,4 @@
 #![feature(unix_sigpipe)]
 
-#[unix_sigpipe] //~ error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
+#[unix_sigpipe] //~ error: malformed `unix_sigpipe` attribute input
 fn main() {}
diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-bare.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-bare.stderr
index 56218ed499e..c1b4470d54a 100644
--- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-bare.stderr
+++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-bare.stderr
@@ -1,8 +1,8 @@
-error: valid values for `#[unix_sigpipe = "..."]` are `inherit`, `sig_ign`, or `sig_dfl`
+error: malformed `unix_sigpipe` attribute input
   --> $DIR/unix_sigpipe-bare.rs:3:1
    |
 LL | #[unix_sigpipe]
-   | ^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^ help: must be of the form: `#[unix_sigpipe = "inherit|sig_ign|sig_dfl"]`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.rs
index d6d020c52b2..f5fa177f29c 100644
--- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.rs
+++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.rs
@@ -1,4 +1,4 @@
 #![feature(unix_sigpipe)]
-#![unix_sigpipe = "inherit"] //~ error: `unix_sigpipe` attribute cannot be used at crate level
+#![unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute cannot be used at crate level
 
 fn main() {}
diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr
index 1666f4a3ee8..fdfa3018086 100644
--- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr
+++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-crate.stderr
@@ -1,7 +1,7 @@
 error: `unix_sigpipe` attribute cannot be used at crate level
   --> $DIR/unix_sigpipe-crate.rs:2:1
    |
-LL | #![unix_sigpipe = "inherit"]
+LL | #![unix_sigpipe = "sig_dfl"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 LL |
 LL | fn main() {}
@@ -9,8 +9,8 @@ LL | fn main() {}
    |
 help: perhaps you meant to use an outer attribute
    |
-LL - #![unix_sigpipe = "inherit"]
-LL + #[unix_sigpipe = "inherit"]
+LL - #![unix_sigpipe = "sig_dfl"]
+LL + #[unix_sigpipe = "sig_dfl"]
    |
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.rs
index b5ebc07a043..462ae24a884 100644
--- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.rs
+++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.rs
@@ -1,4 +1,4 @@
 #![feature(unix_sigpipe)]
 
-#[unix_sigpipe(inherit)] //~ error: malformed `unix_sigpipe` attribute input
+#[unix_sigpipe(sig_dfl)] //~ error: malformed `unix_sigpipe` attribute input
 fn main() {}
diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.stderr
index b1d79d7c2a2..66902f3ca9a 100644
--- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.stderr
+++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-list.stderr
@@ -1,15 +1,8 @@
 error: malformed `unix_sigpipe` attribute input
   --> $DIR/unix_sigpipe-list.rs:3:1
    |
-LL | #[unix_sigpipe(inherit)]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-help: the following are the possible correct uses
-   |
-LL | #[unix_sigpipe = "inherit|sig_ign|sig_dfl"]
-   | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-LL | #[unix_sigpipe]
-   | ~~~~~~~~~~~~~~~
+LL | #[unix_sigpipe(sig_dfl)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[unix_sigpipe = "inherit|sig_ign|sig_dfl"]`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.rs
index cde6719fc9c..16731a4ba2c 100644
--- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.rs
+++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.rs
@@ -1,6 +1,6 @@
 #![feature(unix_sigpipe)]
 
-#[unix_sigpipe = "inherit"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()`
+#[unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()`
 fn f() {}
 
 fn main() {}
diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.stderr
index 124141b6552..fcdd5db8f29 100644
--- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.stderr
+++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-main-fn.stderr
@@ -1,7 +1,7 @@
 error: `unix_sigpipe` attribute can only be used on `fn main()`
   --> $DIR/unix_sigpipe-non-main-fn.rs:3:1
    |
-LL | #[unix_sigpipe = "inherit"]
+LL | #[unix_sigpipe = "sig_dfl"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.rs
index 16f7276398e..a2435258620 100644
--- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.rs
+++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.rs
@@ -1,7 +1,7 @@
 #![feature(unix_sigpipe)]
 
 mod m {
-    #[unix_sigpipe = "inherit"] //~ error: `unix_sigpipe` attribute can only be used on root `fn main()`
+    #[unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute can only be used on root `fn main()`
     fn main() {}
 }
 
diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.stderr
index 346d83fa664..98afb62fdb4 100644
--- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.stderr
+++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-non-root-main.stderr
@@ -1,7 +1,7 @@
 error: `unix_sigpipe` attribute can only be used on root `fn main()`
   --> $DIR/unix_sigpipe-non-root-main.rs:4:5
    |
-LL |     #[unix_sigpipe = "inherit"]
+LL |     #[unix_sigpipe = "sig_dfl"]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.rs
index 64fd5ec4f0e..945b820f9e0 100644
--- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.rs
+++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.rs
@@ -2,5 +2,5 @@
 #![feature(unix_sigpipe)]
 
 #[start]
-#[unix_sigpipe = "inherit"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()`
+#[unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()`
 fn custom_start(argc: isize, argv: *const *const u8) -> isize { 0 }
diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.stderr
index 9f691e396bd..3d56b3655c9 100644
--- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.stderr
+++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-start.stderr
@@ -1,7 +1,7 @@
 error: `unix_sigpipe` attribute can only be used on `fn main()`
   --> $DIR/unix_sigpipe-start.rs:5:1
    |
-LL | #[unix_sigpipe = "inherit"]
+LL | #[unix_sigpipe = "sig_dfl"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.rs b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.rs
index a5e47cfebc8..662779c0821 100644
--- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.rs
+++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.rs
@@ -1,6 +1,6 @@
 #![feature(unix_sigpipe)]
 
-#[unix_sigpipe = "inherit"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()`
+#[unix_sigpipe = "sig_dfl"] //~ error: `unix_sigpipe` attribute can only be used on `fn main()`
 struct S;
 
 fn main() {}
diff --git a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.stderr b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.stderr
index d5eec9424c8..a8fc51bdbc4 100644
--- a/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.stderr
+++ b/tests/ui/attributes/unix_sigpipe/unix_sigpipe-struct.stderr
@@ -1,7 +1,7 @@
 error: `unix_sigpipe` attribute can only be used on `fn main()`
   --> $DIR/unix_sigpipe-struct.rs:3:1
    |
-LL | #[unix_sigpipe = "inherit"]
+LL | #[unix_sigpipe = "sig_dfl"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/auto-traits/issue-23080-2.current.stderr b/tests/ui/auto-traits/issue-23080-2.current.stderr
index 178bfff97d2..62c7b37041f 100644
--- a/tests/ui/auto-traits/issue-23080-2.current.stderr
+++ b/tests/ui/auto-traits/issue-23080-2.current.stderr
@@ -1,5 +1,5 @@
 error[E0380]: auto traits cannot have associated items
-  --> $DIR/issue-23080-2.rs:8:10
+  --> $DIR/issue-23080-2.rs:9:10
    |
 LL | unsafe auto trait Trait {
    |                   ----- auto traits cannot have associated items
diff --git a/tests/ui/auto-traits/issue-23080-2.next.stderr b/tests/ui/auto-traits/issue-23080-2.next.stderr
index 178bfff97d2..62c7b37041f 100644
--- a/tests/ui/auto-traits/issue-23080-2.next.stderr
+++ b/tests/ui/auto-traits/issue-23080-2.next.stderr
@@ -1,5 +1,5 @@
 error[E0380]: auto traits cannot have associated items
-  --> $DIR/issue-23080-2.rs:8:10
+  --> $DIR/issue-23080-2.rs:9:10
    |
 LL | unsafe auto trait Trait {
    |                   ----- auto traits cannot have associated items
diff --git a/tests/ui/auto-traits/issue-23080-2.rs b/tests/ui/auto-traits/issue-23080-2.rs
index 2bfddd449b9..f1e7599959d 100644
--- a/tests/ui/auto-traits/issue-23080-2.rs
+++ b/tests/ui/auto-traits/issue-23080-2.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 #![feature(auto_traits)]
diff --git a/tests/ui/backtrace.rs b/tests/ui/backtrace.rs
index 5c138b75de7..2579ff5203b 100644
--- a/tests/ui/backtrace.rs
+++ b/tests/ui/backtrace.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 //@ ignore-android FIXME #17520
-//@ ignore-emscripten spawning processes is not supported
+//@ ignore-wasm32 spawning processes is not supported
 //@ ignore-openbsd no support for libbacktrace without filename
 //@ ignore-sgx no processes
 //@ ignore-msvc see #62897 and `backtrace-debuginfo.rs` test
diff --git a/tests/ui/binop/issue-77910-1.stderr b/tests/ui/binop/issue-77910-1.stderr
index 6402e568188..71d03b38cd6 100644
--- a/tests/ui/binop/issue-77910-1.stderr
+++ b/tests/ui/binop/issue-77910-1.stderr
@@ -1,3 +1,16 @@
+error[E0381]: used binding `xs` isn't initialized
+  --> $DIR/issue-77910-1.rs:3:5
+   |
+LL |     let xs;
+   |         -- binding declared here but left uninitialized
+LL |     xs
+   |     ^^ `xs` used here but it isn't initialized
+   |
+help: consider assigning a value
+   |
+LL |     let xs = todo!();
+   |            +++++++++
+
 error[E0369]: binary operation `==` cannot be applied to type `for<'a> fn(&'a i32) -> &'a i32 {foo}`
   --> $DIR/issue-77910-1.rs:8:5
    |
@@ -22,19 +35,6 @@ LL |     assert_eq!(foo, y);
    = help: use parentheses to call this function: `foo(/* &i32 */)`
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error[E0381]: used binding `xs` isn't initialized
-  --> $DIR/issue-77910-1.rs:3:5
-   |
-LL |     let xs;
-   |         -- binding declared here but left uninitialized
-LL |     xs
-   |     ^^ `xs` used here but it isn't initialized
-   |
-help: consider assigning a value
-   |
-LL |     let xs = todo!();
-   |            +++++++++
-
 error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0277, E0369, E0381.
diff --git a/tests/ui/binop/issue-77910-2.stderr b/tests/ui/binop/issue-77910-2.stderr
index a14560ff188..87f074ff313 100644
--- a/tests/ui/binop/issue-77910-2.stderr
+++ b/tests/ui/binop/issue-77910-2.stderr
@@ -1,16 +1,3 @@
-error[E0369]: binary operation `==` cannot be applied to type `for<'a> fn(&'a i32) -> &'a i32 {foo}`
-  --> $DIR/issue-77910-2.rs:7:12
-   |
-LL |     if foo == y {}
-   |        --- ^^ - _
-   |        |
-   |        for<'a> fn(&'a i32) -> &'a i32 {foo}
-   |
-help: use parentheses to call this function
-   |
-LL |     if foo(/* &i32 */) == y {}
-   |           ++++++++++++
-
 error[E0381]: used binding `xs` isn't initialized
   --> $DIR/issue-77910-2.rs:3:5
    |
@@ -24,6 +11,19 @@ help: consider assigning a value
 LL |     let xs = todo!();
    |            +++++++++
 
+error[E0369]: binary operation `==` cannot be applied to type `for<'a> fn(&'a i32) -> &'a i32 {foo}`
+  --> $DIR/issue-77910-2.rs:7:12
+   |
+LL |     if foo == y {}
+   |        --- ^^ - _
+   |        |
+   |        for<'a> fn(&'a i32) -> &'a i32 {foo}
+   |
+help: use parentheses to call this function
+   |
+LL |     if foo(/* &i32 */) == y {}
+   |           ++++++++++++
+
 error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0369, E0381.
diff --git a/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr
index 098a2964e9f..c5903b3ab56 100644
--- a/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr
+++ b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr
@@ -13,6 +13,15 @@ help: use `addr_of_mut!` instead to create a raw pointer
 LL |             c1(addr_of_mut!(Y));
    |                ~~~~~~~~~~~~~~~
 
+error[E0594]: cannot assign to `x`, as it is not declared as mutable
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:9:46
+   |
+LL |     pub fn e(x: &'static mut isize) {
+   |              - help: consider changing this to be mutable: `mut x`
+LL |         static mut Y: isize = 3;
+LL |         let mut c1 = |y: &'static mut isize| x = y;
+   |                                              ^^^^^ cannot assign
+
 warning: creating a mutable reference to mutable static is discouraged
   --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:27:16
    |
@@ -27,29 +36,6 @@ help: use `addr_of_mut!` instead to create a raw pointer
 LL |             c1(addr_of_mut!(Z));
    |                ~~~~~~~~~~~~~~~
 
-warning: creating a mutable reference to mutable static is discouraged
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:64:37
-   |
-LL |         borrowck_closures_unique::e(&mut X);
-   |                                     ^^^^^^ mutable reference to mutable static
-   |
-   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
-   = note: this will be a hard error in the 2024 edition
-   = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior
-help: use `addr_of_mut!` instead to create a raw pointer
-   |
-LL |         borrowck_closures_unique::e(addr_of_mut!(X));
-   |                                     ~~~~~~~~~~~~~~~
-
-error[E0594]: cannot assign to `x`, as it is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:9:46
-   |
-LL |     pub fn e(x: &'static mut isize) {
-   |              - help: consider changing this to be mutable: `mut x`
-LL |         static mut Y: isize = 3;
-LL |         let mut c1 = |y: &'static mut isize| x = y;
-   |                                              ^^^^^ cannot assign
-
 error[E0594]: cannot assign to `x`, as it is not declared as mutable
   --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:22:50
    |
@@ -95,6 +81,20 @@ LL |         || {
 LL |             &mut x.0;
    |             ^^^^^^^^ cannot borrow as mutable
 
+warning: creating a mutable reference to mutable static is discouraged
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:64:37
+   |
+LL |         borrowck_closures_unique::e(&mut X);
+   |                                     ^^^^^^ mutable reference to mutable static
+   |
+   = note: for more information, see issue #114447 <https://github.com/rust-lang/rust/issues/114447>
+   = note: this will be a hard error in the 2024 edition
+   = note: this mutable reference has lifetime `'static`, but if the static gets accessed (read or written) by any other means, or any other reference is created, then any further use of this mutable reference is Undefined Behavior
+help: use `addr_of_mut!` instead to create a raw pointer
+   |
+LL |         borrowck_closures_unique::e(addr_of_mut!(X));
+   |                                     ~~~~~~~~~~~~~~~
+
 error: aborting due to 6 previous errors; 3 warnings emitted
 
 Some errors have detailed explanations: E0594, E0596.
diff --git a/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs b/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs
index ac0d4f6e099..b6bcf7b6617 100644
--- a/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs
+++ b/tests/ui/borrowck/two-phase-reservation-sharing-interference.rs
@@ -2,7 +2,7 @@
 
 // The nll_beyond revision is disabled due to missing support from two-phase beyond autorefs
 //@[nll_beyond]compile-flags: -Z two-phase-beyond-autoref
-//[nll_beyond]should-fail
+//@[nll_beyond]should-fail
 
 // This is a corner case that the current implementation is (probably)
 // treating more conservatively than is necessary. But it also does
diff --git a/tests/ui/cfg/cfg-family.rs b/tests/ui/cfg/cfg-family.rs
index b90656a0b41..caf59327f10 100644
--- a/tests/ui/cfg/cfg-family.rs
+++ b/tests/ui/cfg/cfg-family.rs
@@ -1,6 +1,6 @@
 //@ build-pass
 //@ pretty-expanded FIXME #23616
-//@ ignore-wasm32-bare no bare family
+//@ ignore-wasm32 no bare family
 //@ ignore-sgx
 
 #[cfg(windows)]
diff --git a/tests/ui/check-static-recursion-foreign.rs b/tests/ui/check-static-recursion-foreign.rs
index 418c149dcc4..97db47d0bd6 100644
--- a/tests/ui/check-static-recursion-foreign.rs
+++ b/tests/ui/check-static-recursion-foreign.rs
@@ -3,7 +3,6 @@
 // Static recursion check shouldn't fail when given a foreign item (#18279)
 
 //@ aux-build:check_static_recursion_foreign_helper.rs
-//@ ignore-wasm32-bare no libc to test ffi with
 
 //@ pretty-expanded FIXME #23616
 
diff --git a/tests/ui/closures/infer-signature-from-impl.next.stderr b/tests/ui/closures/infer-signature-from-impl.next.stderr
index 0866265cf04..332917eaaff 100644
--- a/tests/ui/closures/infer-signature-from-impl.next.stderr
+++ b/tests/ui/closures/infer-signature-from-impl.next.stderr
@@ -1,5 +1,5 @@
 error[E0282]: type annotations needed
-  --> $DIR/infer-signature-from-impl.rs:17:16
+  --> $DIR/infer-signature-from-impl.rs:18:16
    |
 LL |     needs_foo(|x| {
    |                ^
diff --git a/tests/ui/closures/infer-signature-from-impl.rs b/tests/ui/closures/infer-signature-from-impl.rs
index 910e004ba31..fa455c15ec7 100644
--- a/tests/ui/closures/infer-signature-from-impl.rs
+++ b/tests/ui/closures/infer-signature-from-impl.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@[next] known-bug: trait-system-refactor-initiative#71
 //@[current] check-pass
diff --git a/tests/ui/codegen/issue-27859.rs b/tests/ui/codegen/issue-27859.rs
index 4b4d2d28575..6f5263b0ace 100644
--- a/tests/ui/codegen/issue-27859.rs
+++ b/tests/ui/codegen/issue-27859.rs
@@ -1,5 +1,4 @@
 //@ run-pass
-//@ ignore-wasm32 issue 42629
 
 #[inline(never)]
 fn foo(a: f32, b: f32) -> f32 {
diff --git a/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.next.stderr b/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.next.stderr
new file mode 100644
index 00000000000..6e41561f1a7
--- /dev/null
+++ b/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.next.stderr
@@ -0,0 +1,9 @@
+error[E0284]: type annotations needed: cannot satisfy `<dyn Object<U, Output = T> as Object<U>>::Output == T`
+  --> $DIR/indirect-impl-for-trait-obj-coherence.rs:25:41
+   |
+LL |     foo::<dyn Object<U, Output = T>, U>(x)
+   |                                         ^ cannot satisfy `<dyn Object<U, Output = T> as Object<U>>::Output == T`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0284`.
diff --git a/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.rs b/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.rs
index 201a46a166a..0b66a6e7830 100644
--- a/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.rs
+++ b/tests/ui/coherence/indirect-impl-for-trait-obj-coherence.rs
@@ -1,5 +1,8 @@
-//@ check-pass
-//@ known-bug: #57893
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[current] check-pass
+//@[current] known-bug: #57893
 
 // Should fail. Because we see an impl that uses a certain associated type, we
 // type-check assuming that impl is used. However, this conflicts with the
@@ -20,6 +23,7 @@ fn foo<T: ?Sized, U>(x: <T as Object<U>>::Output) -> U {
 #[allow(dead_code)]
 fn transmute<T, U>(x: T) -> U {
     foo::<dyn Object<U, Output = T>, U>(x)
+    //[next]~^ ERROR type annotations needed: cannot satisfy `<dyn Object<U, Output = T> as Object<U>>::Output == T`
 }
 
 fn main() {}
diff --git a/tests/ui/coherence/normalize-for-errors.current.stderr b/tests/ui/coherence/normalize-for-errors.current.stderr
index 0e48aaed879..dcbb73bd1ff 100644
--- a/tests/ui/coherence/normalize-for-errors.current.stderr
+++ b/tests/ui/coherence/normalize-for-errors.current.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, _)`
-  --> $DIR/normalize-for-errors.rs:16:1
+  --> $DIR/normalize-for-errors.rs:17:1
    |
 LL | impl<T: Copy, S: Iterator> MyTrait<S> for (T, S::Item) {}
    | ------------------------------------------------------ first implementation here
diff --git a/tests/ui/coherence/normalize-for-errors.next.stderr b/tests/ui/coherence/normalize-for-errors.next.stderr
index a8a7d437b32..6c56a917741 100644
--- a/tests/ui/coherence/normalize-for-errors.next.stderr
+++ b/tests/ui/coherence/normalize-for-errors.next.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>, <_ as Iterator>::Item)`
-  --> $DIR/normalize-for-errors.rs:16:1
+  --> $DIR/normalize-for-errors.rs:17:1
    |
 LL | impl<T: Copy, S: Iterator> MyTrait<S> for (T, S::Item) {}
    | ------------------------------------------------------ first implementation here
diff --git a/tests/ui/coherence/normalize-for-errors.rs b/tests/ui/coherence/normalize-for-errors.rs
index 4d98ea609e9..2288118676a 100644
--- a/tests/ui/coherence/normalize-for-errors.rs
+++ b/tests/ui/coherence/normalize-for-errors.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 struct MyType;
diff --git a/tests/ui/command/command-argv0.rs b/tests/ui/command/command-argv0.rs
index 53649e35a89..35625c0b334 100644
--- a/tests/ui/command/command-argv0.rs
+++ b/tests/ui/command/command-argv0.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 
 //@ ignore-windows - this is a unix-specific test
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 use std::env;
 use std::os::unix::process::CommandExt;
diff --git a/tests/ui/command/command-current-dir.rs b/tests/ui/command/command-current-dir.rs
index 7186a165a96..95c16bce6e8 100644
--- a/tests/ui/command/command-current-dir.rs
+++ b/tests/ui/command/command-current-dir.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 //@ ignore-fuchsia Needs directory creation privilege
 
diff --git a/tests/ui/command/command-exec.rs b/tests/ui/command/command-exec.rs
index 3cc5d0bbd3e..c97b8561410 100644
--- a/tests/ui/command/command-exec.rs
+++ b/tests/ui/command/command-exec.rs
@@ -2,7 +2,7 @@
 
 #![allow(stable_features)]
 //@ ignore-windows - this is a unix-specific test
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 //@ ignore-fuchsia no execvp syscall provided
 
diff --git a/tests/ui/command/command-pre-exec.rs b/tests/ui/command/command-pre-exec.rs
index 2f3483fad08..7242dea2775 100644
--- a/tests/ui/command/command-pre-exec.rs
+++ b/tests/ui/command/command-pre-exec.rs
@@ -2,7 +2,7 @@
 
 #![allow(stable_features)]
 //@ ignore-windows - this is a unix-specific test
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 //@ ignore-fuchsia no execvp syscall
 #![feature(process_exec, rustc_private)]
diff --git a/tests/ui/command/command-setgroups.rs b/tests/ui/command/command-setgroups.rs
index f5dbf43feb5..c940135d844 100644
--- a/tests/ui/command/command-setgroups.rs
+++ b/tests/ui/command/command-setgroups.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 //@ ignore-windows - this is a unix-specific test
-//@ ignore-emscripten
+//@ ignore-wasm32
 //@ ignore-sgx
 //@ ignore-musl - returns dummy result for _SC_NGROUPS_MAX
 //@ ignore-nto - does not have `/bin/id`, expects groups to be i32 (not u32)
diff --git a/tests/ui/command/issue-10626.rs b/tests/ui/command/issue-10626.rs
index c63edb83700..f8dbb011513 100644
--- a/tests/ui/command/issue-10626.rs
+++ b/tests/ui/command/issue-10626.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 
 // Make sure that if a process doesn't have its stdio/stderr descriptors set up
diff --git a/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr b/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr
index bb6d650b7ab..bfb40c7e54f 100644
--- a/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/type_mismatch.stderr
@@ -22,6 +22,12 @@ LL | impl<const N: u64> Q for [u8; N] {}
    |      unsatisfied trait bound introduced here
 
 error[E0308]: mismatched types
+  --> $DIR/type_mismatch.rs:8:31
+   |
+LL | impl<const N: u64> Q for [u8; N] {}
+   |                               ^ expected `usize`, found `u64`
+
+error[E0308]: mismatched types
   --> $DIR/type_mismatch.rs:12:20
    |
 LL | pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {}
@@ -29,12 +35,6 @@ LL | pub fn q_user() -> [u8; <[u8; 13] as Q>::ASSOC] {}
    |        |
    |        implicitly returns `()` as its body has no tail or `return` expression
 
-error[E0308]: mismatched types
-  --> $DIR/type_mismatch.rs:8:31
-   |
-LL | impl<const N: u64> Q for [u8; N] {}
-   |                               ^ expected `usize`, found `u64`
-
 error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0046, E0308.
diff --git a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr
index 77a7da17c13..557530ebe3d 100644
--- a/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/unify-op-with-fn-call.stderr
@@ -34,14 +34,6 @@ LL + #[derive(ConstParamTy)]
 LL | struct Foo(u8);
    |
 
-error: unconstrained generic constant
-  --> $DIR/unify-op-with-fn-call.rs:30:12
-   |
-LL |     bar2::<{ std::ops::Add::add(N, N) }>();
-   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: try adding a `where` bound using this expression: `where [(); { std::ops::Add::add(N, N) }]:`
-
 error[E0015]: cannot call non-const operator in constants
   --> $DIR/unify-op-with-fn-call.rs:20:39
    |
@@ -65,6 +57,14 @@ LL |     bar::<{ std::ops::Add::add(N, N) }>();
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
    = help: add `#![feature(effects)]` to the crate attributes to enable
 
+error: unconstrained generic constant
+  --> $DIR/unify-op-with-fn-call.rs:30:12
+   |
+LL |     bar2::<{ std::ops::Add::add(N, N) }>();
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: try adding a `where` bound using this expression: `where [(); { std::ops::Add::add(N, N) }]:`
+
 error[E0015]: cannot call non-const fn `<usize as Add>::add` in constants
   --> $DIR/unify-op-with-fn-call.rs:30:14
    |
diff --git a/tests/ui/const-generics/transmute-fail.stderr b/tests/ui/const-generics/transmute-fail.stderr
index 12644b9f36d..9e308620a9c 100644
--- a/tests/ui/const-generics/transmute-fail.stderr
+++ b/tests/ui/const-generics/transmute-fail.stderr
@@ -16,6 +16,18 @@ LL |     std::mem::transmute(v)
    = note: source type: `[[u32; H]; W]` (this type does not have a fixed size)
    = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W])
 
+error[E0308]: mismatched types
+  --> $DIR/transmute-fail.rs:12:53
+   |
+LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
+   |                                                     ^ expected `usize`, found `bool`
+
+error[E0308]: mismatched types
+  --> $DIR/transmute-fail.rs:12:67
+   |
+LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
+   |                                                                   ^ expected `usize`, found `bool`
+
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
   --> $DIR/transmute-fail.rs:23:5
    |
@@ -34,18 +46,6 @@ LL |     std::mem::transmute(v)
    = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type `[[u32; 8888888]; 9999999]` are too big for the current architecture)
    = note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture)
 
-error[E0308]: mismatched types
-  --> $DIR/transmute-fail.rs:12:53
-   |
-LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
-   |                                                     ^ expected `usize`, found `bool`
-
-error[E0308]: mismatched types
-  --> $DIR/transmute-fail.rs:12:67
-   |
-LL | fn bar<const W: bool, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
-   |                                                                   ^ expected `usize`, found `bool`
-
 error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0308, E0512.
diff --git a/tests/ui/const-generics/type_mismatch.stderr b/tests/ui/const-generics/type_mismatch.stderr
index 07476ae76c6..394dd44d40d 100644
--- a/tests/ui/const-generics/type_mismatch.stderr
+++ b/tests/ui/const-generics/type_mismatch.stderr
@@ -11,6 +11,12 @@ LL | fn bar<const N: u8>() -> [u8; N] {}
    |        ^^^^^^^^^^^ required by this bound in `bar`
 
 error[E0308]: mismatched types
+  --> $DIR/type_mismatch.rs:2:11
+   |
+LL |     bar::<N>()
+   |           ^ expected `u8`, found `usize`
+
+error[E0308]: mismatched types
   --> $DIR/type_mismatch.rs:6:26
    |
 LL | fn bar<const N: u8>() -> [u8; N] {}
@@ -19,12 +25,6 @@ LL | fn bar<const N: u8>() -> [u8; N] {}
    |    implicitly returns `()` as its body has no tail or `return` expression
 
 error[E0308]: mismatched types
-  --> $DIR/type_mismatch.rs:2:11
-   |
-LL |     bar::<N>()
-   |           ^ expected `u8`, found `usize`
-
-error[E0308]: mismatched types
   --> $DIR/type_mismatch.rs:6:31
    |
 LL | fn bar<const N: u8>() -> [u8; N] {}
diff --git a/tests/ui/consts/enclosing-scope-rule.rs b/tests/ui/consts/enclosing-scope-rule.rs
new file mode 100644
index 00000000000..7041ad9af34
--- /dev/null
+++ b/tests/ui/consts/enclosing-scope-rule.rs
@@ -0,0 +1,16 @@
+//@build-pass
+// Some code that looks like it might be relying on promotion, but actually this is using the
+// enclosing-scope rule, meaning the reference is "extended" to outlive its block and live as long
+// as the surrounding block (which in this case is the entire program). There are multiple
+// allocations being interned at once.
+
+struct Gen<T>(T);
+impl<'a, T> Gen<&'a T> {
+    // Can't be promoted because `T` might not be `'static`.
+    const C: &'a [T] = &[];
+}
+
+// Can't be promoted because of `Drop`.
+const V: &Vec<i32> = &Vec::new();
+
+fn main() {}
diff --git a/tests/ui/consts/promote-not.rs b/tests/ui/consts/promote-not.rs
index 47a06e8a72b..9b16f32532a 100644
--- a/tests/ui/consts/promote-not.rs
+++ b/tests/ui/consts/promote-not.rs
@@ -3,6 +3,7 @@
 #![allow(unconditional_panic)]
 
 use std::cell::Cell;
+use std::mem::ManuallyDrop;
 
 // We do not promote mutable references.
 static mut TEST1: Option<&mut [i32]> = Some(&mut [1, 2, 3]); //~ ERROR temporary value dropped while borrowed
@@ -39,7 +40,16 @@ const TEST_INTERIOR_MUT: () = {
     let _val: &'static _ = &(Cell::new(1), 2).1; //~ ERROR temporary value dropped while borrowed
 };
 
-const TEST_DROP: String = String::new();
+// This gets accepted by the "outer scope" rule, not promotion.
+const TEST_DROP_OUTER_SCOPE: &String = &String::new();
+// To demonstrate that, we can rewrite it as follows. If this was promotion it would still work.
+const TEST_DROP_NOT_PROMOTE: &String = {
+    let x = &String::new(); //~ ERROR destructor of `String` cannot be evaluated at compile-time
+    // The "dropped while borrowed" error seems to be suppressed, but the key point is that this
+    // fails to compile.
+    x
+};
+
 
 fn main() {
     // We must not promote things with interior mutability. Not even if we "project it away".
@@ -58,6 +68,7 @@ fn main() {
     let _val: &'static _ = &([1,2,3][4]+1); //~ ERROR temporary value dropped while borrowed
 
     // No promotion of temporaries that need to be dropped.
+    const TEST_DROP: String = String::new();
     let _val: &'static _ = &TEST_DROP;
     //~^ ERROR temporary value dropped while borrowed
     let _val: &'static _ = &&TEST_DROP;
@@ -69,4 +80,12 @@ fn main() {
     let _val: &'static _ = &[&TEST_DROP; 1];
     //~^ ERROR temporary value dropped while borrowed
     //~| ERROR temporary value dropped while borrowed
+
+    // Make sure there is no value-based reasoning for unions.
+    union UnionWithCell {
+        f1: i32,
+        f2: ManuallyDrop<Cell<i32>>,
+    }
+    let x: &'static _ = &UnionWithCell { f1: 0 };
+    //~^ ERROR temporary value dropped while borrowed
 }
diff --git a/tests/ui/consts/promote-not.stderr b/tests/ui/consts/promote-not.stderr
index 67ac5922efd..07d4a135ed4 100644
--- a/tests/ui/consts/promote-not.stderr
+++ b/tests/ui/consts/promote-not.stderr
@@ -1,5 +1,5 @@
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:8:50
+  --> $DIR/promote-not.rs:9:50
    |
 LL | static mut TEST1: Option<&mut [i32]> = Some(&mut [1, 2, 3]);
    |                                        ----------^^^^^^^^^-
@@ -9,7 +9,7 @@ LL | static mut TEST1: Option<&mut [i32]> = Some(&mut [1, 2, 3]);
    |                                        using this value as a static requires that borrow lasts for `'static`
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:11:18
+  --> $DIR/promote-not.rs:12:18
    |
 LL |     let x = &mut [1,2,3];
    |                  ^^^^^^^ creates a temporary value which is freed while still in use
@@ -19,7 +19,7 @@ LL | };
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:33:29
+  --> $DIR/promote-not.rs:34:29
    |
 LL |     let _x: &'static i32 = &unsafe { U { x: 0 }.x };
    |             ------------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -29,7 +29,7 @@ LL | };
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:39:29
+  --> $DIR/promote-not.rs:40:29
    |
 LL |     let _val: &'static _ = &(Cell::new(1), 2).1;
    |               ----------    ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -38,8 +38,17 @@ LL |     let _val: &'static _ = &(Cell::new(1), 2).1;
 LL | };
    | - temporary value is freed at the end of this statement
 
+error[E0493]: destructor of `String` cannot be evaluated at compile-time
+  --> $DIR/promote-not.rs:47:14
+   |
+LL |     let x = &String::new();
+   |              ^^^^^^^^^^^^^ the destructor for this type cannot be evaluated in constants
+...
+LL | };
+   | - value is dropped here
+
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:20:32
+  --> $DIR/promote-not.rs:21:32
    |
 LL |         let _x: &'static () = &foo();
    |                 -----------    ^^^^^ creates a temporary value which is freed while still in use
@@ -49,7 +58,7 @@ LL |     }
    |     - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:28:29
+  --> $DIR/promote-not.rs:29:29
    |
 LL |     let _x: &'static i32 = &unsafe { U { x: 0 }.x };
    |             ------------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -59,7 +68,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:46:29
+  --> $DIR/promote-not.rs:56:29
    |
 LL |     let _val: &'static _ = &(Cell::new(1), 2).0;
    |               ----------    ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -70,7 +79,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:47:29
+  --> $DIR/promote-not.rs:57:29
    |
 LL |     let _val: &'static _ = &(Cell::new(1), 2).1;
    |               ----------    ^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -81,7 +90,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:50:29
+  --> $DIR/promote-not.rs:60:29
    |
 LL |     let _val: &'static _ = &(1/0);
    |               ----------    ^^^^^ creates a temporary value which is freed while still in use
@@ -92,7 +101,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:51:29
+  --> $DIR/promote-not.rs:61:29
    |
 LL |     let _val: &'static _ = &(1/(1-1));
    |               ----------    ^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -103,7 +112,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:52:29
+  --> $DIR/promote-not.rs:62:29
    |
 LL |     let _val: &'static _ = &((1+1)/(1-1));
    |               ----------    ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -114,7 +123,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:53:29
+  --> $DIR/promote-not.rs:63:29
    |
 LL |     let _val: &'static _ = &(i32::MIN/-1);
    |               ----------    ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -125,7 +134,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:54:29
+  --> $DIR/promote-not.rs:64:29
    |
 LL |     let _val: &'static _ = &(i32::MIN/(0-1));
    |               ----------    ^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -136,7 +145,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:55:29
+  --> $DIR/promote-not.rs:65:29
    |
 LL |     let _val: &'static _ = &(-128i8/-1);
    |               ----------    ^^^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -147,7 +156,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:56:29
+  --> $DIR/promote-not.rs:66:29
    |
 LL |     let _val: &'static _ = &(1%0);
    |               ----------    ^^^^^ creates a temporary value which is freed while still in use
@@ -158,7 +167,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:57:29
+  --> $DIR/promote-not.rs:67:29
    |
 LL |     let _val: &'static _ = &(1%(1-1));
    |               ----------    ^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -169,7 +178,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:58:29
+  --> $DIR/promote-not.rs:68:29
    |
 LL |     let _val: &'static _ = &([1,2,3][4]+1);
    |               ----------    ^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -180,7 +189,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:61:29
+  --> $DIR/promote-not.rs:72:29
    |
 LL |     let _val: &'static _ = &TEST_DROP;
    |               ----------    ^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -191,7 +200,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:63:29
+  --> $DIR/promote-not.rs:74:29
    |
 LL |     let _val: &'static _ = &&TEST_DROP;
    |               ----------    ^^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -202,7 +211,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:63:30
+  --> $DIR/promote-not.rs:74:30
    |
 LL |     let _val: &'static _ = &&TEST_DROP;
    |               ----------     ^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -213,7 +222,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:66:29
+  --> $DIR/promote-not.rs:77:29
    |
 LL |     let _val: &'static _ = &(&TEST_DROP,);
    |               ----------    ^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -224,7 +233,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:66:31
+  --> $DIR/promote-not.rs:77:31
    |
 LL |     let _val: &'static _ = &(&TEST_DROP,);
    |               ----------      ^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -235,7 +244,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:69:29
+  --> $DIR/promote-not.rs:80:29
    |
 LL |     let _val: &'static _ = &[&TEST_DROP; 1];
    |               ----------    ^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
@@ -246,7 +255,7 @@ LL | }
    | - temporary value is freed at the end of this statement
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/promote-not.rs:69:31
+  --> $DIR/promote-not.rs:80:31
    |
 LL |     let _val: &'static _ = &[&TEST_DROP; 1];
    |               ----------      ^^^^^^^^^    - temporary value is freed at the end of this statement
@@ -254,6 +263,18 @@ LL |     let _val: &'static _ = &[&TEST_DROP; 1];
    |               |               creates a temporary value which is freed while still in use
    |               type annotation requires that borrow lasts for `'static`
 
-error: aborting due to 24 previous errors
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promote-not.rs:89:26
+   |
+LL |     let x: &'static _ = &UnionWithCell { f1: 0 };
+   |            ----------    ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary value which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL |
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error: aborting due to 26 previous errors
 
-For more information about this error, try `rustc --explain E0716`.
+Some errors have detailed explanations: E0493, E0716.
+For more information about an error, try `rustc --explain E0493`.
diff --git a/tests/ui/consts/refs-to-cell-in-final.rs b/tests/ui/consts/refs-to-cell-in-final.rs
index 6a849ff0df9..ada56a82a5d 100644
--- a/tests/ui/consts/refs-to-cell-in-final.rs
+++ b/tests/ui/consts/refs-to-cell-in-final.rs
@@ -15,4 +15,27 @@ static RAW_SYNC_S: SyncPtr<Cell<i32>> = SyncPtr { x: &Cell::new(42) };
 const RAW_SYNC_C: SyncPtr<Cell<i32>> = SyncPtr { x: &Cell::new(42) };
 //~^ ERROR: cannot refer to interior mutable data
 
+// This one does not get promoted because of `Drop`, and then enters interesting codepaths because
+// as a value it has no interior mutability, but as a type it does. See
+// <https://github.com/rust-lang/rust/issues/121610>. Value-based reasoning for interior mutability
+// is questionable (https://github.com/rust-lang/unsafe-code-guidelines/issues/493) so for now we
+// reject this, though not with a great error message.
+pub enum JsValue {
+    Undefined,
+    Object(Cell<bool>),
+}
+impl Drop for JsValue {
+    fn drop(&mut self) {}
+}
+const UNDEFINED: &JsValue = &JsValue::Undefined;
+//~^ERROR: mutable pointer in final value of constant
+
+// In contrast, this one works since it is being promoted.
+const NONE: &'static Option<Cell<i32>> = &None;
+// Making it clear that this is promotion, not "outer scope".
+const NONE_EXPLICIT_PROMOTED: &'static Option<Cell<i32>> = {
+    let x = &None;
+    x
+};
+
 fn main() {}
diff --git a/tests/ui/consts/refs-to-cell-in-final.stderr b/tests/ui/consts/refs-to-cell-in-final.stderr
index fae16fa0125..b06db3e116c 100644
--- a/tests/ui/consts/refs-to-cell-in-final.stderr
+++ b/tests/ui/consts/refs-to-cell-in-final.stderr
@@ -12,6 +12,12 @@ error[E0492]: constants cannot refer to interior mutable data
 LL | const RAW_SYNC_C: SyncPtr<Cell<i32>> = SyncPtr { x: &Cell::new(42) };
    |                                                     ^^^^^^^^^^^^^^ this borrow of an interior mutable value may end up in the final value
 
-error: aborting due to 2 previous errors
+error: encountered mutable pointer in final value of constant
+  --> $DIR/refs-to-cell-in-final.rs:30:1
+   |
+LL | const UNDEFINED: &JsValue = &JsValue::Undefined;
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0492`.
diff --git a/tests/ui/consts/trait_specialization.rs b/tests/ui/consts/trait_specialization.rs
index f195e067b55..1360fabd1fe 100644
--- a/tests/ui/consts/trait_specialization.rs
+++ b/tests/ui/consts/trait_specialization.rs
@@ -1,4 +1,3 @@
-//@ ignore-wasm32-bare which doesn't support `std::process:exit()`
 //@ compile-flags: -Zmir-opt-level=3
 //@ run-pass
 
diff --git a/tests/ui/consts/trait_specialization.stderr b/tests/ui/consts/trait_specialization.stderr
index 10bebe8ebc5..ce52cf17b89 100644
--- a/tests/ui/consts/trait_specialization.stderr
+++ b/tests/ui/consts/trait_specialization.stderr
@@ -1,5 +1,5 @@
 warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/trait_specialization.rs:8:12
+  --> $DIR/trait_specialization.rs:7:12
    |
 LL | #![feature(specialization)]
    |            ^^^^^^^^^^^^^^
diff --git a/tests/ui/coroutine/clone-rpit.next.stderr b/tests/ui/coroutine/clone-rpit.next.stderr
index 2dbdbcc7b05..02d3390496a 100644
--- a/tests/ui/coroutine/clone-rpit.next.stderr
+++ b/tests/ui/coroutine/clone-rpit.next.stderr
@@ -1,47 +1,47 @@
 error[E0391]: cycle detected when type-checking `foo`
-  --> $DIR/clone-rpit.rs:12:1
+  --> $DIR/clone-rpit.rs:13:1
    |
 LL | pub fn foo<'a, 'b>() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: ...which requires coroutine witness types for `foo::{closure#0}`...
-  --> $DIR/clone-rpit.rs:13:5
+  --> $DIR/clone-rpit.rs:14:5
    |
 LL |     move |_: ()| {
    |     ^^^^^^^^^^^^
 note: ...which requires promoting constants in MIR for `foo::{closure#0}`...
-  --> $DIR/clone-rpit.rs:13:5
+  --> $DIR/clone-rpit.rs:14:5
    |
 LL |     move |_: ()| {
    |     ^^^^^^^^^^^^
 note: ...which requires preparing `foo::{closure#0}` for borrow checking...
-  --> $DIR/clone-rpit.rs:13:5
+  --> $DIR/clone-rpit.rs:14:5
    |
 LL |     move |_: ()| {
    |     ^^^^^^^^^^^^
 note: ...which requires checking if `foo::{closure#0}` contains FFI-unwind calls...
-  --> $DIR/clone-rpit.rs:13:5
+  --> $DIR/clone-rpit.rs:14:5
    |
 LL |     move |_: ()| {
    |     ^^^^^^^^^^^^
 note: ...which requires building MIR for `foo::{closure#0}`...
-  --> $DIR/clone-rpit.rs:13:5
+  --> $DIR/clone-rpit.rs:14:5
    |
 LL |     move |_: ()| {
    |     ^^^^^^^^^^^^
 note: ...which requires match-checking `foo::{closure#0}`...
-  --> $DIR/clone-rpit.rs:13:5
+  --> $DIR/clone-rpit.rs:14:5
    |
 LL |     move |_: ()| {
    |     ^^^^^^^^^^^^
 note: ...which requires type-checking `foo::{closure#0}`...
-  --> $DIR/clone-rpit.rs:13:5
+  --> $DIR/clone-rpit.rs:14:5
    |
 LL |     move |_: ()| {
    |     ^^^^^^^^^^^^
    = note: ...which again requires type-checking `foo`, completing the cycle
 note: cycle used when computing type of opaque `foo::{opaque#0}`
-  --> $DIR/clone-rpit.rs:12:25
+  --> $DIR/clone-rpit.rs:13:25
    |
 LL | pub fn foo<'a, 'b>() -> impl Clone {
    |                         ^^^^^^^^^^
diff --git a/tests/ui/coroutine/clone-rpit.rs b/tests/ui/coroutine/clone-rpit.rs
index 445d155afa9..0df9bf61601 100644
--- a/tests/ui/coroutine/clone-rpit.rs
+++ b/tests/ui/coroutine/clone-rpit.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@[current] check-pass
 //@[next] known-bug: trait-system-refactor-initiative#82
diff --git a/tests/ui/coroutine/non-static-is-unpin.rs b/tests/ui/coroutine/non-static-is-unpin.rs
index 0a108d52897..616a78d5fe2 100644
--- a/tests/ui/coroutine/non-static-is-unpin.rs
+++ b/tests/ui/coroutine/non-static-is-unpin.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@ run-pass
 
diff --git a/tests/ui/coroutine/size-moved-locals.rs b/tests/ui/coroutine/size-moved-locals.rs
index 84cc4319070..eb5210087a0 100644
--- a/tests/ui/coroutine/size-moved-locals.rs
+++ b/tests/ui/coroutine/size-moved-locals.rs
@@ -10,7 +10,6 @@
 // See issue #59123 for a full explanation.
 
 //@ edition:2018
-//@ ignore-wasm32 issue #62807
 //@ needs-unwind Size of Closures change on panic=abort
 
 #![feature(coroutines, coroutine_trait)]
diff --git a/tests/ui/coroutine/static-not-unpin.current.stderr b/tests/ui/coroutine/static-not-unpin.current.stderr
index 8ef54298431..518abdd62c7 100644
--- a/tests/ui/coroutine/static-not-unpin.current.stderr
+++ b/tests/ui/coroutine/static-not-unpin.current.stderr
@@ -1,15 +1,15 @@
-error[E0277]: `{static coroutine@$DIR/static-not-unpin.rs:14:25: 14:34}` cannot be unpinned
-  --> $DIR/static-not-unpin.rs:17:18
+error[E0277]: `{static coroutine@$DIR/static-not-unpin.rs:15:25: 15:34}` cannot be unpinned
+  --> $DIR/static-not-unpin.rs:18:18
    |
 LL |     assert_unpin(coroutine);
-   |     ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `{static coroutine@$DIR/static-not-unpin.rs:14:25: 14:34}`
+   |     ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `{static coroutine@$DIR/static-not-unpin.rs:15:25: 15:34}`
    |     |
    |     required by a bound introduced by this call
    |
    = note: consider using the `pin!` macro
            consider using `Box::pin` if you need to access the pinned value outside of the current scope
 note: required by a bound in `assert_unpin`
-  --> $DIR/static-not-unpin.rs:10:20
+  --> $DIR/static-not-unpin.rs:11:20
    |
 LL | fn assert_unpin<T: Unpin>(_: T) {
    |                    ^^^^^ required by this bound in `assert_unpin`
diff --git a/tests/ui/coroutine/static-not-unpin.next.stderr b/tests/ui/coroutine/static-not-unpin.next.stderr
index 8ef54298431..518abdd62c7 100644
--- a/tests/ui/coroutine/static-not-unpin.next.stderr
+++ b/tests/ui/coroutine/static-not-unpin.next.stderr
@@ -1,15 +1,15 @@
-error[E0277]: `{static coroutine@$DIR/static-not-unpin.rs:14:25: 14:34}` cannot be unpinned
-  --> $DIR/static-not-unpin.rs:17:18
+error[E0277]: `{static coroutine@$DIR/static-not-unpin.rs:15:25: 15:34}` cannot be unpinned
+  --> $DIR/static-not-unpin.rs:18:18
    |
 LL |     assert_unpin(coroutine);
-   |     ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `{static coroutine@$DIR/static-not-unpin.rs:14:25: 14:34}`
+   |     ------------ ^^^^^^^^^ the trait `Unpin` is not implemented for `{static coroutine@$DIR/static-not-unpin.rs:15:25: 15:34}`
    |     |
    |     required by a bound introduced by this call
    |
    = note: consider using the `pin!` macro
            consider using `Box::pin` if you need to access the pinned value outside of the current scope
 note: required by a bound in `assert_unpin`
-  --> $DIR/static-not-unpin.rs:10:20
+  --> $DIR/static-not-unpin.rs:11:20
    |
 LL | fn assert_unpin<T: Unpin>(_: T) {
    |                    ^^^^^ required by this bound in `assert_unpin`
diff --git a/tests/ui/coroutine/static-not-unpin.rs b/tests/ui/coroutine/static-not-unpin.rs
index 63a2b35ef7a..3704cca7729 100644
--- a/tests/ui/coroutine/static-not-unpin.rs
+++ b/tests/ui/coroutine/static-not-unpin.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 #![feature(coroutines)]
diff --git a/tests/ui/duplicate/dupe-symbols-7.rs b/tests/ui/duplicate/dupe-symbols-7.rs
index 2c75a5ffe6d..162c3c40446 100644
--- a/tests/ui/duplicate/dupe-symbols-7.rs
+++ b/tests/ui/duplicate/dupe-symbols-7.rs
@@ -1,4 +1,5 @@
 //@ build-fail
+//@ ignore-wasi wasi does different things with the `main` symbol
 
 //
 //@ error-pattern: entry symbol `main` declared multiple times
diff --git a/tests/ui/duplicate/dupe-symbols-7.stderr b/tests/ui/duplicate/dupe-symbols-7.stderr
index 23f74ef7509..ab9167e005a 100644
--- a/tests/ui/duplicate/dupe-symbols-7.stderr
+++ b/tests/ui/duplicate/dupe-symbols-7.stderr
@@ -1,5 +1,5 @@
 error: entry symbol `main` declared multiple times
-  --> $DIR/dupe-symbols-7.rs:9:1
+  --> $DIR/dupe-symbols-7.rs:10:1
    |
 LL | fn main(){}
    | ^^^^^^^^^
diff --git a/tests/ui/duplicate/dupe-symbols-8.rs b/tests/ui/duplicate/dupe-symbols-8.rs
index fc0b1037777..258e91fa8c8 100644
--- a/tests/ui/duplicate/dupe-symbols-8.rs
+++ b/tests/ui/duplicate/dupe-symbols-8.rs
@@ -1,5 +1,6 @@
 //@ build-fail
 //@ error-pattern: entry symbol `main` declared multiple times
+//@ ignore-wasi wasi does different things with the `main` symbol
 //
 // See #67946.
 
diff --git a/tests/ui/duplicate/dupe-symbols-8.stderr b/tests/ui/duplicate/dupe-symbols-8.stderr
index 67eb0bc71a9..d7d419c9aa4 100644
--- a/tests/ui/duplicate/dupe-symbols-8.stderr
+++ b/tests/ui/duplicate/dupe-symbols-8.stderr
@@ -1,5 +1,5 @@
 error: entry symbol `main` declared multiple times
-  --> $DIR/dupe-symbols-8.rs:7:1
+  --> $DIR/dupe-symbols-8.rs:8:1
    |
 LL | fn main() {
    | ^^^^^^^^^
diff --git a/tests/ui/dyn-star/box.rs b/tests/ui/dyn-star/box.rs
index a7e8e81b654..f1c9fd1a01e 100644
--- a/tests/ui/dyn-star/box.rs
+++ b/tests/ui/dyn-star/box.rs
@@ -1,5 +1,6 @@
 //@ run-pass
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[current] compile-flags: -C opt-level=0
 //@[next] compile-flags: -Znext-solver -C opt-level=0
 
diff --git a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.current.stderr b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.current.stderr
index f291b1e2ca3..7b5ea7bb707 100644
--- a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.current.stderr
+++ b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.current.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `&T` needs to have the same ABI as a pointer
-  --> $DIR/check-size-at-cast-polymorphic-bad.rs:14:15
+  --> $DIR/check-size-at-cast-polymorphic-bad.rs:15:15
    |
 LL |     dyn_debug(t);
    |               ^ `&T` needs to be a pointer-like type
diff --git a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.next.stderr b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.next.stderr
index f291b1e2ca3..7b5ea7bb707 100644
--- a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.next.stderr
+++ b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.next.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `&T` needs to have the same ABI as a pointer
-  --> $DIR/check-size-at-cast-polymorphic-bad.rs:14:15
+  --> $DIR/check-size-at-cast-polymorphic-bad.rs:15:15
    |
 LL |     dyn_debug(t);
    |               ^ `&T` needs to be a pointer-like type
diff --git a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs
index ad3391a7ad7..acc293a5956 100644
--- a/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs
+++ b/tests/ui/dyn-star/check-size-at-cast-polymorphic-bad.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 #![feature(dyn_star)]
diff --git a/tests/ui/dyn-star/thin.next.stderr b/tests/ui/dyn-star/thin.next.stderr
new file mode 100644
index 00000000000..ef251062afc
--- /dev/null
+++ b/tests/ui/dyn-star/thin.next.stderr
@@ -0,0 +1,11 @@
+warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/thin.rs:6:12
+   |
+LL | #![feature(dyn_star)]
+   |            ^^^^^^^^
+   |
+   = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/dyn-star/thin.old.stderr b/tests/ui/dyn-star/thin.old.stderr
new file mode 100644
index 00000000000..ef251062afc
--- /dev/null
+++ b/tests/ui/dyn-star/thin.old.stderr
@@ -0,0 +1,11 @@
+warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/thin.rs:6:12
+   |
+LL | #![feature(dyn_star)]
+   |            ^^^^^^^^
+   |
+   = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/dyn-star/thin.rs b/tests/ui/dyn-star/thin.rs
new file mode 100644
index 00000000000..6df70f560de
--- /dev/null
+++ b/tests/ui/dyn-star/thin.rs
@@ -0,0 +1,16 @@
+//@check-pass
+//@revisions: old next
+//@[next] compile-flags: -Znext-solver
+
+#![feature(ptr_metadata)]
+#![feature(dyn_star)]
+//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
+
+use std::fmt::Debug;
+use std::ptr::Thin;
+
+fn check_thin<T: ?Sized + Thin>() {}
+
+fn main() {
+    check_thin::<dyn* Debug>();
+}
diff --git a/tests/ui/env-args-reverse-iterator.rs b/tests/ui/env-args-reverse-iterator.rs
index 4971d2b30e7..830e9535466 100644
--- a/tests/ui/env-args-reverse-iterator.rs
+++ b/tests/ui/env-args-reverse-iterator.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 
 use std::env::args;
diff --git a/tests/ui/env-funky-keys.rs b/tests/ui/env-funky-keys.rs
index ac6da1fefae..314ccaea015 100644
--- a/tests/ui/env-funky-keys.rs
+++ b/tests/ui/env-funky-keys.rs
@@ -3,7 +3,7 @@
 
 //@ ignore-android
 //@ ignore-windows
-//@ ignore-emscripten no execve
+//@ ignore-wasm32 no execve
 //@ ignore-sgx no execve
 //@ ignore-vxworks no execve
 //@ ignore-fuchsia no 'execve'
diff --git a/tests/ui/env-null-vars.rs b/tests/ui/env-null-vars.rs
index 55fe8ac25ca..bb86fd353c4 100644
--- a/tests/ui/env-null-vars.rs
+++ b/tests/ui/env-null-vars.rs
@@ -3,7 +3,6 @@
 #![allow(unused_imports)]
 
 //@ ignore-windows
-//@ ignore-wasm32-bare no libc to test ffi with
 
 // issue-53200
 
diff --git a/tests/ui/env-vars.rs b/tests/ui/env-vars.rs
index 5ca1b80f235..73068b5dfb8 100644
--- a/tests/ui/env-vars.rs
+++ b/tests/ui/env-vars.rs
@@ -1,5 +1,4 @@
 //@ run-pass
-//@ ignore-wasm32-bare no env vars
 
 use std::env::*;
 
diff --git a/tests/ui/exec-env.rs b/tests/ui/exec-env.rs
index 08c5aa86467..9054b378f56 100644
--- a/tests/ui/exec-env.rs
+++ b/tests/ui/exec-env.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 //@ exec-env:TEST_EXEC_ENV=22
-//@ ignore-emscripten FIXME: issue #31622
+//@ ignore-wasm32 wasm runtimes aren't configured to inherit env vars yet
 //@ ignore-sgx unsupported
 
 use std::env;
diff --git a/tests/ui/explicit-tail-calls/return-mismatches.stderr b/tests/ui/explicit-tail-calls/return-mismatches.stderr
index 31c7a46ded9..147cec499e8 100644
--- a/tests/ui/explicit-tail-calls/return-mismatches.stderr
+++ b/tests/ui/explicit-tail-calls/return-mismatches.stderr
@@ -16,12 +16,6 @@ LL |     become _g1();
    = note: expected unit type `()`
                    found type `!`
 
-error[E0308]: mismatched types
-  --> $DIR/return-mismatches.rs:21:5
-   |
-LL |     become _g2();
-   |     ^^^^^^^^^^^^ expected `u32`, found `u16`
-
 warning: function cannot return without recursing
   --> $DIR/return-mismatches.rs:16:1
    |
@@ -33,6 +27,12 @@ LL |     become _g1();
    = help: a `loop` may express intention better if this is on purpose
    = note: `#[warn(unconditional_recursion)]` on by default
 
+error[E0308]: mismatched types
+  --> $DIR/return-mismatches.rs:21:5
+   |
+LL |     become _g2();
+   |     ^^^^^^^^^^^^ expected `u32`, found `u16`
+
 error: aborting due to 3 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/expr/if/if-no-match-bindings.stderr b/tests/ui/expr/if/if-no-match-bindings.stderr
index 18f3b6b168e..34ba126d9a7 100644
--- a/tests/ui/expr/if/if-no-match-bindings.stderr
+++ b/tests/ui/expr/if/if-no-match-bindings.stderr
@@ -1,3 +1,12 @@
+error[E0515]: cannot return reference to temporary value
+  --> $DIR/if-no-match-bindings.rs:8:38
+   |
+LL | fn b_mut_ref<'a>() -> &'a mut bool { &mut true }
+   |                                      ^^^^^----
+   |                                      |    |
+   |                                      |    temporary value created here
+   |                                      returns a reference to data owned by the current function
+
 error[E0308]: mismatched types
   --> $DIR/if-no-match-bindings.rs:19:8
    |
@@ -90,15 +99,6 @@ LL -     while &mut true {}
 LL +     while true {}
    |
 
-error[E0515]: cannot return reference to temporary value
-  --> $DIR/if-no-match-bindings.rs:8:38
-   |
-LL | fn b_mut_ref<'a>() -> &'a mut bool { &mut true }
-   |                                      ^^^^^----
-   |                                      |    |
-   |                                      |    temporary value created here
-   |                                      returns a reference to data owned by the current function
-
 error: aborting due to 9 previous errors
 
 Some errors have detailed explanations: E0308, E0515.
diff --git a/tests/ui/extern/extern-const.fixed b/tests/ui/extern/extern-const.fixed
index b338a56dd78..9f695eaafd0 100644
--- a/tests/ui/extern/extern-const.fixed
+++ b/tests/ui/extern/extern-const.fixed
@@ -5,7 +5,6 @@
 // compile. To sidestep this by using one that *is* defined.
 
 //@ run-rustfix
-//@ ignore-wasm32-bare no external library to link to.
 //@ compile-flags: -g
 #![feature(rustc_private)]
 extern crate libc;
diff --git a/tests/ui/extern/extern-const.rs b/tests/ui/extern/extern-const.rs
index 1c552950afb..e412dff8895 100644
--- a/tests/ui/extern/extern-const.rs
+++ b/tests/ui/extern/extern-const.rs
@@ -5,7 +5,6 @@
 // compile. To sidestep this by using one that *is* defined.
 
 //@ run-rustfix
-//@ ignore-wasm32-bare no external library to link to.
 //@ compile-flags: -g
 #![feature(rustc_private)]
 extern crate libc;
diff --git a/tests/ui/extern/extern-const.stderr b/tests/ui/extern/extern-const.stderr
index 4c2c3d6e0a8..07485cf9994 100644
--- a/tests/ui/extern/extern-const.stderr
+++ b/tests/ui/extern/extern-const.stderr
@@ -1,5 +1,5 @@
 error: extern items cannot be `const`
-  --> $DIR/extern-const.rs:15:11
+  --> $DIR/extern-const.rs:14:11
    |
 LL |     const rust_dbg_static_mut: libc::c_int;
    |     ------^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/extern/issue-1251.rs b/tests/ui/extern/issue-1251.rs
index bf701a41f94..da2b8be7bc1 100644
--- a/tests/ui/extern/issue-1251.rs
+++ b/tests/ui/extern/issue-1251.rs
@@ -2,7 +2,6 @@
 #![allow(unused_attributes)]
 #![allow(dead_code)]
 //@ pretty-expanded FIXME #23616
-//@ ignore-wasm32-bare no libc to test ffi with
 #![feature(rustc_private)]
 
 mod rustrt {
diff --git a/tests/ui/feature-gates/feature-gate-freeze-impls.rs b/tests/ui/feature-gates/feature-gate-freeze-impls.rs
new file mode 100644
index 00000000000..c14c9494874
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-freeze-impls.rs
@@ -0,0 +1,15 @@
+#![feature(freeze, negative_impls)]
+
+use std::marker::Freeze;
+
+struct Foo;
+
+unsafe impl Freeze for Foo {}
+//~^ explicit impls for the `Freeze` trait are not permitted
+
+struct Bar;
+
+impl !Freeze for Bar {}
+//~^ explicit impls for the `Freeze` trait are not permitted
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-freeze-impls.stderr b/tests/ui/feature-gates/feature-gate-freeze-impls.stderr
new file mode 100644
index 00000000000..eef524fe78e
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-freeze-impls.stderr
@@ -0,0 +1,23 @@
+error[E0658]: explicit impls for the `Freeze` trait are not permitted
+  --> $DIR/feature-gate-freeze-impls.rs:7:1
+   |
+LL | unsafe impl Freeze for Foo {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Freeze` not allowed
+   |
+   = note: see issue #121675 <https://github.com/rust-lang/rust/issues/121675> for more information
+   = help: add `#![feature(freeze_impls)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: explicit impls for the `Freeze` trait are not permitted
+  --> $DIR/feature-gate-freeze-impls.rs:12:1
+   |
+LL | impl !Freeze for Bar {}
+   | ^^^^^^^^^^^^^^^^^^^^ impl of `Freeze` not allowed
+   |
+   = note: see issue #121675 <https://github.com/rust-lang/rust/issues/121675> for more information
+   = help: add `#![feature(freeze_impls)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/for/issue-20605.current.stderr b/tests/ui/for/issue-20605.current.stderr
index 9e706601ef5..1a66cb41464 100644
--- a/tests/ui/for/issue-20605.current.stderr
+++ b/tests/ui/for/issue-20605.current.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `dyn Iterator<Item = &'a mut u8>` is not an iterator
-  --> $DIR/issue-20605.rs:5:17
+  --> $DIR/issue-20605.rs:6:17
    |
 LL |     for item in *things { *item = 0 }
    |                 ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator<Item = &'a mut u8>`
diff --git a/tests/ui/for/issue-20605.next.stderr b/tests/ui/for/issue-20605.next.stderr
index f9c3848476c..0669999cb82 100644
--- a/tests/ui/for/issue-20605.next.stderr
+++ b/tests/ui/for/issue-20605.next.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `dyn Iterator<Item = &'a mut u8>` is not an iterator
-  --> $DIR/issue-20605.rs:5:17
+  --> $DIR/issue-20605.rs:6:17
    |
 LL |     for item in *things { *item = 0 }
    |                 ^^^^^^^ `dyn Iterator<Item = &'a mut u8>` is not an iterator
@@ -7,25 +7,25 @@ LL |     for item in *things { *item = 0 }
    = help: the trait `IntoIterator` is not implemented for `dyn Iterator<Item = &'a mut u8>`
 
 error: the type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
-  --> $DIR/issue-20605.rs:5:17
+  --> $DIR/issue-20605.rs:6:17
    |
 LL |     for item in *things { *item = 0 }
    |                 ^^^^^^^
 
 error: the type `&mut <dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter` is not well-formed
-  --> $DIR/issue-20605.rs:5:17
+  --> $DIR/issue-20605.rs:6:17
    |
 LL |     for item in *things { *item = 0 }
    |                 ^^^^^^^
 
 error: the type `Option<<<dyn Iterator<Item = &'a mut u8> as IntoIterator>::IntoIter as Iterator>::Item>` is not well-formed
-  --> $DIR/issue-20605.rs:5:17
+  --> $DIR/issue-20605.rs:6:17
    |
 LL |     for item in *things { *item = 0 }
    |                 ^^^^^^^
 
 error[E0614]: type `<dyn Iterator<Item = &'a mut u8> as IntoIterator>::Item` cannot be dereferenced
-  --> $DIR/issue-20605.rs:5:27
+  --> $DIR/issue-20605.rs:6:27
    |
 LL |     for item in *things { *item = 0 }
    |                           ^^^^^
diff --git a/tests/ui/for/issue-20605.rs b/tests/ui/for/issue-20605.rs
index 1c01de967cc..b923a7088fe 100644
--- a/tests/ui/for/issue-20605.rs
+++ b/tests/ui/for/issue-20605.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 fn changer<'a>(mut things: Box<dyn Iterator<Item=&'a mut u8>>) {
diff --git a/tests/ui/foreign/foreign-fn-linkname.rs b/tests/ui/foreign/foreign-fn-linkname.rs
index 42876937a83..47edf6fc7bb 100644
--- a/tests/ui/foreign/foreign-fn-linkname.rs
+++ b/tests/ui/foreign/foreign-fn-linkname.rs
@@ -1,5 +1,4 @@
 //@ run-pass
-//@ ignore-wasm32-bare no libc to test ffi with
 //@ ignore-sgx no libc
 
 // Ensure no false positive on "unused extern crate" lint
diff --git a/tests/ui/foreign/foreign2.rs b/tests/ui/foreign/foreign2.rs
index 9379a0b4bd6..eb24df35033 100644
--- a/tests/ui/foreign/foreign2.rs
+++ b/tests/ui/foreign/foreign2.rs
@@ -1,6 +1,5 @@
 //@ run-pass
 #![allow(dead_code)]
-//@ ignore-wasm32-bare no libc to test ffi with
 //@ pretty-expanded FIXME #23616
 #![feature(rustc_private)]
 
diff --git a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.stderr b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.current.stderr
index 314a5509da8..2097115af00 100644
--- a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.stderr
+++ b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.current.stderr
@@ -1,16 +1,16 @@
 error[E0277]: the trait bound `<Self as Foo>::Bar<()>: Eq<i32>` is not satisfied
-  --> $DIR/assume-gat-normalization-for-nested-goals.rs:6:30
+  --> $DIR/assume-gat-normalization-for-nested-goals.rs:10:30
    |
 LL |     type Bar<T>: Baz<Self> = i32;
    |                              ^^^ the trait `Eq<i32>` is not implemented for `<Self as Foo>::Bar<()>`, which is required by `i32: Baz<Self>`
    |
 note: required for `i32` to implement `Baz<Self>`
-  --> $DIR/assume-gat-normalization-for-nested-goals.rs:13:23
+  --> $DIR/assume-gat-normalization-for-nested-goals.rs:17:23
    |
 LL | impl<T: Foo + ?Sized> Baz<T> for i32 where T::Bar<()>: Eq<i32> {}
    |                       ^^^^^^     ^^^                   ------- unsatisfied trait bound introduced here
 note: required by a bound in `Foo::Bar`
-  --> $DIR/assume-gat-normalization-for-nested-goals.rs:6:18
+  --> $DIR/assume-gat-normalization-for-nested-goals.rs:10:18
    |
 LL |     type Bar<T>: Baz<Self> = i32;
    |                  ^^^^^^^^^ required by this bound in `Foo::Bar`
diff --git a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.rs b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.rs
index fade3c441ab..56b50594e52 100644
--- a/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.rs
+++ b/tests/ui/generic-associated-types/assume-gat-normalization-for-nested-goals.rs
@@ -1,4 +1,8 @@
-//@ known-bug: #117606
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[current] known-bug: #117606
+//@[next] check-pass
 
 #![feature(associated_type_defaults)]
 
diff --git a/tests/ui/generic-associated-types/issue-102114.current.stderr b/tests/ui/generic-associated-types/issue-102114.current.stderr
index 69ae5676ee0..03471d08d74 100644
--- a/tests/ui/generic-associated-types/issue-102114.current.stderr
+++ b/tests/ui/generic-associated-types/issue-102114.current.stderr
@@ -1,5 +1,5 @@
 error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters
-  --> $DIR/issue-102114.rs:14:12
+  --> $DIR/issue-102114.rs:15:12
    |
 LL |     type B<'b>;
    |            -- expected 0 type parameters
diff --git a/tests/ui/generic-associated-types/issue-102114.next.stderr b/tests/ui/generic-associated-types/issue-102114.next.stderr
index 69ae5676ee0..03471d08d74 100644
--- a/tests/ui/generic-associated-types/issue-102114.next.stderr
+++ b/tests/ui/generic-associated-types/issue-102114.next.stderr
@@ -1,5 +1,5 @@
 error[E0049]: type `B` has 1 type parameter but its trait declaration has 0 type parameters
-  --> $DIR/issue-102114.rs:14:12
+  --> $DIR/issue-102114.rs:15:12
    |
 LL |     type B<'b>;
    |            -- expected 0 type parameters
diff --git a/tests/ui/generic-associated-types/issue-102114.rs b/tests/ui/generic-associated-types/issue-102114.rs
index 58518f3f59a..3d63e5c8aca 100644
--- a/tests/ui/generic-associated-types/issue-102114.rs
+++ b/tests/ui/generic-associated-types/issue-102114.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 trait A {
diff --git a/tests/ui/generic-associated-types/issue-74684-2.stderr b/tests/ui/generic-associated-types/issue-74684-2.stderr
index d39513ec523..7b295c7bd45 100644
--- a/tests/ui/generic-associated-types/issue-74684-2.stderr
+++ b/tests/ui/generic-associated-types/issue-74684-2.stderr
@@ -1,3 +1,19 @@
+error[E0597]: `a` does not live long enough
+  --> $DIR/issue-74684-2.rs:13:25
+   |
+LL | fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(t: Box<T>) -> &'static T::F<'a> {
+   |        -- lifetime `'a` defined here
+LL |     let a = [0; 1];
+   |         - binding `a` declared here
+LL |     let x = T::identity(&a);
+   |             ------------^^-
+   |             |           |
+   |             |           borrowed value does not live long enough
+   |             argument requires that `a` is borrowed for `'a`
+LL |     todo!()
+LL | }
+   | - `a` dropped here while still borrowed
+
 error[E0271]: type mismatch resolving `<{integer} as Fun>::F<'_> == [u8]`
   --> $DIR/issue-74684-2.rs:21:9
    |
@@ -17,22 +33,6 @@ note: required by a bound in `bug`
 LL | fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(t: Box<T>) -> &'static T::F<'a> {
    |                            ^^^^^^^^^^^^ required by this bound in `bug`
 
-error[E0597]: `a` does not live long enough
-  --> $DIR/issue-74684-2.rs:13:25
-   |
-LL | fn bug<'a, T: ?Sized + Fun<F<'a> = [u8]>>(t: Box<T>) -> &'static T::F<'a> {
-   |        -- lifetime `'a` defined here
-LL |     let a = [0; 1];
-   |         - binding `a` declared here
-LL |     let x = T::identity(&a);
-   |             ------------^^-
-   |             |           |
-   |             |           borrowed value does not live long enough
-   |             argument requires that `a` is borrowed for `'a`
-LL |     todo!()
-LL | }
-   | - `a` dropped here while still borrowed
-
 error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0271, E0597.
diff --git a/tests/ui/generic-associated-types/issue-88595.rs b/tests/ui/generic-associated-types/issue-88595.rs
index 5a40a612972..b1fe542a568 100644
--- a/tests/ui/generic-associated-types/issue-88595.rs
+++ b/tests/ui/generic-associated-types/issue-88595.rs
@@ -19,4 +19,5 @@ impl<'a> A<'a> for C {
     type B<'b> = impl Clone;
 
     fn a(&'a self) -> Self::B<'a> {} //~ ERROR: non-defining opaque type use in defining scope
+    //~^ ERROR: non-defining opaque type use in defining scope
 }
diff --git a/tests/ui/generic-associated-types/issue-88595.stderr b/tests/ui/generic-associated-types/issue-88595.stderr
index ab75a924006..87dd7118c06 100644
--- a/tests/ui/generic-associated-types/issue-88595.stderr
+++ b/tests/ui/generic-associated-types/issue-88595.stderr
@@ -10,5 +10,19 @@ note: for this opaque type
 LL |     type B<'b> = impl Clone;
    |                  ^^^^^^^^^^
 
-error: aborting due to 1 previous error
+error: non-defining opaque type use in defining scope
+  --> $DIR/issue-88595.rs:21:35
+   |
+LL |     fn a(&'a self) -> Self::B<'a> {}
+   |                                   ^^
+   |
+note: lifetime used multiple times
+  --> $DIR/issue-88595.rs:18:6
+   |
+LL | impl<'a> A<'a> for C {
+   |      ^^
+LL |     type B<'b> = impl Clone;
+   |            ^^
+
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/generic-associated-types/issue-90014-tait2.next-solver.stderr b/tests/ui/generic-associated-types/issue-90014-tait2.next-solver.stderr
new file mode 100644
index 00000000000..85c5dad7fc0
--- /dev/null
+++ b/tests/ui/generic-associated-types/issue-90014-tait2.next-solver.stderr
@@ -0,0 +1,15 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-90014-tait2.rs:27:9
+   |
+LL |     fn make_fut(&self) -> Box<dyn for<'a> Trait<'a, Thing = Fut<'a>>> {
+   |                           ------------------------------------------- expected `Box<(dyn for<'a> Trait<'a, Thing = Fut<'a>> + 'static)>` because of return type
+LL |         Box::new((async { () },))
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Box<dyn Trait<'a, Thing = Fut<'_>>>`, found `Box<(...,)>`
+   |
+   = note: expected struct `Box<(dyn for<'a> Trait<'a, Thing = Fut<'a>> + 'static)>`
+              found struct `Box<({async block@$DIR/issue-90014-tait2.rs:27:19: 27:31},)>`
+   = help: `({async block@$DIR/issue-90014-tait2.rs:27:19: 27:31},)` implements `Trait` so you could box the found value and coerce it to the trait object `Box<dyn Trait>`, you will have to change the expected type as well
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/generic-const-items/associated-const-equality.rs b/tests/ui/generic-const-items/associated-const-equality.rs
index 3c727097e2b..c0179f02fd2 100644
--- a/tests/ui/generic-const-items/associated-const-equality.rs
+++ b/tests/ui/generic-const-items/associated-const-equality.rs
@@ -1,22 +1,31 @@
 //@ check-pass
 
-#![feature(generic_const_items, associated_const_equality)]
+#![feature(generic_const_items, associated_const_equality, adt_const_params)]
 #![allow(incomplete_features)]
 
 trait Owner {
     const C<const N: u32>: u32;
     const K<const N: u32>: u32;
+    const Q<T>: Maybe<T>;
 }
 
 impl Owner for () {
     const C<const N: u32>: u32 = N;
     const K<const N: u32>: u32 = N + 1;
+    const Q<T>: Maybe<T> = Maybe::Nothing;
 }
 
 fn take0<const N: u32>(_: impl Owner<C<N> = { N }>) {}
 fn take1(_: impl Owner<K<99> = 100>) {}
+fn take2(_: impl Owner<Q<()> = { Maybe::Just(()) }>) {}
 
 fn main() {
     take0::<128>(());
     take1(());
 }
+
+#[derive(PartialEq, Eq, std::marker::ConstParamTy)]
+enum Maybe<T> {
+    Nothing,
+    Just(T),
+}
diff --git a/tests/ui/higher-ranked/trait-bounds/fn-ptr.current.stderr b/tests/ui/higher-ranked/trait-bounds/fn-ptr.current.stderr
new file mode 100644
index 00000000000..f3583cd218b
--- /dev/null
+++ b/tests/ui/higher-ranked/trait-bounds/fn-ptr.current.stderr
@@ -0,0 +1,19 @@
+error[E0277]: expected a `Fn(&'w ())` closure, found `fn(&'w ())`
+  --> $DIR/fn-ptr.rs:13:5
+   |
+LL |     ice();
+   |     ^^^^^ expected an `Fn(&'w ())` closure, found `fn(&'w ())`
+   |
+   = help: the trait `for<'w> Fn<(&'w (),)>` is not implemented for `fn(&'w ())`
+note: required by a bound in `ice`
+  --> $DIR/fn-ptr.rs:8:25
+   |
+LL | fn ice()
+   |    --- required by a bound in this function
+LL | where
+LL |     for<'w> fn(&'w ()): Fn(&'w ()),
+   |                         ^^^^^^^^^^ required by this bound in `ice`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/higher-ranked/trait-bounds/fn-ptr.rs b/tests/ui/higher-ranked/trait-bounds/fn-ptr.rs
index e015db1eb64..9298c10c341 100644
--- a/tests/ui/higher-ranked/trait-bounds/fn-ptr.rs
+++ b/tests/ui/higher-ranked/trait-bounds/fn-ptr.rs
@@ -1,4 +1,5 @@
-//@ revisions: classic next
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@[next] check-pass
 
@@ -10,5 +11,5 @@ where
 
 fn main() {
     ice();
-    //[classic]~^ ERROR expected a `Fn(&'w ())` closure, found `fn(&'w ())`
+    //[current]~^ ERROR expected a `Fn(&'w ())` closure, found `fn(&'w ())`
 }
diff --git a/tests/ui/higher-ranked/trait-bounds/future.current.stderr b/tests/ui/higher-ranked/trait-bounds/future.current.stderr
new file mode 100644
index 00000000000..5a6381ad28e
--- /dev/null
+++ b/tests/ui/higher-ranked/trait-bounds/future.current.stderr
@@ -0,0 +1,6 @@
+error: the compiler unexpectedly panicked. this is a bug.
+
+query stack during panic:
+#0 [evaluate_obligation] evaluating trait selection obligation `for<'a> {async fn body@$DIR/future.rs:33:35: 35:2}: core::future::future::Future`
+#1 [codegen_select_candidate] computing candidate for `<strlen as Trait>`
+end of query stack
diff --git a/tests/ui/higher-ranked/trait-bounds/future.rs b/tests/ui/higher-ranked/trait-bounds/future.rs
index 9ee012c05d9..4b52f04dbe0 100644
--- a/tests/ui/higher-ranked/trait-bounds/future.rs
+++ b/tests/ui/higher-ranked/trait-bounds/future.rs
@@ -1,15 +1,16 @@
 // ignore-tidy-linelength
 //@ edition:2021
-//@ revisions: classic next
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@[next] check-pass
-//@[classic] known-bug: #112347
-//@[classic] build-fail
-//@[classic] failure-status: 101
-//@[classic] normalize-stderr-test "note: .*\n\n" -> ""
-//@[classic] normalize-stderr-test "thread 'rustc' panicked.*\n.*\n" -> ""
-//@[classic] normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
-//@[classic] rustc-env:RUST_BACKTRACE=0
+//@[current] known-bug: #112347
+//@[current] build-fail
+//@[current] failure-status: 101
+//@[current] normalize-stderr-test "note: .*\n\n" -> ""
+//@[current] normalize-stderr-test "thread 'rustc' panicked.*\n.*\n" -> ""
+//@[current] normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
+//@[current] rustc-env:RUST_BACKTRACE=0
 
 #![feature(unboxed_closures)]
 
diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr
index f220ba6f338..23dfc77d92e 100644
--- a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits.stderr
@@ -18,6 +18,19 @@ help: consider further restricting this bound
 LL |     where F : Foo<'x> + for<'tcx> Foo<'tcx>
    |                       +++++++++++++++++++++
 
+warning: function cannot return without recursing
+  --> $DIR/hrtb-higher-ranker-supertraits.rs:21:1
+   |
+LL | / fn want_foo_for_any_tcx<F>(f: &F)
+LL | |     where F : for<'tcx> Foo<'tcx>
+   | |_________________________________^ cannot return without recursing
+...
+LL |       want_foo_for_any_tcx(f);
+   |       ----------------------- recursive call site
+   |
+   = help: a `loop` may express intention better if this is on purpose
+   = note: `#[warn(unconditional_recursion)]` on by default
+
 error[E0277]: the trait bound `for<'ccx> B: Bar<'ccx>` is not satisfied
   --> $DIR/hrtb-higher-ranker-supertraits.rs:35:26
    |
@@ -39,19 +52,6 @@ LL |     where B : Bar<'x> + for<'ccx> Bar<'ccx>
    |                       +++++++++++++++++++++
 
 warning: function cannot return without recursing
-  --> $DIR/hrtb-higher-ranker-supertraits.rs:21:1
-   |
-LL | / fn want_foo_for_any_tcx<F>(f: &F)
-LL | |     where F : for<'tcx> Foo<'tcx>
-   | |_________________________________^ cannot return without recursing
-...
-LL |       want_foo_for_any_tcx(f);
-   |       ----------------------- recursive call site
-   |
-   = help: a `loop` may express intention better if this is on purpose
-   = note: `#[warn(unconditional_recursion)]` on by default
-
-warning: function cannot return without recursing
   --> $DIR/hrtb-higher-ranker-supertraits.rs:38:1
    |
 LL | / fn want_bar_for_any_ccx<B>(b: &B)
diff --git a/tests/ui/hygiene/panic-location.rs b/tests/ui/hygiene/panic-location.rs
index a98960d74b0..b2f9bfe4f9a 100644
--- a/tests/ui/hygiene/panic-location.rs
+++ b/tests/ui/hygiene/panic-location.rs
@@ -1,6 +1,7 @@
 //@ run-fail
 //@ check-run-results
 //@ exec-env:RUST_BACKTRACE=0
+//@ normalize-stderr-test ".rs:\d+:\d+" -> ".rs:LL:CC"
 //
 // Regression test for issue #70963
 // The captured stderr from this test reports a location
diff --git a/tests/ui/hygiene/panic-location.run.stderr b/tests/ui/hygiene/panic-location.run.stderr
index ec0ce18c3df..5c1778bc485 100644
--- a/tests/ui/hygiene/panic-location.run.stderr
+++ b/tests/ui/hygiene/panic-location.run.stderr
@@ -1,3 +1,3 @@
-thread 'main' panicked at library/alloc/src/raw_vec.rs:26:5:
+thread 'main' panicked at library/alloc/src/raw_vec.rs:LL:CC:
 capacity overflow
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/tests/ui/impl-trait/auto-trait-leak.stderr b/tests/ui/impl-trait/auto-trait-leak.stderr
index 3fab766fa23..cc9939f2d57 100644
--- a/tests/ui/impl-trait/auto-trait-leak.stderr
+++ b/tests/ui/impl-trait/auto-trait-leak.stderr
@@ -6,16 +6,12 @@ LL |     send(cycle1().clone());
    |     |
    |     required by a bound introduced by this call
    |
+   = note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
 note: opaque type is declared here
   --> $DIR/auto-trait-leak.rs:11:16
    |
 LL | fn cycle1() -> impl Clone {
    |                ^^^^^^^^^^
-note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
-  --> $DIR/auto-trait-leak.rs:17:4
-   |
-LL | fn cycle2() -> impl Clone {
-   |    ^^^^^^
 note: required by a bound in `send`
   --> $DIR/auto-trait-leak.rs:4:12
    |
diff --git a/tests/ui/impl-trait/autoderef.rs b/tests/ui/impl-trait/autoderef.rs
index afab4e980a8..7802f725d6f 100644
--- a/tests/ui/impl-trait/autoderef.rs
+++ b/tests/ui/impl-trait/autoderef.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@ check-pass
 
diff --git a/tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr b/tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr
index 4cd4febc4f0..5fea5353ba5 100644
--- a/tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr
+++ b/tests/ui/impl-trait/erased-regions-in-hidden-ty.current.stderr
@@ -1,11 +1,11 @@
 error: {foo<ReEarlyParam(DefId(..), 0, 'a)>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()}
-  --> $DIR/erased-regions-in-hidden-ty.rs:11:36
+  --> $DIR/erased-regions-in-hidden-ty.rs:12:36
    |
 LL | fn foo<'a: 'a>(x: &'a Vec<i32>) -> impl Fn() + 'static {
    |                                    ^^^^^^^^^^^^^^^^^^^
 
 error: Opaque(DefId(..), [ReErased])
-  --> $DIR/erased-regions-in-hidden-ty.rs:17:13
+  --> $DIR/erased-regions-in-hidden-ty.rs:18:13
    |
 LL | fn bar() -> impl Fn() + 'static {
    |             ^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr b/tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr
index 4cd4febc4f0..5fea5353ba5 100644
--- a/tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr
+++ b/tests/ui/impl-trait/erased-regions-in-hidden-ty.next.stderr
@@ -1,11 +1,11 @@
 error: {foo<ReEarlyParam(DefId(..), 0, 'a)>::{closure#0} closure_kind_ty=i8 closure_sig_as_fn_ptr_ty=extern "rust-call" fn(()) upvar_tys=()}
-  --> $DIR/erased-regions-in-hidden-ty.rs:11:36
+  --> $DIR/erased-regions-in-hidden-ty.rs:12:36
    |
 LL | fn foo<'a: 'a>(x: &'a Vec<i32>) -> impl Fn() + 'static {
    |                                    ^^^^^^^^^^^^^^^^^^^
 
 error: Opaque(DefId(..), [ReErased])
-  --> $DIR/erased-regions-in-hidden-ty.rs:17:13
+  --> $DIR/erased-regions-in-hidden-ty.rs:18:13
    |
 LL | fn bar() -> impl Fn() + 'static {
    |             ^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/impl-trait/erased-regions-in-hidden-ty.rs b/tests/ui/impl-trait/erased-regions-in-hidden-ty.rs
index c73f4fc1f65..c18df16bd6c 100644
--- a/tests/ui/impl-trait/erased-regions-in-hidden-ty.rs
+++ b/tests/ui/impl-trait/erased-regions-in-hidden-ty.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@ compile-flags: -Zverbose-internals
 //@[next] compile-flags: -Znext-solver
 //@ normalize-stderr-test "DefId\([^\)]+\)" -> "DefId(..)"
diff --git a/tests/ui/impl-trait/in-trait/object-safety-sized.rs b/tests/ui/impl-trait/in-trait/object-safety-sized.rs
index 2bd8ea646a1..b5b7a6ed9bf 100644
--- a/tests/ui/impl-trait/in-trait/object-safety-sized.rs
+++ b/tests/ui/impl-trait/in-trait/object-safety-sized.rs
@@ -1,5 +1,6 @@
 //@ check-pass
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 
diff --git a/tests/ui/impl-trait/in-trait/refine-normalize.rs b/tests/ui/impl-trait/in-trait/refine-normalize.rs
index 95f2cda6a74..490e7bf8923 100644
--- a/tests/ui/impl-trait/in-trait/refine-normalize.rs
+++ b/tests/ui/impl-trait/in-trait/refine-normalize.rs
@@ -1,6 +1,7 @@
 //@ check-pass
 //@ edition: 2021
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 #![deny(refining_impl_trait)]
diff --git a/tests/ui/impl-trait/issue-103181-1.current.stderr b/tests/ui/impl-trait/issue-103181-1.current.stderr
index 83410dfc6ea..c15b7e04c26 100644
--- a/tests/ui/impl-trait/issue-103181-1.current.stderr
+++ b/tests/ui/impl-trait/issue-103181-1.current.stderr
@@ -1,5 +1,5 @@
 error[E0046]: not all trait items implemented, missing: `Error`
-  --> $DIR/issue-103181-1.rs:11:5
+  --> $DIR/issue-103181-1.rs:12:5
    |
 LL |         type Error;
    |         ---------- `Error` from trait
diff --git a/tests/ui/impl-trait/issue-103181-1.next.stderr b/tests/ui/impl-trait/issue-103181-1.next.stderr
index 83410dfc6ea..c15b7e04c26 100644
--- a/tests/ui/impl-trait/issue-103181-1.next.stderr
+++ b/tests/ui/impl-trait/issue-103181-1.next.stderr
@@ -1,5 +1,5 @@
 error[E0046]: not all trait items implemented, missing: `Error`
-  --> $DIR/issue-103181-1.rs:11:5
+  --> $DIR/issue-103181-1.rs:12:5
    |
 LL |         type Error;
    |         ---------- `Error` from trait
diff --git a/tests/ui/impl-trait/issue-103181-1.rs b/tests/ui/impl-trait/issue-103181-1.rs
index 75333af58ec..fd8b72c1c75 100644
--- a/tests/ui/impl-trait/issue-103181-1.rs
+++ b/tests/ui/impl-trait/issue-103181-1.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@ edition:2021
 
diff --git a/tests/ui/impl-trait/issues/issue-78722-2.rs b/tests/ui/impl-trait/issues/issue-78722-2.rs
index 26181b612ed..e811620c03b 100644
--- a/tests/ui/impl-trait/issues/issue-78722-2.rs
+++ b/tests/ui/impl-trait/issues/issue-78722-2.rs
@@ -12,9 +12,9 @@ struct Bug {
             //~^ ERROR future that resolves to `u8`, but it resolves to `()`
             async {}
         }
+        // FIXME(type_alias_impl_trait): inform the user about why `F` is not available here.
         let f: F = async { 1 };
-        //~^ ERROR item constrains opaque type that is not in its signature
-        //~| ERROR `async` blocks are not allowed in constants
+        //~^ ERROR mismatched types
         1
     }],
 }
diff --git a/tests/ui/impl-trait/issues/issue-78722-2.stderr b/tests/ui/impl-trait/issues/issue-78722-2.stderr
index c402ce864c7..91dad1b5e67 100644
--- a/tests/ui/impl-trait/issues/issue-78722-2.stderr
+++ b/tests/ui/impl-trait/issues/issue-78722-2.stderr
@@ -4,30 +4,21 @@ error[E0271]: expected `{async block@$DIR/issue-78722-2.rs:13:13: 13:21}` to be
 LL |         fn concrete_use() -> F {
    |                              ^ expected `()`, found `u8`
 
-error: item constrains opaque type that is not in its signature
-  --> $DIR/issue-78722-2.rs:15:20
+error[E0308]: mismatched types
+  --> $DIR/issue-78722-2.rs:16:20
    |
+LL | type F = impl core::future::Future<Output = u8>;
+   |          -------------------------------------- the expected future
+...
 LL |         let f: F = async { 1 };
-   |                    ^^^^^^^^^^^
+   |                -   ^^^^^^^^^^^ expected future, found `async` block
+   |                |
+   |                expected due to this
    |
-   = note: this item must mention the opaque type in its signature in order to be able to register hidden types
-note: this item must mention the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/issue-78722-2.rs:15:20
-   |
-LL |         let f: F = async { 1 };
-   |                    ^^^^^^^^^^^
-
-error[E0658]: `async` blocks are not allowed in constants
-  --> $DIR/issue-78722-2.rs:15:20
-   |
-LL |         let f: F = async { 1 };
-   |                    ^^^^^^^^^^^
-   |
-   = note: see issue #85368 <https://github.com/rust-lang/rust/issues/85368> for more information
-   = help: add `#![feature(const_async_blocks)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = note: expected opaque type `F`
+            found `async` block `{async block@$DIR/issue-78722-2.rs:16:20: 16:31}`
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0271, E0658.
+Some errors have detailed explanations: E0271, E0308.
 For more information about an error, try `rustc --explain E0271`.
diff --git a/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr b/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr
index 4a5e4bfe94b..755d12d7448 100644
--- a/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr
+++ b/tests/ui/impl-trait/recursive-coroutine-boxed.next.stderr
@@ -1,5 +1,5 @@
 error[E0282]: type annotations needed
-  --> $DIR/recursive-coroutine-boxed.rs:11:23
+  --> $DIR/recursive-coroutine-boxed.rs:12:23
    |
 LL |         let mut gen = Box::pin(foo());
    |                       ^^^^^^^^ cannot infer type of the type parameter `T` declared on the struct `Box`
@@ -13,7 +13,7 @@ LL |         let mut gen = Box::<T>::pin(foo());
    |                          +++++
 
 error[E0282]: type annotations needed
-  --> $DIR/recursive-coroutine-boxed.rs:8:13
+  --> $DIR/recursive-coroutine-boxed.rs:9:13
    |
 LL | fn foo() -> impl Coroutine<Yield = (), Return = ()> {
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type for opaque type `impl Coroutine<Yield = (), Return = ()>`
diff --git a/tests/ui/impl-trait/recursive-coroutine-boxed.rs b/tests/ui/impl-trait/recursive-coroutine-boxed.rs
index 8f0bbb400cf..3b8ffb92090 100644
--- a/tests/ui/impl-trait/recursive-coroutine-boxed.rs
+++ b/tests/ui/impl-trait/recursive-coroutine-boxed.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[current] check-pass
 //@[next] compile-flags: -Znext-solver
 #![feature(coroutines, coroutine_trait)]
diff --git a/tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr b/tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr
index df457c13e70..ee87c483d0d 100644
--- a/tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr
+++ b/tests/ui/impl-trait/recursive-coroutine-indirect.current.stderr
@@ -1,5 +1,5 @@
 error[E0733]: recursion in a coroutine requires boxing
-  --> $DIR/recursive-coroutine-indirect.rs:10:5
+  --> $DIR/recursive-coroutine-indirect.rs:11:5
    |
 LL |     move || {
    |     ^^^^^^^
diff --git a/tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr b/tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr
index df457c13e70..ee87c483d0d 100644
--- a/tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr
+++ b/tests/ui/impl-trait/recursive-coroutine-indirect.next.stderr
@@ -1,5 +1,5 @@
 error[E0733]: recursion in a coroutine requires boxing
-  --> $DIR/recursive-coroutine-indirect.rs:10:5
+  --> $DIR/recursive-coroutine-indirect.rs:11:5
    |
 LL |     move || {
    |     ^^^^^^^
diff --git a/tests/ui/impl-trait/recursive-coroutine-indirect.rs b/tests/ui/impl-trait/recursive-coroutine-indirect.rs
index 31d22970e04..bba9792fe3c 100644
--- a/tests/ui/impl-trait/recursive-coroutine-indirect.rs
+++ b/tests/ui/impl-trait/recursive-coroutine-indirect.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 //@[next] build-fail
diff --git a/tests/ui/impl-trait/reveal-during-codegen.rs b/tests/ui/impl-trait/reveal-during-codegen.rs
index 996f0bb8bbf..d3ec746d9a9 100644
--- a/tests/ui/impl-trait/reveal-during-codegen.rs
+++ b/tests/ui/impl-trait/reveal-during-codegen.rs
@@ -1,5 +1,6 @@
 //@ build-pass
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 fn test() -> Option<impl Sized> {
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other.current.stderr b/tests/ui/impl-trait/two_tait_defining_each_other.current.stderr
index b60529ed002..bf194f997b4 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other.current.stderr
+++ b/tests/ui/impl-trait/two_tait_defining_each_other.current.stderr
@@ -1,16 +1,16 @@
 error: opaque type's hidden type cannot be another opaque type from the same scope
-  --> $DIR/two_tait_defining_each_other.rs:16:5
+  --> $DIR/two_tait_defining_each_other.rs:17:5
    |
 LL |     x // A's hidden type is `Bar`, because all the hidden types of `B` are compared with each other
    |     ^ one of the two opaque types used here has to be outside its defining scope
    |
 note: opaque type whose hidden type is being assigned
-  --> $DIR/two_tait_defining_each_other.rs:8:10
+  --> $DIR/two_tait_defining_each_other.rs:9:10
    |
 LL | type B = impl Foo;
    |          ^^^^^^^^
 note: opaque type being used as hidden type
-  --> $DIR/two_tait_defining_each_other.rs:7:10
+  --> $DIR/two_tait_defining_each_other.rs:8:10
    |
 LL | type A = impl Foo;
    |          ^^^^^^^^
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other.rs b/tests/ui/impl-trait/two_tait_defining_each_other.rs
index 0c3376b413f..ebfe7f674be 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other.rs
+++ b/tests/ui/impl-trait/two_tait_defining_each_other.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@[next] check-pass
 
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr b/tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr
index c5c9ae33f4d..6f2b2d9ca04 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr
+++ b/tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr
@@ -1,5 +1,5 @@
 error: unconstrained opaque type
-  --> $DIR/two_tait_defining_each_other2.rs:5:10
+  --> $DIR/two_tait_defining_each_other2.rs:6:10
    |
 LL | type A = impl Foo;
    |          ^^^^^^^^
@@ -7,18 +7,18 @@ LL | type A = impl Foo;
    = note: `A` must be used in combination with a concrete type within the same module
 
 error: opaque type's hidden type cannot be another opaque type from the same scope
-  --> $DIR/two_tait_defining_each_other2.rs:12:5
+  --> $DIR/two_tait_defining_each_other2.rs:13:5
    |
 LL |     x // B's hidden type is A (opaquely)
    |     ^ one of the two opaque types used here has to be outside its defining scope
    |
 note: opaque type whose hidden type is being assigned
-  --> $DIR/two_tait_defining_each_other2.rs:6:10
+  --> $DIR/two_tait_defining_each_other2.rs:7:10
    |
 LL | type B = impl Foo;
    |          ^^^^^^^^
 note: opaque type being used as hidden type
-  --> $DIR/two_tait_defining_each_other2.rs:5:10
+  --> $DIR/two_tait_defining_each_other2.rs:6:10
    |
 LL | type A = impl Foo;
    |          ^^^^^^^^
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr b/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr
index 7e2b05618c4..5316160125b 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr
+++ b/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr
@@ -1,5 +1,5 @@
 error[E0284]: type annotations needed: cannot satisfy `_ == A`
-  --> $DIR/two_tait_defining_each_other2.rs:10:8
+  --> $DIR/two_tait_defining_each_other2.rs:11:8
    |
 LL | fn muh(x: A) -> B {
    |        ^ cannot satisfy `_ == A`
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other2.rs b/tests/ui/impl-trait/two_tait_defining_each_other2.rs
index faa1fed22d3..e850736fdfa 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other2.rs
+++ b/tests/ui/impl-trait/two_tait_defining_each_other2.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 #![feature(type_alias_impl_trait)]
 
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other3.current.stderr b/tests/ui/impl-trait/two_tait_defining_each_other3.current.stderr
index 1dccfd17a70..fa353a77536 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other3.current.stderr
+++ b/tests/ui/impl-trait/two_tait_defining_each_other3.current.stderr
@@ -1,16 +1,16 @@
 error: opaque type's hidden type cannot be another opaque type from the same scope
-  --> $DIR/two_tait_defining_each_other3.rs:13:16
+  --> $DIR/two_tait_defining_each_other3.rs:14:16
    |
 LL |         return x;  // B's hidden type is A (opaquely)
    |                ^ one of the two opaque types used here has to be outside its defining scope
    |
 note: opaque type whose hidden type is being assigned
-  --> $DIR/two_tait_defining_each_other3.rs:7:10
+  --> $DIR/two_tait_defining_each_other3.rs:8:10
    |
 LL | type B = impl Foo;
    |          ^^^^^^^^
 note: opaque type being used as hidden type
-  --> $DIR/two_tait_defining_each_other3.rs:6:10
+  --> $DIR/two_tait_defining_each_other3.rs:7:10
    |
 LL | type A = impl Foo;
    |          ^^^^^^^^
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other3.rs b/tests/ui/impl-trait/two_tait_defining_each_other3.rs
index a596860e176..33695d8ed80 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other3.rs
+++ b/tests/ui/impl-trait/two_tait_defining_each_other3.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@[next] check-pass
 #![feature(type_alias_impl_trait)]
diff --git a/tests/ui/inference/type-infer-generalize-ty-var.rs b/tests/ui/inference/type-infer-generalize-ty-var.rs
index 8dae835a9db..d623aeff47d 100644
--- a/tests/ui/inference/type-infer-generalize-ty-var.rs
+++ b/tests/ui/inference/type-infer-generalize-ty-var.rs
@@ -1,5 +1,6 @@
 //@ check-pass
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 #![allow(non_upper_case_globals)]
diff --git a/tests/ui/inherit-env.rs b/tests/ui/inherit-env.rs
index e4ae8145d71..0eb61fcdd53 100644
--- a/tests/ui/inherit-env.rs
+++ b/tests/ui/inherit-env.rs
@@ -1,6 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten
-//@ ignore-wasm32
+//@ ignore-wasm32 no subprocess support
 //@ ignore-sgx no processes
 
 use std::env;
diff --git a/tests/ui/intrinsics/intrinsic-alignment.rs b/tests/ui/intrinsics/intrinsic-alignment.rs
index 69ccab201e6..4856da553a8 100644
--- a/tests/ui/intrinsics/intrinsic-alignment.rs
+++ b/tests/ui/intrinsics/intrinsic-alignment.rs
@@ -1,5 +1,4 @@
 //@ run-pass
-//@ ignore-wasm32-bare seems not important to test here
 
 #![feature(intrinsics, rustc_attrs)]
 
@@ -65,6 +64,16 @@ mod m {
     }
 }
 
+#[cfg(target_family = "wasm")]
+mod m {
+    pub fn main() {
+        unsafe {
+            assert_eq!(::rusti::pref_align_of::<u64>(), 8);
+            assert_eq!(::rusti::min_align_of::<u64>(), 8);
+        }
+    }
+}
+
 fn main() {
     m::main();
 }
diff --git a/tests/ui/intrinsics/panic-uninitialized-zeroed.rs b/tests/ui/intrinsics/panic-uninitialized-zeroed.rs
index fb3b0652ddb..b1ac7528d58 100644
--- a/tests/ui/intrinsics/panic-uninitialized-zeroed.rs
+++ b/tests/ui/intrinsics/panic-uninitialized-zeroed.rs
@@ -2,7 +2,7 @@
 //@ revisions: default strict
 //@ [strict]compile-flags: -Zstrict-init-checks
 // ignore-tidy-linelength
-//@ ignore-emscripten spawning processes is not supported
+//@ ignore-wasm32 spawning processes is not supported
 //@ ignore-sgx no processes
 //
 // This test checks panic emitted from `mem::{uninitialized,zeroed}`.
diff --git a/tests/ui/io-checks/non-ice-error-on-worker-io-fail.rs b/tests/ui/io-checks/non-ice-error-on-worker-io-fail.rs
index 3a80934b865..fab7ec166e6 100644
--- a/tests/ui/io-checks/non-ice-error-on-worker-io-fail.rs
+++ b/tests/ui/io-checks/non-ice-error-on-worker-io-fail.rs
@@ -26,7 +26,6 @@
 
 //@ ignore-windows - this is a unix-specific test
 //@ ignore-emscripten - the file-system issues do not replicate here
-//@ ignore-wasm - the file-system issues do not replicate here
 //@ ignore-arm - the file-system issues do not replicate here, at least on armhf-gnu
 
 #![crate_type = "lib"]
diff --git a/tests/ui/issues/issue-11374.stderr b/tests/ui/issues/issue-11374.stderr
index 3ae5cfc79f8..c5dca7a9313 100644
--- a/tests/ui/issues/issue-11374.stderr
+++ b/tests/ui/issues/issue-11374.stderr
@@ -1,3 +1,12 @@
+error[E0515]: cannot return value referencing local variable `r`
+  --> $DIR/issue-11374.rs:20:5
+   |
+LL |     Container::wrap(&mut r as &mut dyn io::Read)
+   |     ^^^^^^^^^^^^^^^^------^^^^^^^^^^^^^^^^^^^^^^
+   |     |               |
+   |     |               `r` is borrowed here
+   |     returns a value referencing data owned by the current function
+
 error[E0308]: mismatched types
   --> $DIR/issue-11374.rs:27:15
    |
@@ -18,15 +27,6 @@ help: consider mutably borrowing here
 LL |     c.read_to(&mut v);
    |               ++++
 
-error[E0515]: cannot return value referencing local variable `r`
-  --> $DIR/issue-11374.rs:20:5
-   |
-LL |     Container::wrap(&mut r as &mut dyn io::Read)
-   |     ^^^^^^^^^^^^^^^^------^^^^^^^^^^^^^^^^^^^^^^
-   |     |               |
-   |     |               `r` is borrowed here
-   |     returns a value referencing data owned by the current function
-
 error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0308, E0515.
diff --git a/tests/ui/issues/issue-12133-3.rs b/tests/ui/issues/issue-12133-3.rs
index 572337679af..a34c075d64d 100644
--- a/tests/ui/issues/issue-12133-3.rs
+++ b/tests/ui/issues/issue-12133-3.rs
@@ -2,7 +2,7 @@
 //@ aux-build:issue-12133-rlib.rs
 //@ aux-build:issue-12133-dylib.rs
 //@ aux-build:issue-12133-dylib2.rs
-//@ ignore-emscripten no dylib support
+//@ ignore-wasm32 no dylib support
 //@ ignore-musl
 //@ needs-dynamic-linking
 
diff --git a/tests/ui/issues/issue-12699.rs b/tests/ui/issues/issue-12699.rs
index 3222fbe00ea..4fc93735c3c 100644
--- a/tests/ui/issues/issue-12699.rs
+++ b/tests/ui/issues/issue-12699.rs
@@ -1,5 +1,4 @@
 //@ run-pass
-//@ ignore-wasm32-bare can't block the thread
 //@ ignore-sgx not supported
 #![allow(deprecated)]
 
diff --git a/tests/ui/issues/issue-13167.rs b/tests/ui/issues/issue-13167.rs
index 3cf8367a678..15ee02b9cd4 100644
--- a/tests/ui/issues/issue-13167.rs
+++ b/tests/ui/issues/issue-13167.rs
@@ -1,6 +1,7 @@
 //@ check-pass
 //@ pretty-expanded FIXME #23616
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 use std::slice;
diff --git a/tests/ui/issues/issue-15734.rs b/tests/ui/issues/issue-15734.rs
index b8d0b088a89..26fb7061664 100644
--- a/tests/ui/issues/issue-15734.rs
+++ b/tests/ui/issues/issue-15734.rs
@@ -1,5 +1,6 @@
 //@ run-pass
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 use std::ops::Index;
diff --git a/tests/ui/issues/issue-2214.rs b/tests/ui/issues/issue-2214.rs
index 3c458984204..5d732cd7798 100644
--- a/tests/ui/issues/issue-2214.rs
+++ b/tests/ui/issues/issue-2214.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-wasm32-bare no libc to test ffi with
+//@ ignore-wasm32 wasi-libc does not have lgamma
 //@ ignore-sgx no libc
 #![feature(rustc_private)]
 
diff --git a/tests/ui/issues/issue-25185.rs b/tests/ui/issues/issue-25185.rs
index ee54a21694e..7dc06ad96df 100644
--- a/tests/ui/issues/issue-25185.rs
+++ b/tests/ui/issues/issue-25185.rs
@@ -1,7 +1,6 @@
 //@ run-pass
 //@ aux-build:issue-25185-1.rs
 //@ aux-build:issue-25185-2.rs
-//@ ignore-wasm32-bare no libc for ffi testing
 
 extern crate issue_25185_2;
 
diff --git a/tests/ui/issues/issue-33770.rs b/tests/ui/issues/issue-33770.rs
index b4290955be5..0fa91ac91c4 100644
--- a/tests/ui/issues/issue-33770.rs
+++ b/tests/ui/issues/issue-33770.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 
 use std::process::{Command, Stdio};
diff --git a/tests/ui/issues/issue-33992.rs b/tests/ui/issues/issue-33992.rs
index d1c62c830a9..177ff234bb2 100644
--- a/tests/ui/issues/issue-33992.rs
+++ b/tests/ui/issues/issue-33992.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 //@ ignore-windows
 //@ ignore-macos
-//@ ignore-emscripten common linkage not implemented right now
+//@ ignore-wasm32 common linkage not implemented right now
 
 #![feature(linkage)]
 
diff --git a/tests/ui/issues/issue-3656.rs b/tests/ui/issues/issue-3656.rs
index ff3b782ade9..1b65129d0c3 100644
--- a/tests/ui/issues/issue-3656.rs
+++ b/tests/ui/issues/issue-3656.rs
@@ -6,7 +6,6 @@
 // the alignment of elements into account.
 
 //@ pretty-expanded FIXME #23616
-//@ ignore-wasm32-bare no libc to test with
 #![feature(rustc_private)]
 
 extern crate libc;
diff --git a/tests/ui/issues/issue-39175.rs b/tests/ui/issues/issue-39175.rs
index ddba8052b5e..7b801317b71 100644
--- a/tests/ui/issues/issue-39175.rs
+++ b/tests/ui/issues/issue-39175.rs
@@ -4,7 +4,7 @@
 // these platforms also.
 
 //@ ignore-windows
-//@ ignore-emscripten
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 
 use std::process::Command;
diff --git a/tests/ui/issues/issue-44216-add-instant.rs b/tests/ui/issues/issue-44216-add-instant.rs
index 1db0adedcf5..ca2c52b99a8 100644
--- a/tests/ui/issues/issue-44216-add-instant.rs
+++ b/tests/ui/issues/issue-44216-add-instant.rs
@@ -1,10 +1,9 @@
 //@ run-fail
 //@ error-pattern:overflow
-//@ ignore-emscripten no processes
 
-use std::time::{Instant, Duration};
+use std::time::{Duration, Instant};
 
 fn main() {
     let now = Instant::now();
-    let _ = now + Duration::from_secs(u64::MAX);
+    let _ = now + Duration::MAX;
 }
diff --git a/tests/ui/kindck/kindck-impl-type-params.stderr b/tests/ui/kindck/kindck-impl-type-params.stderr
index aad020e4ec9..ca3a90f46a7 100644
--- a/tests/ui/kindck/kindck-impl-type-params.stderr
+++ b/tests/ui/kindck/kindck-impl-type-params.stderr
@@ -74,6 +74,15 @@ help: consider restricting type parameter `T`
 LL | fn g<T: std::marker::Copy>(val: T) {
    |       +++++++++++++++++++
 
+error: lifetime may not live long enough
+  --> $DIR/kindck-impl-type-params.rs:30:13
+   |
+LL | fn foo<'a>() {
+   |        -- lifetime `'a` defined here
+LL |     let t: S<&'a isize> = S(marker::PhantomData);
+LL |     let a = &t as &dyn Gettable<&'a isize>;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
+
 error[E0277]: the trait bound `String: Copy` is not satisfied
   --> $DIR/kindck-impl-type-params.rs:36:13
    |
@@ -111,15 +120,6 @@ LL +     #[derive(Copy)]
 LL |     struct Foo; // does not impl Copy
    |
 
-error: lifetime may not live long enough
-  --> $DIR/kindck-impl-type-params.rs:30:13
-   |
-LL | fn foo<'a>() {
-   |        -- lifetime `'a` defined here
-LL |     let t: S<&'a isize> = S(marker::PhantomData);
-LL |     let a = &t as &dyn Gettable<&'a isize>;
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
-
 error: aborting due to 7 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/kindck/kindck-send-object1.stderr b/tests/ui/kindck/kindck-send-object1.stderr
index f2aa814676f..5d06a2ab4da 100644
--- a/tests/ui/kindck/kindck-send-object1.stderr
+++ b/tests/ui/kindck/kindck-send-object1.stderr
@@ -12,6 +12,14 @@ note: required by a bound in `assert_send`
 LL | fn assert_send<T:Send+'static>() { }
    |                  ^^^^ required by this bound in `assert_send`
 
+error: lifetime may not live long enough
+  --> $DIR/kindck-send-object1.rs:14:5
+   |
+LL | fn test52<'a>() {
+   |           -- lifetime `'a` defined here
+LL |     assert_send::<&'a (dyn Dummy + Sync)>();
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
+
 error[E0277]: `(dyn Dummy + 'a)` cannot be sent between threads safely
   --> $DIR/kindck-send-object1.rs:29:19
    |
@@ -28,14 +36,6 @@ note: required by a bound in `assert_send`
 LL | fn assert_send<T:Send+'static>() { }
    |                  ^^^^ required by this bound in `assert_send`
 
-error: lifetime may not live long enough
-  --> $DIR/kindck-send-object1.rs:14:5
-   |
-LL | fn test52<'a>() {
-   |           -- lifetime `'a` defined here
-LL |     assert_send::<&'a (dyn Dummy + Sync)>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
-
 error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/lazy-type-alias/coerce-behind-lazy.current.stderr b/tests/ui/lazy-type-alias/coerce-behind-lazy.current.stderr
index 98b3921dec4..78dd05b78af 100644
--- a/tests/ui/lazy-type-alias/coerce-behind-lazy.current.stderr
+++ b/tests/ui/lazy-type-alias/coerce-behind-lazy.current.stderr
@@ -1,5 +1,5 @@
 warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/coerce-behind-lazy.rs:5:12
+  --> $DIR/coerce-behind-lazy.rs:6:12
    |
 LL | #![feature(lazy_type_alias)]
    |            ^^^^^^^^^^^^^^^
diff --git a/tests/ui/lazy-type-alias/coerce-behind-lazy.next.stderr b/tests/ui/lazy-type-alias/coerce-behind-lazy.next.stderr
index 98b3921dec4..78dd05b78af 100644
--- a/tests/ui/lazy-type-alias/coerce-behind-lazy.next.stderr
+++ b/tests/ui/lazy-type-alias/coerce-behind-lazy.next.stderr
@@ -1,5 +1,5 @@
 warning: the feature `lazy_type_alias` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/coerce-behind-lazy.rs:5:12
+  --> $DIR/coerce-behind-lazy.rs:6:12
    |
 LL | #![feature(lazy_type_alias)]
    |            ^^^^^^^^^^^^^^^
diff --git a/tests/ui/lazy-type-alias/coerce-behind-lazy.rs b/tests/ui/lazy-type-alias/coerce-behind-lazy.rs
index 42adfd274a3..7873ff46b66 100644
--- a/tests/ui/lazy-type-alias/coerce-behind-lazy.rs
+++ b/tests/ui/lazy-type-alias/coerce-behind-lazy.rs
@@ -1,5 +1,6 @@
 //@ check-pass
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 #![feature(lazy_type_alias)]
diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.current.stderr b/tests/ui/lazy-type-alias/inherent-impls-overflow.current.stderr
new file mode 100644
index 00000000000..05f5449dbc8
--- /dev/null
+++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.current.stderr
@@ -0,0 +1,43 @@
+error[E0275]: overflow normalizing the type alias `Loop`
+  --> $DIR/inherent-impls-overflow.rs:8:13
+   |
+LL | type Loop = Loop;
+   |             ^^^^
+   |
+   = note: in case this is a recursive type alias, consider using a struct, enum, or union instead
+
+error[E0275]: overflow normalizing the type alias `Loop`
+  --> $DIR/inherent-impls-overflow.rs:10:1
+   |
+LL | impl Loop {}
+   | ^^^^^^^^^^^^
+   |
+   = note: in case this is a recursive type alias, consider using a struct, enum, or union instead
+
+error[E0275]: overflow normalizing the type alias `Poly0<(((((((...,),),),),),),)>`
+  --> $DIR/inherent-impls-overflow.rs:14:17
+   |
+LL | type Poly0<T> = Poly1<(T,)>;
+   |                 ^^^^^^^^^^^
+   |
+   = note: in case this is a recursive type alias, consider using a struct, enum, or union instead
+
+error[E0275]: overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>`
+  --> $DIR/inherent-impls-overflow.rs:17:17
+   |
+LL | type Poly1<T> = Poly0<(T,)>;
+   |                 ^^^^^^^^^^^
+   |
+   = note: in case this is a recursive type alias, consider using a struct, enum, or union instead
+
+error[E0275]: overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>`
+  --> $DIR/inherent-impls-overflow.rs:21:1
+   |
+LL | impl Poly0<()> {}
+   | ^^^^^^^^^^^^^^^^^
+   |
+   = note: in case this is a recursive type alias, consider using a struct, enum, or union instead
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr b/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr
index 80377bf6c20..944fe8aa8e5 100644
--- a/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr
+++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr
@@ -1,11 +1,11 @@
 error[E0275]: overflow evaluating the requirement `Loop == _`
-  --> $DIR/inherent-impls-overflow.rs:9:6
+  --> $DIR/inherent-impls-overflow.rs:10:6
    |
 LL | impl Loop {}
    |      ^^^^
 
 error[E0392]: type parameter `T` is never used
-  --> $DIR/inherent-impls-overflow.rs:13:12
+  --> $DIR/inherent-impls-overflow.rs:14:12
    |
 LL | type Poly0<T> = Poly1<(T,)>;
    |            ^ unused type parameter
@@ -14,7 +14,7 @@ LL | type Poly0<T> = Poly1<(T,)>;
    = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
 
 error[E0392]: type parameter `T` is never used
-  --> $DIR/inherent-impls-overflow.rs:16:12
+  --> $DIR/inherent-impls-overflow.rs:17:12
    |
 LL | type Poly1<T> = Poly0<(T,)>;
    |            ^ unused type parameter
@@ -23,7 +23,7 @@ LL | type Poly1<T> = Poly0<(T,)>;
    = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead
 
 error[E0275]: overflow evaluating the requirement `Poly0<()> == _`
-  --> $DIR/inherent-impls-overflow.rs:20:6
+  --> $DIR/inherent-impls-overflow.rs:21:6
    |
 LL | impl Poly0<()> {}
    |      ^^^^^^^^^
diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.rs b/tests/ui/lazy-type-alias/inherent-impls-overflow.rs
index dbf5c3743e8..98f0d811a47 100644
--- a/tests/ui/lazy-type-alias/inherent-impls-overflow.rs
+++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.rs
@@ -1,24 +1,25 @@
-//@ revisions: classic next
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 #![feature(lazy_type_alias)]
 #![allow(incomplete_features)]
 
-type Loop = Loop; //[classic]~ ERROR overflow normalizing the type alias `Loop`
+type Loop = Loop; //[current]~ ERROR overflow normalizing the type alias `Loop`
 
 impl Loop {}
-//[classic]~^ ERROR overflow normalizing the type alias `Loop`
+//[current]~^ ERROR overflow normalizing the type alias `Loop`
 //[next]~^^ ERROR overflow evaluating the requirement `Loop == _`
 
 type Poly0<T> = Poly1<(T,)>;
-//[classic]~^ ERROR overflow normalizing the type alias `Poly0<(((((((...,),),),),),),)>`
+//[current]~^ ERROR overflow normalizing the type alias `Poly0<(((((((...,),),),),),),)>`
 //[next]~^^ ERROR type parameter `T` is never used
 type Poly1<T> = Poly0<(T,)>;
-//[classic]~^ ERROR  overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>`
+//[current]~^ ERROR  overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>`
 //[next]~^^ ERROR type parameter `T` is never used
 
 impl Poly0<()> {}
-//[classic]~^ ERROR overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>`
+//[current]~^ ERROR overflow normalizing the type alias `Poly1<(((((((...,),),),),),),)>`
 //[next]~^^ ERROR overflow evaluating the requirement `Poly0<()> == _`
 
 fn main() {}
diff --git a/tests/ui/lifetimes/issue-17728.stderr b/tests/ui/lifetimes/issue-17728.stderr
index 23547f722a1..811d8c89991 100644
--- a/tests/ui/lifetimes/issue-17728.stderr
+++ b/tests/ui/lifetimes/issue-17728.stderr
@@ -1,3 +1,19 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-17728.rs:15:28
+   |
+LL |     fn attemptTraverse(&self, room: &Room, directionStr: &str) -> Result<&Room, &str> {
+   |                        -            - let's call the lifetime of this reference `'1`
+   |                        |
+   |                        let's call the lifetime of this reference `'2`
+...
+LL |             Some(entry) => Ok(entry),
+   |                            ^^^^^^^^^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
+   |
+help: consider introducing a named lifetime parameter
+   |
+LL |     fn attemptTraverse<'a>(&'a self, room: &'a Room, directionStr: &str) -> Result<&Room, &str> {
+   |                       ++++  ++              ++
+
 error[E0308]: `match` arms have incompatible types
   --> $DIR/issue-17728.rs:108:14
    |
@@ -16,22 +32,6 @@ LL | |     }
    = note: expected enum `RoomDirection`
               found enum `Option<_>`
 
-error: lifetime may not live long enough
-  --> $DIR/issue-17728.rs:15:28
-   |
-LL |     fn attemptTraverse(&self, room: &Room, directionStr: &str) -> Result<&Room, &str> {
-   |                        -            - let's call the lifetime of this reference `'1`
-   |                        |
-   |                        let's call the lifetime of this reference `'2`
-...
-LL |             Some(entry) => Ok(entry),
-   |                            ^^^^^^^^^ method was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
-   |
-help: consider introducing a named lifetime parameter
-   |
-LL |     fn attemptTraverse<'a>(&'a self, room: &'a Room, directionStr: &str) -> Result<&Room, &str> {
-   |                       ++++  ++              ++
-
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/linkage-attr/common-linkage-non-zero-init.rs b/tests/ui/linkage-attr/common-linkage-non-zero-init.rs
index 61eb4fb66b5..a1fdd5a014c 100644
--- a/tests/ui/linkage-attr/common-linkage-non-zero-init.rs
+++ b/tests/ui/linkage-attr/common-linkage-non-zero-init.rs
@@ -1,6 +1,7 @@
 //@ build-fail
 //@ failure-status: 101
 //@ known-bug: #109681
+//@ ignore-wasm32 this appears to SIGABRT on wasm, not fail cleanly
 
 // This test verifies that we continue to hit the LLVM error for common linkage with non-zero
 // initializers, since it generates invalid LLVM IR.
diff --git a/tests/ui/lint/dead-code/issue-41883.stderr b/tests/ui/lint/dead-code/issue-41883.stderr
index cf079e4dda3..47ccef9a530 100644
--- a/tests/ui/lint/dead-code/issue-41883.stderr
+++ b/tests/ui/lint/dead-code/issue-41883.stderr
@@ -29,8 +29,6 @@ error: struct `UnusedStruct` is never constructed
    |
 LL |     struct UnusedStruct;
    |            ^^^^^^^^^^^^
-   |
-   = note: `UnusedStruct` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr
index b992005318f..25a7d96cb89 100644
--- a/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr
+++ b/tests/ui/lint/dead-code/multiple-dead-codes-in-the-same-struct.stderr
@@ -56,8 +56,6 @@ warning: struct `Foo` is never constructed
    |
 LL | struct Foo(usize, #[allow(unused)] usize);
    |        ^^^
-   |
-   = note: `Foo` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
 
 error: aborting due to 2 previous errors; 2 warnings emitted
 
diff --git a/tests/ui/lint/dead-code/unused-adt-impls-pub-trait.rs b/tests/ui/lint/dead-code/unused-adt-impls-pub-trait.rs
new file mode 100644
index 00000000000..10d6c728c2d
--- /dev/null
+++ b/tests/ui/lint/dead-code/unused-adt-impls-pub-trait.rs
@@ -0,0 +1,17 @@
+#![deny(dead_code)]
+
+enum Foo {} //~ ERROR enum `Foo` is never used
+
+impl Clone for Foo {
+    fn clone(&self) -> Foo { loop {} }
+}
+
+pub trait PubTrait {
+    fn unused_method(&self) -> Self;
+}
+
+impl PubTrait for Foo {
+    fn unused_method(&self) -> Foo { loop {} }
+}
+
+fn main() {}
diff --git a/tests/ui/lint/dead-code/unused-adt-impls-pub-trait.stderr b/tests/ui/lint/dead-code/unused-adt-impls-pub-trait.stderr
new file mode 100644
index 00000000000..f0d0cc50f7d
--- /dev/null
+++ b/tests/ui/lint/dead-code/unused-adt-impls-pub-trait.stderr
@@ -0,0 +1,14 @@
+error: enum `Foo` is never used
+  --> $DIR/unused-adt-impls-pub-trait.rs:3:6
+   |
+LL | enum Foo {}
+   |      ^^^
+   |
+note: the lint level is defined here
+  --> $DIR/unused-adt-impls-pub-trait.rs:1:9
+   |
+LL | #![deny(dead_code)]
+   |         ^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/lint/issue-99387.rs b/tests/ui/lint/issue-99387.rs
index 571d4194fe7..6f082239456 100644
--- a/tests/ui/lint/issue-99387.rs
+++ b/tests/ui/lint/issue-99387.rs
@@ -19,8 +19,8 @@ impl<'a> Tr for &'a () {
 }
 
 pub fn ohno<'a>() -> <&'a () as Tr>::Item {
-    //~^ ERROR item constrains opaque type that is not in its signature
     None.into_iter()
+    //~^ ERROR mismatched types
 }
 
 fn main() {}
diff --git a/tests/ui/lint/issue-99387.stderr b/tests/ui/lint/issue-99387.stderr
index 0005e55324f..4eee4f36392 100644
--- a/tests/ui/lint/issue-99387.stderr
+++ b/tests/ui/lint/issue-99387.stderr
@@ -1,11 +1,17 @@
-error: item constrains opaque type that is not in its signature
-  --> $DIR/issue-99387.rs:21:22
+error[E0308]: mismatched types
+  --> $DIR/issue-99387.rs:22:5
    |
+LL | pub type Successors<'a> = impl Iterator<Item = &'a ()>;
+   |                           ---------------------------- the expected opaque type
+...
 LL | pub fn ohno<'a>() -> <&'a () as Tr>::Item {
-   |                      ^^^^^^^^^^^^^^^^^^^^
+   |                      -------------------- expected `Successors<'a>` because of return type
+LL |     None.into_iter()
+   |     ^^^^^^^^^^^^^^^^ expected opaque type, found `IntoIter<_>`
    |
-   = note: this item must mention the opaque type in its signature in order to be able to register hidden types
-note: this item must mention the opaque type in its signature in order to be able to register hidden types
+   = note: expected opaque type `Successors<'a>`
+                   found struct `std::option::IntoIter<_>`
+note: this item must have the opaque type in its signature in order to be able to register hidden types
   --> $DIR/issue-99387.rs:21:8
    |
 LL | pub fn ohno<'a>() -> <&'a () as Tr>::Item {
@@ -13,3 +19,4 @@ LL | pub fn ohno<'a>() -> <&'a () as Tr>::Item {
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/liveness/liveness-consts.stderr b/tests/ui/liveness/liveness-consts.stderr
index 34ce3947337..ceff62de5d2 100644
--- a/tests/ui/liveness/liveness-consts.stderr
+++ b/tests/ui/liveness/liveness-consts.stderr
@@ -40,12 +40,6 @@ LL |     b += 1;
    = help: maybe it is overwritten before being read?
    = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]`
 
-warning: unused variable: `z`
-  --> $DIR/liveness-consts.rs:60:13
-   |
-LL |         let z = 42;
-   |             ^ help: if this is intentional, prefix it with an underscore: `_z`
-
 warning: value assigned to `t` is never read
   --> $DIR/liveness-consts.rs:42:9
    |
@@ -60,5 +54,11 @@ warning: unused variable: `w`
 LL |         let w = 10;
    |             ^ help: if this is intentional, prefix it with an underscore: `_w`
 
+warning: unused variable: `z`
+  --> $DIR/liveness-consts.rs:60:13
+   |
+LL |         let z = 42;
+   |             ^ help: if this is intentional, prefix it with an underscore: `_z`
+
 warning: 8 warnings emitted
 
diff --git a/tests/ui/liveness/liveness-forgot-ret.stderr b/tests/ui/liveness/liveness-forgot-ret.stderr
index f72a30fc4e9..8f26bbf16d9 100644
--- a/tests/ui/liveness/liveness-forgot-ret.stderr
+++ b/tests/ui/liveness/liveness-forgot-ret.stderr
@@ -1,3 +1,14 @@
+warning: function cannot return without recursing
+  --> $DIR/liveness-forgot-ret.rs:1:1
+   |
+LL | fn god_exists(a: isize) -> bool { return god_exists(a); }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^          ------------- recursive call site
+   | |
+   | cannot return without recursing
+   |
+   = help: a `loop` may express intention better if this is on purpose
+   = note: `#[warn(unconditional_recursion)]` on by default
+
 error[E0308]: mismatched types
   --> $DIR/liveness-forgot-ret.rs:4:19
    |
@@ -11,17 +22,6 @@ help: consider returning the local binding `a`
 LL | fn f(a: isize) -> isize { if god_exists(a) { return 5; }; a }
    |                                                           +
 
-warning: function cannot return without recursing
-  --> $DIR/liveness-forgot-ret.rs:1:1
-   |
-LL | fn god_exists(a: isize) -> bool { return god_exists(a); }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^          ------------- recursive call site
-   | |
-   | cannot return without recursing
-   |
-   = help: a `loop` may express intention better if this is on purpose
-   = note: `#[warn(unconditional_recursion)]` on by default
-
 error: aborting due to 1 previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/liveness/liveness-unused.stderr b/tests/ui/liveness/liveness-unused.stderr
index f6c478ddbc7..9f9be8c897b 100644
--- a/tests/ui/liveness/liveness-unused.stderr
+++ b/tests/ui/liveness/liveness-unused.stderr
@@ -1,18 +1,3 @@
-warning: unreachable statement
-  --> $DIR/liveness-unused.rs:92:9
-   |
-LL |         continue;
-   |         -------- any code following this expression is unreachable
-LL |         drop(*x as i32);
-   |         ^^^^^^^^^^^^^^^^ unreachable statement
-   |
-note: the lint level is defined here
-  --> $DIR/liveness-unused.rs:1:9
-   |
-LL | #![warn(unused)]
-   |         ^^^^^^
-   = note: `#[warn(unreachable_code)]` implied by `#[warn(unused)]`
-
 error: unused variable: `x`
   --> $DIR/liveness-unused.rs:8:7
    |
@@ -90,6 +75,21 @@ error: unused variable: `x`
 LL |     for (x, _) in [1, 2, 3].iter().enumerate() { }
    |          ^ help: if this is intentional, prefix it with an underscore: `_x`
 
+warning: unreachable statement
+  --> $DIR/liveness-unused.rs:92:9
+   |
+LL |         continue;
+   |         -------- any code following this expression is unreachable
+LL |         drop(*x as i32);
+   |         ^^^^^^^^^^^^^^^^ unreachable statement
+   |
+note: the lint level is defined here
+  --> $DIR/liveness-unused.rs:1:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: `#[warn(unreachable_code)]` implied by `#[warn(unused)]`
+
 error: unused variable: `x`
   --> $DIR/liveness-unused.rs:89:13
    |
diff --git a/tests/ui/loops/issue-69225-SCEVAddExpr-wrap-flag.rs b/tests/ui/loops/issue-69225-SCEVAddExpr-wrap-flag.rs
index 881c9e88c46..03717c7c22d 100644
--- a/tests/ui/loops/issue-69225-SCEVAddExpr-wrap-flag.rs
+++ b/tests/ui/loops/issue-69225-SCEVAddExpr-wrap-flag.rs
@@ -1,8 +1,6 @@
 //@ run-fail
 //@ compile-flags: -C opt-level=3
 //@ error-pattern: index out of bounds: the len is 0 but the index is 16777216
-//@ ignore-wasm no panic or subprocess support
-//@ ignore-emscripten no panic or subprocess support
 
 fn do_test(x: usize) {
     let mut arr = vec![vec![0u8; 3]];
diff --git a/tests/ui/loops/issue-69225-layout-repeated-checked-add.rs b/tests/ui/loops/issue-69225-layout-repeated-checked-add.rs
index 9a85d1b01eb..048c7c8872c 100644
--- a/tests/ui/loops/issue-69225-layout-repeated-checked-add.rs
+++ b/tests/ui/loops/issue-69225-layout-repeated-checked-add.rs
@@ -4,8 +4,6 @@
 //@ run-fail
 //@ compile-flags: -C opt-level=3
 //@ error-pattern: index out of bounds: the len is 0 but the index is 16777216
-//@ ignore-wasm no panic or subprocess support
-//@ ignore-emscripten no panic or subprocess support
 
 fn do_test(x: usize) {
     let arr = vec![vec![0u8; 3]];
diff --git a/tests/ui/macros/assert-long-condition.rs b/tests/ui/macros/assert-long-condition.rs
index 424d566e439..1c067438432 100644
--- a/tests/ui/macros/assert-long-condition.rs
+++ b/tests/ui/macros/assert-long-condition.rs
@@ -1,7 +1,6 @@
 //@ run-fail
 //@ check-run-results
 //@ exec-env:RUST_BACKTRACE=0
-//@ ignore-emscripten no processes
 // ignore-tidy-linelength
 
 fn main() {
diff --git a/tests/ui/macros/assert-long-condition.run.stderr b/tests/ui/macros/assert-long-condition.run.stderr
index 16e56c92735..5c0ff357cb7 100644
--- a/tests/ui/macros/assert-long-condition.run.stderr
+++ b/tests/ui/macros/assert-long-condition.run.stderr
@@ -1,4 +1,4 @@
-thread 'main' panicked at $DIR/assert-long-condition.rs:8:5:
+thread 'main' panicked at $DIR/assert-long-condition.rs:7:5:
 assertion failed: 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18
                                 + 19 + 20 + 21 + 22 + 23 + 24 + 25 == 0
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
diff --git a/tests/ui/macros/macros-in-extern.rs b/tests/ui/macros/macros-in-extern.rs
index 363ff5df64a..97780650d11 100644
--- a/tests/ui/macros/macros-in-extern.rs
+++ b/tests/ui/macros/macros-in-extern.rs
@@ -1,5 +1,4 @@
 //@ run-pass
-//@ ignore-wasm32
 
 #![feature(decl_macro)]
 
diff --git a/tests/ui/mir/alignment/misaligned_lhs.rs b/tests/ui/mir/alignment/misaligned_lhs.rs
index 5f484b8b3be..b169823bc08 100644
--- a/tests/ui/mir/alignment/misaligned_lhs.rs
+++ b/tests/ui/mir/alignment/misaligned_lhs.rs
@@ -1,5 +1,4 @@
 //@ run-fail
-//@ ignore-wasm32-bare: No panic messages
 //@ ignore-i686-pc-windows-msvc: #112480
 //@ compile-flags: -C debug-assertions
 //@ error-pattern: misaligned pointer dereference: address must be a multiple of 0x4 but is
diff --git a/tests/ui/mir/alignment/misaligned_rhs.rs b/tests/ui/mir/alignment/misaligned_rhs.rs
index ca63a4711cd..55da30a2fd7 100644
--- a/tests/ui/mir/alignment/misaligned_rhs.rs
+++ b/tests/ui/mir/alignment/misaligned_rhs.rs
@@ -1,5 +1,4 @@
 //@ run-fail
-//@ ignore-wasm32-bare: No panic messages
 //@ ignore-i686-pc-windows-msvc: #112480
 //@ compile-flags: -C debug-assertions
 //@ error-pattern: misaligned pointer dereference: address must be a multiple of 0x4 but is
diff --git a/tests/ui/mir/alignment/two_pointers.rs b/tests/ui/mir/alignment/two_pointers.rs
index 68bf45c6e70..198a1c9853d 100644
--- a/tests/ui/mir/alignment/two_pointers.rs
+++ b/tests/ui/mir/alignment/two_pointers.rs
@@ -1,5 +1,4 @@
 //@ run-fail
-//@ ignore-wasm32-bare: No panic messages
 //@ ignore-i686-pc-windows-msvc: #112480
 //@ compile-flags: -C debug-assertions
 //@ error-pattern: misaligned pointer dereference: address must be a multiple of 0x4 but is
diff --git a/tests/ui/never_type/never-from-impl-is-reserved.current.stderr b/tests/ui/never_type/never-from-impl-is-reserved.current.stderr
index d008f88c188..7868206950c 100644
--- a/tests/ui/never_type/never-from-impl-is-reserved.current.stderr
+++ b/tests/ui/never_type/never-from-impl-is-reserved.current.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `MyTrait` for type `MyFoo`
-  --> $DIR/never-from-impl-is-reserved.rs:13:1
+  --> $DIR/never-from-impl-is-reserved.rs:14:1
    |
 LL | impl MyTrait for MyFoo {}
    | ---------------------- first implementation here
diff --git a/tests/ui/never_type/never-from-impl-is-reserved.next.stderr b/tests/ui/never_type/never-from-impl-is-reserved.next.stderr
index d008f88c188..7868206950c 100644
--- a/tests/ui/never_type/never-from-impl-is-reserved.next.stderr
+++ b/tests/ui/never_type/never-from-impl-is-reserved.next.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `MyTrait` for type `MyFoo`
-  --> $DIR/never-from-impl-is-reserved.rs:13:1
+  --> $DIR/never-from-impl-is-reserved.rs:14:1
    |
 LL | impl MyTrait for MyFoo {}
    | ---------------------- first implementation here
diff --git a/tests/ui/never_type/never-from-impl-is-reserved.rs b/tests/ui/never_type/never-from-impl-is-reserved.rs
index 26d194144f6..c673462f296 100644
--- a/tests/ui/never_type/never-from-impl-is-reserved.rs
+++ b/tests/ui/never_type/never-from-impl-is-reserved.rs
@@ -1,6 +1,7 @@
 // check that the `for<T> T: From<!>` impl is reserved
 
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver=coherence
 
 #![feature(never_type)]
diff --git a/tests/ui/nll/issue-53119.rs b/tests/ui/nll/issue-53119.rs
index e7c97c854af..e699a6f9fd7 100644
--- a/tests/ui/nll/issue-53119.rs
+++ b/tests/ui/nll/issue-53119.rs
@@ -1,5 +1,6 @@
 //@ check-pass
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 use std::ops::Deref;
diff --git a/tests/ui/non-copyable-void.rs b/tests/ui/non-copyable-void.rs
index 8089f5e2218..58668147801 100644
--- a/tests/ui/non-copyable-void.rs
+++ b/tests/ui/non-copyable-void.rs
@@ -1,5 +1,3 @@
-//@ ignore-wasm32-bare no libc to test ffi with
-
 #![feature(rustc_private)]
 
 extern crate libc;
diff --git a/tests/ui/non-copyable-void.stderr b/tests/ui/non-copyable-void.stderr
index bef1e1077eb..d25bb8c17ee 100644
--- a/tests/ui/non-copyable-void.stderr
+++ b/tests/ui/non-copyable-void.stderr
@@ -1,5 +1,5 @@
 error[E0599]: no method named `clone` found for enum `c_void` in the current scope
-  --> $DIR/non-copyable-void.rs:11:23
+  --> $DIR/non-copyable-void.rs:9:23
    |
 LL |         let _z = (*y).clone();
    |                       ^^^^^ method not found in `c_void`
diff --git a/tests/ui/numbers-arithmetic/location-add-assign-overflow.rs b/tests/ui/numbers-arithmetic/location-add-assign-overflow.rs
index 654e54a1591..8014bae2889 100644
--- a/tests/ui/numbers-arithmetic/location-add-assign-overflow.rs
+++ b/tests/ui/numbers-arithmetic/location-add-assign-overflow.rs
@@ -1,5 +1,4 @@
 //@ run-fail
-//@ ignore-wasm32
 //@ error-pattern:location-add-assign-overflow.rs
 
 fn main() {
diff --git a/tests/ui/numbers-arithmetic/location-add-overflow.rs b/tests/ui/numbers-arithmetic/location-add-overflow.rs
index 65452e2c2c2..0d2e52d532e 100644
--- a/tests/ui/numbers-arithmetic/location-add-overflow.rs
+++ b/tests/ui/numbers-arithmetic/location-add-overflow.rs
@@ -1,5 +1,4 @@
 //@ run-fail
-//@ ignore-wasm32
 //@ error-pattern:location-add-overflow.rs
 
 fn main() {
diff --git a/tests/ui/numbers-arithmetic/location-divide-assign-by-zero.rs b/tests/ui/numbers-arithmetic/location-divide-assign-by-zero.rs
index 8bce8ded5da..63fbab5ecc4 100644
--- a/tests/ui/numbers-arithmetic/location-divide-assign-by-zero.rs
+++ b/tests/ui/numbers-arithmetic/location-divide-assign-by-zero.rs
@@ -1,5 +1,4 @@
 //@ run-fail
-//@ ignore-wasm32
 //@ error-pattern:location-divide-assign-by-zero.rs
 
 fn main() {
diff --git a/tests/ui/numbers-arithmetic/location-divide-by-zero.rs b/tests/ui/numbers-arithmetic/location-divide-by-zero.rs
index 180f72eb6f4..88c1b51c1bb 100644
--- a/tests/ui/numbers-arithmetic/location-divide-by-zero.rs
+++ b/tests/ui/numbers-arithmetic/location-divide-by-zero.rs
@@ -1,5 +1,4 @@
 //@ run-fail
-//@ ignore-wasm32
 //@ error-pattern:location-divide-by-zero.rs
 
 // https://github.com/rust-lang/rust/issues/114814
diff --git a/tests/ui/numbers-arithmetic/location-mod-assign-by-zero.rs b/tests/ui/numbers-arithmetic/location-mod-assign-by-zero.rs
index bc4377eb679..ae62f5c26d9 100644
--- a/tests/ui/numbers-arithmetic/location-mod-assign-by-zero.rs
+++ b/tests/ui/numbers-arithmetic/location-mod-assign-by-zero.rs
@@ -1,5 +1,4 @@
 //@ run-fail
-//@ ignore-wasm32
 //@ error-pattern:location-mod-assign-by-zero.rs
 
 fn main() {
diff --git a/tests/ui/numbers-arithmetic/location-mod-by-zero.rs b/tests/ui/numbers-arithmetic/location-mod-by-zero.rs
index 2f176013db2..6a2e1b158bf 100644
--- a/tests/ui/numbers-arithmetic/location-mod-by-zero.rs
+++ b/tests/ui/numbers-arithmetic/location-mod-by-zero.rs
@@ -1,5 +1,4 @@
 //@ run-fail
-//@ ignore-wasm32
 //@ error-pattern:location-mod-by-zero.rs
 
 fn main() {
diff --git a/tests/ui/numbers-arithmetic/location-mul-assign-overflow.rs b/tests/ui/numbers-arithmetic/location-mul-assign-overflow.rs
index 33de927b034..07cec7d1730 100644
--- a/tests/ui/numbers-arithmetic/location-mul-assign-overflow.rs
+++ b/tests/ui/numbers-arithmetic/location-mul-assign-overflow.rs
@@ -1,5 +1,4 @@
 //@ run-fail
-//@ ignore-wasm32
 //@ error-pattern:location-mul-assign-overflow.rs
 
 fn main() {
diff --git a/tests/ui/numbers-arithmetic/location-mul-overflow.rs b/tests/ui/numbers-arithmetic/location-mul-overflow.rs
index 8d93406ba50..0a00d3beaa7 100644
--- a/tests/ui/numbers-arithmetic/location-mul-overflow.rs
+++ b/tests/ui/numbers-arithmetic/location-mul-overflow.rs
@@ -1,5 +1,4 @@
 //@ run-fail
-//@ ignore-wasm32
 //@ error-pattern:location-mul-overflow.rs
 
 fn main() {
diff --git a/tests/ui/numbers-arithmetic/location-sub-assign-overflow.rs b/tests/ui/numbers-arithmetic/location-sub-assign-overflow.rs
index 1bc1a9b2d66..13f074b0ffe 100644
--- a/tests/ui/numbers-arithmetic/location-sub-assign-overflow.rs
+++ b/tests/ui/numbers-arithmetic/location-sub-assign-overflow.rs
@@ -1,5 +1,4 @@
 //@ run-fail
-//@ ignore-wasm32
 //@ error-pattern:location-sub-assign-overflow.rs
 
 fn main() {
diff --git a/tests/ui/numbers-arithmetic/location-sub-overflow.rs b/tests/ui/numbers-arithmetic/location-sub-overflow.rs
index 911b2815a00..9a0fabe1cd6 100644
--- a/tests/ui/numbers-arithmetic/location-sub-overflow.rs
+++ b/tests/ui/numbers-arithmetic/location-sub-overflow.rs
@@ -1,5 +1,4 @@
 //@ run-fail
-//@ ignore-wasm32
 //@ error-pattern:location-sub-overflow.rs
 
 fn main() {
diff --git a/tests/ui/object-safety/call-when-assoc-ty-is-sized.rs b/tests/ui/object-safety/call-when-assoc-ty-is-sized.rs
index b8445849169..7a3a7f3ca2f 100644
--- a/tests/ui/object-safety/call-when-assoc-ty-is-sized.rs
+++ b/tests/ui/object-safety/call-when-assoc-ty-is-sized.rs
@@ -1,5 +1,6 @@
 //@ check-pass
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 trait Foo {
diff --git a/tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs b/tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs
index 4f8efd6d688..11e4929f12e 100644
--- a/tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs
+++ b/tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs
@@ -3,7 +3,7 @@
 //@ compile-flags:-C panic=abort
 //@ aux-build:exit-success-if-unwind.rs
 //@ no-prefer-dynamic
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 //@ ignore-macos
 
diff --git a/tests/ui/panic-runtime/abort.rs b/tests/ui/panic-runtime/abort.rs
index 810e13c9762..22bd2ecfb00 100644
--- a/tests/ui/panic-runtime/abort.rs
+++ b/tests/ui/panic-runtime/abort.rs
@@ -2,7 +2,7 @@
 #![allow(unused_variables)]
 //@ compile-flags:-C panic=abort
 //@ no-prefer-dynamic
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 //@ ignore-macos
 
diff --git a/tests/ui/panic-runtime/lto-abort.rs b/tests/ui/panic-runtime/lto-abort.rs
index 1d2aed12b9b..c66b6a60c73 100644
--- a/tests/ui/panic-runtime/lto-abort.rs
+++ b/tests/ui/panic-runtime/lto-abort.rs
@@ -2,7 +2,7 @@
 #![allow(unused_variables)]
 //@ compile-flags:-C lto -C panic=abort
 //@ no-prefer-dynamic
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 
 use std::process::Command;
diff --git a/tests/ui/panics/abort-on-panic.rs b/tests/ui/panics/abort-on-panic.rs
index 4929cdab1c2..5736ecf8685 100644
--- a/tests/ui/panics/abort-on-panic.rs
+++ b/tests/ui/panics/abort-on-panic.rs
@@ -1,5 +1,6 @@
 //@ run-pass
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 #![allow(unused_must_use)]
@@ -8,7 +9,7 @@
 // Since we mark some ABIs as "nounwind" to LLVM, we must make sure that
 // we never unwind through them.
 
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 
 use std::io;
diff --git a/tests/ui/panics/runtime-switch.rs b/tests/ui/panics/runtime-switch.rs
index b0991321ee4..a4ef0dcd8a2 100644
--- a/tests/ui/panics/runtime-switch.rs
+++ b/tests/ui/panics/runtime-switch.rs
@@ -9,7 +9,7 @@
 //@ ignore-msvc see #62897 and `backtrace-debuginfo.rs` test
 //@ ignore-android FIXME #17520
 //@ ignore-openbsd no support for libbacktrace without filename
-//@ ignore-wasm no panic or subprocess support
+//@ ignore-wasm no backtrace support
 //@ ignore-emscripten no panic or subprocess support
 //@ ignore-sgx no subprocess support
 //@ ignore-fuchsia Backtrace not symbolized
diff --git a/tests/ui/panics/short-ice-remove-middle-frames-2.rs b/tests/ui/panics/short-ice-remove-middle-frames-2.rs
index 15843fa6626..6caad2212d4 100644
--- a/tests/ui/panics/short-ice-remove-middle-frames-2.rs
+++ b/tests/ui/panics/short-ice-remove-middle-frames-2.rs
@@ -4,7 +4,6 @@
 //@ exec-env:RUST_BACKTRACE=1
 //@ needs-unwind
 //@ ignore-android FIXME #17520
-//@ ignore-wasm no panic support
 //@ ignore-openbsd no support for libbacktrace without filename
 //@ ignore-emscripten no panic
 //@ ignore-sgx Backtraces not symbolized
diff --git a/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr b/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr
index 664ebaa4c51..2b648a0cad2 100644
--- a/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr
+++ b/tests/ui/panics/short-ice-remove-middle-frames-2.run.stderr
@@ -1,4 +1,4 @@
-thread 'main' panicked at $DIR/short-ice-remove-middle-frames-2.rs:57:5:
+thread 'main' panicked at $DIR/short-ice-remove-middle-frames-2.rs:56:5:
 debug!!!
 stack backtrace:
    0: std::panicking::begin_panic
diff --git a/tests/ui/panics/short-ice-remove-middle-frames.rs b/tests/ui/panics/short-ice-remove-middle-frames.rs
index 204780459b3..5f275d13cc4 100644
--- a/tests/ui/panics/short-ice-remove-middle-frames.rs
+++ b/tests/ui/panics/short-ice-remove-middle-frames.rs
@@ -4,7 +4,6 @@
 //@ exec-env:RUST_BACKTRACE=1
 //@ needs-unwind
 //@ ignore-android FIXME #17520
-//@ ignore-wasm no panic support
 //@ ignore-openbsd no support for libbacktrace without filename
 //@ ignore-emscripten no panic
 //@ ignore-sgx Backtraces not symbolized
diff --git a/tests/ui/panics/short-ice-remove-middle-frames.run.stderr b/tests/ui/panics/short-ice-remove-middle-frames.run.stderr
index bc252fde1f6..5b372684096 100644
--- a/tests/ui/panics/short-ice-remove-middle-frames.run.stderr
+++ b/tests/ui/panics/short-ice-remove-middle-frames.run.stderr
@@ -1,4 +1,4 @@
-thread 'main' panicked at $DIR/short-ice-remove-middle-frames.rs:53:5:
+thread 'main' panicked at $DIR/short-ice-remove-middle-frames.rs:52:5:
 debug!!!
 stack backtrace:
    0: std::panicking::begin_panic
diff --git a/tests/ui/panics/test-should-fail-bad-message.rs b/tests/ui/panics/test-should-fail-bad-message.rs
index 9d8084053cc..1fb2da9055b 100644
--- a/tests/ui/panics/test-should-fail-bad-message.rs
+++ b/tests/ui/panics/test-should-fail-bad-message.rs
@@ -1,7 +1,7 @@
 //@ run-fail
 //@ check-stdout
 //@ compile-flags: --test
-//@ ignore-emscripten
+//@ needs-unwind
 
 #[test]
 #[should_panic(expected = "foobar")]
diff --git a/tests/ui/panics/test-should-panic-bad-message.rs b/tests/ui/panics/test-should-panic-bad-message.rs
index 4f39412af5f..1a3c52ea176 100644
--- a/tests/ui/panics/test-should-panic-bad-message.rs
+++ b/tests/ui/panics/test-should-panic-bad-message.rs
@@ -1,7 +1,7 @@
 //@ run-fail
 //@ compile-flags: --test
 //@ check-stdout
-//@ ignore-emscripten no processes
+//@ needs-unwind
 
 #[test]
 #[should_panic(expected = "foo")]
diff --git a/tests/ui/panics/test-should-panic-no-message.rs b/tests/ui/panics/test-should-panic-no-message.rs
index 8bbcbe9fa59..b6ed6b19dd0 100644
--- a/tests/ui/panics/test-should-panic-no-message.rs
+++ b/tests/ui/panics/test-should-panic-no-message.rs
@@ -1,7 +1,7 @@
 //@ run-fail
 //@ compile-flags: --test
 //@ check-stdout
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 
 #[test]
 #[should_panic(expected = "foo")]
diff --git a/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-1.rs b/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-1.rs
new file mode 100644
index 00000000000..5de3b401ab4
--- /dev/null
+++ b/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-1.rs
@@ -0,0 +1,14 @@
+fn main() {
+  foo::( //~ HELP: consider removing the `::` here to call the expression
+    //~^ NOTE: while parsing this parenthesized list of type arguments starting
+    bar(x, y, z),
+    bar(x, y, z),
+    bar(x, y, z),
+    bar(x, y, z),
+    bar(x, y, z),
+    bar(x, y, z),
+    bar(x, y, z),
+    baz("test"), //~ ERROR: expected type, found `"test"`
+    //~^ NOTE: expected type
+  )
+}
diff --git a/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-1.stderr b/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-1.stderr
new file mode 100644
index 00000000000..60e57a3629c
--- /dev/null
+++ b/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-1.stderr
@@ -0,0 +1,17 @@
+error: expected type, found `"test"`
+  --> $DIR/diagnostics-parenthesized-type-arguments-issue-120892-1.rs:11:9
+   |
+LL |   foo::(
+   |      --- while parsing this parenthesized list of type arguments starting here
+...
+LL |     baz("test"),
+   |         ^^^^^^ expected type
+   |
+help: consider removing the `::` here to call the expression
+   |
+LL -   foo::(
+LL +   foo(
+   |
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-2.rs b/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-2.rs
new file mode 100644
index 00000000000..2876a9afe00
--- /dev/null
+++ b/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-2.rs
@@ -0,0 +1,5 @@
+fn main() {
+  foo::/* definitely not harmful comment */(123, "foo") -> (u32); //~ ERROR: expected type, found `123`
+  //~^ NOTE: while parsing this parenthesized list of type arguments starting
+  //~^^ NOTE: expected type
+}
diff --git a/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-2.stderr b/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-2.stderr
new file mode 100644
index 00000000000..7fd2b6b18e3
--- /dev/null
+++ b/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-2.stderr
@@ -0,0 +1,10 @@
+error: expected type, found `123`
+  --> $DIR/diagnostics-parenthesized-type-arguments-issue-120892-2.rs:2:45
+   |
+LL |   foo::/* definitely not harmful comment */(123, "foo") -> (u32);
+   |      ---------------------------------------^^^ expected type
+   |      |
+   |      while parsing this parenthesized list of type arguments starting here
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-3.rs b/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-3.rs
new file mode 100644
index 00000000000..402afac46de
--- /dev/null
+++ b/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-3.rs
@@ -0,0 +1,14 @@
+struct Foo(u32, u32);
+impl Foo {
+    fn foo(&self) {
+        match *self {
+            Foo::(1, 2) => {}, //~ HELP: consider removing the `::` here to turn this into a tuple struct pattern
+            //~^ NOTE: while parsing this parenthesized list of type arguments starting
+            //~^^ ERROR: expected type, found `1`
+            //~^^^ NOTE: expected type
+             _ => {},
+        }
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-3.stderr b/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-3.stderr
new file mode 100644
index 00000000000..72770ca265d
--- /dev/null
+++ b/tests/ui/parser/issues/diagnostics-parenthesized-type-arguments-issue-120892-3.stderr
@@ -0,0 +1,16 @@
+error: expected type, found `1`
+  --> $DIR/diagnostics-parenthesized-type-arguments-issue-120892-3.rs:5:19
+   |
+LL |             Foo::(1, 2) => {},
+   |                ---^ expected type
+   |                |
+   |                while parsing this parenthesized list of type arguments starting here
+   |
+help: consider removing the `::` here to turn this into a tuple struct pattern
+   |
+LL -             Foo::(1, 2) => {},
+LL +             Foo(1, 2) => {},
+   |
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/paths-containing-nul.rs b/tests/ui/paths-containing-nul.rs
index 23ea84bc33f..5c37980127d 100644
--- a/tests/ui/paths-containing-nul.rs
+++ b/tests/ui/paths-containing-nul.rs
@@ -1,8 +1,7 @@
 //@ run-pass
 
 #![allow(deprecated)]
-//@ ignore-wasm32-bare no files or I/O
-//@ ignore-emscripten no files
+//@ ignore-wasm32 no cwd
 //@ ignore-sgx no files
 
 use std::fs;
diff --git a/tests/ui/precondition-checks/misaligned-slice.rs b/tests/ui/precondition-checks/misaligned-slice.rs
index d105154ecd8..52c149b594e 100644
--- a/tests/ui/precondition-checks/misaligned-slice.rs
+++ b/tests/ui/precondition-checks/misaligned-slice.rs
@@ -2,7 +2,6 @@
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=yes
 //@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts
 //@ ignore-debug
-//@ ignore-wasm32-bare no panic messages
 
 fn main() {
     unsafe {
diff --git a/tests/ui/precondition-checks/null-slice.rs b/tests/ui/precondition-checks/null-slice.rs
index 4347b85875d..61c7d467649 100644
--- a/tests/ui/precondition-checks/null-slice.rs
+++ b/tests/ui/precondition-checks/null-slice.rs
@@ -2,7 +2,6 @@
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=yes
 //@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts
 //@ ignore-debug
-//@ ignore-wasm32-bare no panic messages
 
 fn main() {
     unsafe {
diff --git a/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs b/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs
index 77bec6aab7f..ba02c3da7b2 100644
--- a/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs
+++ b/tests/ui/precondition-checks/out-of-bounds-get-unchecked.rs
@@ -2,7 +2,6 @@
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=yes
 //@ error-pattern: slice::get_unchecked requires
 //@ ignore-debug
-//@ ignore-wasm32-bare no panic messages
 
 fn main() {
     unsafe {
diff --git a/tests/ui/print-stdout-eprint-stderr.rs b/tests/ui/print-stdout-eprint-stderr.rs
index e676a9ad1af..e84a9bebc49 100644
--- a/tests/ui/print-stdout-eprint-stderr.rs
+++ b/tests/ui/print-stdout-eprint-stderr.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten spawning processes is not supported
+//@ ignore-wasm32 spawning processes is not supported
 //@ ignore-sgx no processes
 
 use std::{env, process};
diff --git a/tests/ui/privacy/pub-extern-privacy.rs b/tests/ui/privacy/pub-extern-privacy.rs
index b6c18bd1ee7..dc5e8951bfc 100644
--- a/tests/ui/privacy/pub-extern-privacy.rs
+++ b/tests/ui/privacy/pub-extern-privacy.rs
@@ -1,5 +1,4 @@
 //@ run-pass
-//@ ignore-wasm32-bare no libc to test ffi with
 
 //@ pretty-expanded FIXME #23616
 
diff --git a/tests/ui/proc-macro/crt-static.rs b/tests/ui/proc-macro/crt-static.rs
index 546d30dbad7..0874c4e8a38 100644
--- a/tests/ui/proc-macro/crt-static.rs
+++ b/tests/ui/proc-macro/crt-static.rs
@@ -2,7 +2,6 @@
 // on musl target
 // override -Ctarget-feature=-crt-static from compiletest
 //@ compile-flags: --crate-type proc-macro -Ctarget-feature=
-//@ ignore-wasm32
 //@ ignore-sgx no support for proc-macro crate type
 //@ build-pass
 //@ force-host
diff --git a/tests/ui/proc-macro/macros-in-extern.rs b/tests/ui/proc-macro/macros-in-extern.rs
index 82ab7b506ba..da384d1b141 100644
--- a/tests/ui/proc-macro/macros-in-extern.rs
+++ b/tests/ui/proc-macro/macros-in-extern.rs
@@ -1,6 +1,5 @@
 //@ run-pass
 //@ aux-build:test-macros.rs
-//@ ignore-wasm32
 
 #[macro_use]
 extern crate test_macros;
diff --git a/tests/ui/process/core-run-destroy.rs b/tests/ui/process/core-run-destroy.rs
index 42bb35edf3b..338203657bd 100644
--- a/tests/ui/process/core-run-destroy.rs
+++ b/tests/ui/process/core-run-destroy.rs
@@ -5,7 +5,7 @@
 #![allow(deprecated)]
 #![allow(unused_imports)]
 //@ compile-flags:--test
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 //@ ignore-vxworks no 'cat' and 'sleep'
 //@ ignore-fuchsia no 'cat'
diff --git a/tests/ui/process/fds-are-cloexec.rs b/tests/ui/process/fds-are-cloexec.rs
index a5ede2ee04d..e7b000b2c49 100644
--- a/tests/ui/process/fds-are-cloexec.rs
+++ b/tests/ui/process/fds-are-cloexec.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 //@ ignore-windows
 //@ ignore-android
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-haiku
 //@ ignore-sgx no processes
 
diff --git a/tests/ui/process/issue-13304.rs b/tests/ui/process/issue-13304.rs
index 06aad569169..6dbf0caaaec 100644
--- a/tests/ui/process/issue-13304.rs
+++ b/tests/ui/process/issue-13304.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 #![allow(unused_mut)]
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 
 use std::env;
diff --git a/tests/ui/process/issue-14456.rs b/tests/ui/process/issue-14456.rs
index 9146588aa4b..fd6da8a5fc4 100644
--- a/tests/ui/process/issue-14456.rs
+++ b/tests/ui/process/issue-14456.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 #![allow(unused_mut)]
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 
 use std::env;
diff --git a/tests/ui/process/issue-14940.rs b/tests/ui/process/issue-14940.rs
index 3c8de7cfccc..13fb18154a0 100644
--- a/tests/ui/process/issue-14940.rs
+++ b/tests/ui/process/issue-14940.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 
 use std::env;
diff --git a/tests/ui/process/issue-16272.rs b/tests/ui/process/issue-16272.rs
index 484c3ea4116..bf26769d494 100644
--- a/tests/ui/process/issue-16272.rs
+++ b/tests/ui/process/issue-16272.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 
 use std::process::Command;
diff --git a/tests/ui/process/issue-20091.rs b/tests/ui/process/issue-20091.rs
index 27986277fad..b6d94661b75 100644
--- a/tests/ui/process/issue-20091.rs
+++ b/tests/ui/process/issue-20091.rs
@@ -1,7 +1,6 @@
 //@ run-pass
 #![allow(stable_features)]
-
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 
 #![feature(os)]
diff --git a/tests/ui/process/multi-panic.rs b/tests/ui/process/multi-panic.rs
index e8aa7f59f85..02b69903654 100644
--- a/tests/ui/process/multi-panic.rs
+++ b/tests/ui/process/multi-panic.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 //@ needs-unwind
 
diff --git a/tests/ui/process/no-stdio.rs b/tests/ui/process/no-stdio.rs
index 86e177617e5..05b1e52b799 100644
--- a/tests/ui/process/no-stdio.rs
+++ b/tests/ui/process/no-stdio.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 //@ ignore-android
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 
 #![feature(rustc_private)]
diff --git a/tests/ui/process/println-with-broken-pipe.rs b/tests/ui/process/println-with-broken-pipe.rs
index bfbea280f0b..1df8c765cbd 100644
--- a/tests/ui/process/println-with-broken-pipe.rs
+++ b/tests/ui/process/println-with-broken-pipe.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 //@ check-run-results
 //@ ignore-windows
-//@ ignore-emscripten
+//@ ignore-wasm32
 //@ ignore-fuchsia
 //@ ignore-horizon
 //@ ignore-android
diff --git a/tests/ui/process/process-envs.rs b/tests/ui/process/process-envs.rs
index 6f8a591b7d4..15285960d16 100644
--- a/tests/ui/process/process-envs.rs
+++ b/tests/ui/process/process-envs.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 //@ ignore-vxworks no 'env'
 //@ ignore-fuchsia no 'env'
diff --git a/tests/ui/process/process-exit.rs b/tests/ui/process/process-exit.rs
index 7cf1f2bccc3..a75a7306cbc 100644
--- a/tests/ui/process/process-exit.rs
+++ b/tests/ui/process/process-exit.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 #![allow(unused_imports)]
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 
 use std::env;
diff --git a/tests/ui/process/process-panic-after-fork.rs b/tests/ui/process/process-panic-after-fork.rs
index 0115dbd27ef..bae121576bd 100644
--- a/tests/ui/process/process-panic-after-fork.rs
+++ b/tests/ui/process/process-panic-after-fork.rs
@@ -1,9 +1,7 @@
 //@ run-pass
 //@ no-prefer-dynamic
-//@ ignore-wasm32-bare no libc
 //@ ignore-windows
-//@ ignore-sgx no libc
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 //@ ignore-fuchsia no fork
 
diff --git a/tests/ui/process/process-remove-from-env.rs b/tests/ui/process/process-remove-from-env.rs
index abacccf5a8a..21fff4fd45d 100644
--- a/tests/ui/process/process-remove-from-env.rs
+++ b/tests/ui/process/process-remove-from-env.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 //@ ignore-vxworks no 'env'
 //@ ignore-fuchsia no 'env'
diff --git a/tests/ui/process/process-sigpipe.rs b/tests/ui/process/process-sigpipe.rs
index 64d0bbc2b41..11f363d625f 100644
--- a/tests/ui/process/process-sigpipe.rs
+++ b/tests/ui/process/process-sigpipe.rs
@@ -13,7 +13,6 @@
 // (instead of running forever), and that it does not print an error
 // message about a broken pipe.
 
-//@ ignore-emscripten no threads support
 //@ ignore-vxworks no 'sh'
 //@ ignore-fuchsia no 'sh'
 
diff --git a/tests/ui/process/process-spawn-nonexistent.rs b/tests/ui/process/process-spawn-nonexistent.rs
index 2f45dace2f9..1cd32866299 100644
--- a/tests/ui/process/process-spawn-nonexistent.rs
+++ b/tests/ui/process/process-spawn-nonexistent.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 //@ ignore-fuchsia ErrorKind not translated
 
diff --git a/tests/ui/process/process-spawn-with-unicode-params.rs b/tests/ui/process/process-spawn-with-unicode-params.rs
index 26b3899df96..4d2ba49eeac 100644
--- a/tests/ui/process/process-spawn-with-unicode-params.rs
+++ b/tests/ui/process/process-spawn-with-unicode-params.rs
@@ -7,7 +7,7 @@
 // non-ASCII characters.  The child process ensures all the strings are
 // intact.
 
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 //@ ignore-fuchsia Filesystem manipulation privileged
 
diff --git a/tests/ui/process/process-status-inherits-stdin.rs b/tests/ui/process/process-status-inherits-stdin.rs
index 210968a6ce5..39eef34c5f8 100644
--- a/tests/ui/process/process-status-inherits-stdin.rs
+++ b/tests/ui/process/process-status-inherits-stdin.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 
 use std::env;
diff --git a/tests/ui/process/signal-exit-status.rs b/tests/ui/process/signal-exit-status.rs
index 5efef8a6121..a6acea47636 100644
--- a/tests/ui/process/signal-exit-status.rs
+++ b/tests/ui/process/signal-exit-status.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 //@ ignore-windows
 //@ ignore-fuchsia code returned as ZX_TASK_RETCODE_EXCEPTION_KILL, FIXME (#58590)
diff --git a/tests/ui/process/sigpipe-should-be-ignored.rs b/tests/ui/process/sigpipe-should-be-ignored.rs
index cd6bda27646..44785bee7f8 100644
--- a/tests/ui/process/sigpipe-should-be-ignored.rs
+++ b/tests/ui/process/sigpipe-should-be-ignored.rs
@@ -4,7 +4,7 @@
 // Be sure that when a SIGPIPE would have been received that the entire process
 // doesn't die in a ball of fire, but rather it's gracefully handled.
 
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 
 use std::env;
diff --git a/tests/ui/process/tls-exit-status.rs b/tests/ui/process/tls-exit-status.rs
index 5a81c7708fe..cddcf369da0 100644
--- a/tests/ui/process/tls-exit-status.rs
+++ b/tests/ui/process/tls-exit-status.rs
@@ -1,7 +1,7 @@
 //@ run-fail
 //@ error-pattern:nonzero
 //@ exec-env:RUST_NEWRT=1
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 
 use std::env;
 
diff --git a/tests/ui/process/try-wait.rs b/tests/ui/process/try-wait.rs
index 948ce63c76c..b6d026d802f 100644
--- a/tests/ui/process/try-wait.rs
+++ b/tests/ui/process/try-wait.rs
@@ -1,9 +1,8 @@
 //@ run-pass
 
 #![allow(stable_features)]
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
-
 #![feature(process_try_wait)]
 
 use std::env;
diff --git a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr
index 5a02d01b4e1..ab13b4876b1 100644
--- a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr
+++ b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr
@@ -1,14 +1,3 @@
-error[E0308]: mismatched types
-  --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:43
-   |
-LL |     let _: fn(&mut &isize, &mut &isize) = a;
-   |            ----------------------------   ^ one type is more general than the other
-   |            |
-   |            expected due to this
-   |
-   = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b _, &'c mut &'d _)`
-                 found fn item `for<'a, 'b> fn(&'a mut &_, &'b mut &_) {a::<'_, '_>}`
-
 error: lifetime may not live long enough
   --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:8:5
    |
@@ -38,6 +27,17 @@ LL |     a(x, y);
    = note: mutable references are invariant over their type parameter
    = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
+error[E0308]: mismatched types
+  --> $DIR/region-lifetime-bounds-on-fns-where-clause.rs:20:43
+   |
+LL |     let _: fn(&mut &isize, &mut &isize) = a;
+   |            ----------------------------   ^ one type is more general than the other
+   |            |
+   |            expected due to this
+   |
+   = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b _, &'c mut &'d _)`
+                 found fn item `for<'a, 'b> fn(&'a mut &_, &'b mut &_) {a::<'_, '_>}`
+
 error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr
index 063ff46bb6c..f1ed0a6bb15 100644
--- a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr
+++ b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr
@@ -1,14 +1,3 @@
-error[E0308]: mismatched types
-  --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:56
-   |
-LL |     let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
-   |            -----------------------------------------   ^ one type is more general than the other
-   |            |
-   |            expected due to this
-   |
-   = note: expected fn pointer `for<'a, 'b, 'c, 'd, 'e, 'f> fn(&'a mut &'b _, &'c mut &'d _, &'e mut &'f _)`
-                 found fn item `for<'a, 'b, 'c> fn(&'a mut &_, &'b mut &_, &'c mut &_) {a::<'_, '_, '_>}`
-
 error: lifetime may not live long enough
   --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:9:5
    |
@@ -38,6 +27,17 @@ LL |     a(x, y, z);
    = note: mutable references are invariant over their type parameter
    = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
+error[E0308]: mismatched types
+  --> $DIR/region-multiple-lifetime-bounds-on-fns-where-clause.rs:22:56
+   |
+LL |     let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
+   |            -----------------------------------------   ^ one type is more general than the other
+   |            |
+   |            expected due to this
+   |
+   = note: expected fn pointer `for<'a, 'b, 'c, 'd, 'e, 'f> fn(&'a mut &'b _, &'c mut &'d _, &'e mut &'f _)`
+                 found fn item `for<'a, 'b, 'c> fn(&'a mut &_, &'b mut &_, &'c mut &_) {a::<'_, '_, '_>}`
+
 error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr b/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr
index 830a61a21f9..807e8172d53 100644
--- a/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr
+++ b/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr
@@ -1,14 +1,3 @@
-error[E0308]: mismatched types
-  --> $DIR/regions-lifetime-bounds-on-fns.rs:20:43
-   |
-LL |     let _: fn(&mut &isize, &mut &isize) = a;
-   |            ----------------------------   ^ one type is more general than the other
-   |            |
-   |            expected due to this
-   |
-   = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b _, &'c mut &'d _)`
-                 found fn item `for<'a, 'b> fn(&'a mut &_, &'b mut &_) {a::<'_, '_>}`
-
 error: lifetime may not live long enough
   --> $DIR/regions-lifetime-bounds-on-fns.rs:8:5
    |
@@ -38,6 +27,17 @@ LL |     a(x, y);
    = note: mutable references are invariant over their type parameter
    = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
 
+error[E0308]: mismatched types
+  --> $DIR/regions-lifetime-bounds-on-fns.rs:20:43
+   |
+LL |     let _: fn(&mut &isize, &mut &isize) = a;
+   |            ----------------------------   ^ one type is more general than the other
+   |            |
+   |            expected due to this
+   |
+   = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b _, &'c mut &'d _)`
+                 found fn item `for<'a, 'b> fn(&'a mut &_, &'b mut &_) {a::<'_, '_>}`
+
 error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-1014-stdout-existential-crisis/rfc-1014.rs b/tests/ui/rfcs/rfc-1014-stdout-existential-crisis/rfc-1014.rs
index 1edd51dd23c..cc2d9bad029 100644
--- a/tests/ui/rfcs/rfc-1014-stdout-existential-crisis/rfc-1014.rs
+++ b/tests/ui/rfcs/rfc-1014-stdout-existential-crisis/rfc-1014.rs
@@ -1,6 +1,5 @@
 //@ run-pass
 #![allow(dead_code)]
-//@ ignore-wasm32-bare no libc
 //@ ignore-sgx no libc
 
 #![feature(rustc_private)]
diff --git a/tests/ui/rfcs/rfc-1717-dllimport/1717-dllimport/library-override.rs b/tests/ui/rfcs/rfc-1717-dllimport/1717-dllimport/library-override.rs
index e31516a6480..e29f025bcff 100644
--- a/tests/ui/rfcs/rfc-1717-dllimport/1717-dllimport/library-override.rs
+++ b/tests/ui/rfcs/rfc-1717-dllimport/1717-dllimport/library-override.rs
@@ -1,5 +1,4 @@
 //@ run-pass
-//@ ignore-wasm32-bare no libc to test ffi with
 //@ compile-flags: -lstatic=wronglibrary:rust_test_helpers
 
 #[link(name = "wronglibrary", kind = "dylib")]
diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr
index 4a219ff8b55..1489791b20d 100644
--- a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr
+++ b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.current.stderr
@@ -1,5 +1,5 @@
 warning: methods `good_virt` and `good_indirect` are never used
-  --> $DIR/manual-self-impl-for-unsafe-obj.rs:22:8
+  --> $DIR/manual-self-impl-for-unsafe-obj.rs:23:8
    |
 LL | trait Good {
    |       ---- methods in this trait
diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr
index 4a219ff8b55..1489791b20d 100644
--- a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr
+++ b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.next.stderr
@@ -1,5 +1,5 @@
 warning: methods `good_virt` and `good_indirect` are never used
-  --> $DIR/manual-self-impl-for-unsafe-obj.rs:22:8
+  --> $DIR/manual-self-impl-for-unsafe-obj.rs:23:8
    |
 LL | trait Good {
    |       ---- methods in this trait
diff --git a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs
index ba09550aad5..a020d91fb14 100644
--- a/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs
+++ b/tests/ui/rfcs/rfc-2027-object-safe-for-dispatch/manual-self-impl-for-unsafe-obj.rs
@@ -1,6 +1,7 @@
 // Check that we can manually implement an object-unsafe trait for its trait object.
 
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@ run-pass
 
diff --git a/tests/ui/runtime/atomic-print.rs b/tests/ui/runtime/atomic-print.rs
index aa3183885bf..73520589736 100644
--- a/tests/ui/runtime/atomic-print.rs
+++ b/tests/ui/runtime/atomic-print.rs
@@ -2,7 +2,7 @@
 
 #![allow(unused_must_use)]
 #![allow(deprecated)]
-//@ ignore-emscripten no threads support
+//@ ignore-wasm32 no processes or threads
 //@ ignore-sgx no processes
 
 use std::{env, fmt, process, sync, thread};
diff --git a/tests/ui/runtime/backtrace-debuginfo.rs b/tests/ui/runtime/backtrace-debuginfo.rs
index 49f153fabda..9c4b15e64f5 100644
--- a/tests/ui/runtime/backtrace-debuginfo.rs
+++ b/tests/ui/runtime/backtrace-debuginfo.rs
@@ -9,7 +9,7 @@
 //@ compile-flags:-g -Copt-level=0 -Cllvm-args=-enable-tail-merge=0
 //@ compile-flags:-Cforce-frame-pointers=yes
 //@ compile-flags:-Cstrip=none
-//@ ignore-emscripten spawning processes is not supported
+//@ ignore-wasm32 spawning processes is not supported
 //@ ignore-sgx no processes
 //@ ignore-fuchsia Backtrace not symbolized, trace different line alignment
 
diff --git a/tests/ui/runtime/out-of-stack.rs b/tests/ui/runtime/out-of-stack.rs
index e8e0e847a8e..ab2b50b293c 100644
--- a/tests/ui/runtime/out-of-stack.rs
+++ b/tests/ui/runtime/out-of-stack.rs
@@ -3,7 +3,7 @@
 #![allow(unused_must_use)]
 #![allow(unconditional_recursion)]
 //@ ignore-android: FIXME (#20004)
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 //@ ignore-fuchsia must translate zircon signal to SIGABRT, FIXME (#58590)
 //@ ignore-nto no stack overflow handler used (no alternate stack available)
diff --git a/tests/ui/runtime/running-with-no-runtime.rs b/tests/ui/runtime/running-with-no-runtime.rs
index 8430e826dc3..695025b3859 100644
--- a/tests/ui/runtime/running-with-no-runtime.rs
+++ b/tests/ui/runtime/running-with-no-runtime.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten spawning processes is not supported
+//@ ignore-wasm32 spawning processes is not supported
 //@ ignore-sgx no processes
 
 #![feature(start)]
diff --git a/tests/ui/runtime/signal-alternate-stack-cleanup.rs b/tests/ui/runtime/signal-alternate-stack-cleanup.rs
index 3b7bb0d505d..f2af86be0a5 100644
--- a/tests/ui/runtime/signal-alternate-stack-cleanup.rs
+++ b/tests/ui/runtime/signal-alternate-stack-cleanup.rs
@@ -3,7 +3,7 @@
 // main thread exit while still being in use by signal handlers. This test
 // triggers this situation by sending signal from atexit handler.
 //
-//@ ignore-wasm32-bare no libc
+//@ ignore-wasm32 no signals
 //@ ignore-windows
 //@ ignore-sgx no libc
 //@ ignore-vxworks no SIGWINCH in user space
diff --git a/tests/ui/rust-2018/uniform-paths/issue-55779.rs b/tests/ui/rust-2018/uniform-paths/issue-55779.rs
index 246b8dd82c5..f90054e6b1d 100644
--- a/tests/ui/rust-2018/uniform-paths/issue-55779.rs
+++ b/tests/ui/rust-2018/uniform-paths/issue-55779.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 //@ edition:2018
 //@ aux-crate:issue_55779_extern_trait=issue-55779-extern-trait.rs
 
diff --git a/tests/ui/simd/target-feature-mixup.rs b/tests/ui/simd/target-feature-mixup.rs
index 7148fc509de..034cb867c95 100644
--- a/tests/ui/simd/target-feature-mixup.rs
+++ b/tests/ui/simd/target-feature-mixup.rs
@@ -3,7 +3,7 @@
 #![allow(stable_features)]
 #![allow(overflowing_literals)]
 
-//@ ignore-emscripten
+//@ ignore-wasm32 no subprocess support
 //@ ignore-sgx no processes
 //@ ignore-fuchsia must translate zircon signal to SIGILL, FIXME (#58590)
 
diff --git a/tests/ui/single-use-lifetime/dedup.rs b/tests/ui/single-use-lifetime/dedup.rs
new file mode 100644
index 00000000000..16b39609a6d
--- /dev/null
+++ b/tests/ui/single-use-lifetime/dedup.rs
@@ -0,0 +1,9 @@
+// Check that `unused_lifetimes` lint doesn't duplicate a "parameter is never used" error.
+// Fixed in <https://github.com/rust-lang/rust/pull/96833>.
+// Issue: <https://github.com/rust-lang/rust/issues/72587>.
+
+#![warn(unused_lifetimes)]
+struct Foo<'a>;
+//~^ ERROR parameter `'a` is never used
+
+fn main() {}
diff --git a/tests/ui/single-use-lifetime/dedup.stderr b/tests/ui/single-use-lifetime/dedup.stderr
new file mode 100644
index 00000000000..6d02cb3c714
--- /dev/null
+++ b/tests/ui/single-use-lifetime/dedup.stderr
@@ -0,0 +1,11 @@
+error[E0392]: lifetime parameter `'a` is never used
+  --> $DIR/dedup.rs:6:12
+   |
+LL | struct Foo<'a>;
+   |            ^^ unused lifetime parameter
+   |
+   = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0392`.
diff --git a/tests/ui/std-backtrace.rs b/tests/ui/std-backtrace.rs
index 141847d958d..b4806457877 100644
--- a/tests/ui/std-backtrace.rs
+++ b/tests/ui/std-backtrace.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 //@ ignore-android FIXME #17520
-//@ ignore-emscripten spawning processes is not supported
+//@ ignore-wasm32 spawning processes is not supported
 //@ ignore-openbsd no support for libbacktrace without filename
 //@ ignore-sgx no processes
 //@ ignore-msvc see #62897 and `backtrace-debuginfo.rs` test
diff --git a/tests/ui/stdio-is-blocking.rs b/tests/ui/stdio-is-blocking.rs
index 438fb06c426..dda100951dd 100644
--- a/tests/ui/stdio-is-blocking.rs
+++ b/tests/ui/stdio-is-blocking.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 
 use std::env;
diff --git a/tests/ui/structs-enums/rec-align-u64.rs b/tests/ui/structs-enums/rec-align-u64.rs
index e4b02fa0c58..72601bb16ff 100644
--- a/tests/ui/structs-enums/rec-align-u64.rs
+++ b/tests/ui/structs-enums/rec-align-u64.rs
@@ -1,7 +1,6 @@
 //@ run-pass
 #![allow(dead_code)]
 #![allow(unused_unsafe)]
-//@ ignore-wasm32-bare seems unimportant to test
 
 // Issue #2303
 
@@ -78,6 +77,14 @@ mod m {
     }
 }
 
+#[cfg(target_family = "wasm")]
+mod m {
+    pub mod m {
+        pub fn align() -> usize { 8 }
+        pub fn size() -> usize { 16 }
+    }
+}
+
 pub fn main() {
     unsafe {
         let x = Outer {c8: 22, t: Inner {c64: 44}};
diff --git a/tests/ui/suggestions/issue-102892.stderr b/tests/ui/suggestions/issue-102892.stderr
index 38f19b33218..58b201d1c77 100644
--- a/tests/ui/suggestions/issue-102892.stderr
+++ b/tests/ui/suggestions/issue-102892.stderr
@@ -1,3 +1,19 @@
+error[E0507]: cannot move out of an `Arc`
+  --> $DIR/issue-102892.rs:11:18
+   |
+LL |     let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed!
+   |          -  -    ^^^^^
+   |          |  |
+   |          |  ...and here
+   |          data moved here
+   |
+   = note: move occurs because these variables have types that don't implement the `Copy` trait
+help: consider removing the dereference here
+   |
+LL -     let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed!
+LL +     let (a, b) = *arc; // suggests putting `&**arc` here; with that, fixed!
+   |
+
 error[E0308]: mismatched types
   --> $DIR/issue-102892.rs:16:26
    |
@@ -52,22 +68,6 @@ help: alternatively, consider changing the type annotation
 LL |     let (a, b): ((A, B), &A) = (&mut *mutation, &(**arc).0); // suggests putting `&**arc` here too
    |                          +
 
-error[E0507]: cannot move out of an `Arc`
-  --> $DIR/issue-102892.rs:11:18
-   |
-LL |     let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed!
-   |          -  -    ^^^^^
-   |          |  |
-   |          |  ...and here
-   |          data moved here
-   |
-   = note: move occurs because these variables have types that don't implement the `Copy` trait
-help: consider removing the dereference here
-   |
-LL -     let (a, b) = **arc; // suggests putting `&**arc` here; with that, fixed!
-LL +     let (a, b) = *arc; // suggests putting `&**arc` here; with that, fixed!
-   |
-
 error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0308, E0507.
diff --git a/tests/ui/test-attrs/test-passed-wasm.rs b/tests/ui/test-attrs/test-passed-wasm.rs
deleted file mode 100644
index 614678e2353..00000000000
--- a/tests/ui/test-attrs/test-passed-wasm.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-//@ no-prefer-dynamic
-//@ compile-flags: --test
-//@ run-flags: --test-threads=1
-//@ run-pass
-//@ check-run-results
-//@ only-wasm32
-
-// Tests the output of the test harness with only passed tests.
-
-#![cfg(test)]
-
-#[test]
-fn it_works() {
-    assert_eq!(1 + 1, 2);
-}
-
-#[test]
-fn it_works_too() {
-    assert_eq!(1 * 0, 0);
-}
diff --git a/tests/ui/test-attrs/test-passed-wasm.run.stdout b/tests/ui/test-attrs/test-passed-wasm.run.stdout
deleted file mode 100644
index c3005a77983..00000000000
--- a/tests/ui/test-attrs/test-passed-wasm.run.stdout
+++ /dev/null
@@ -1,7 +0,0 @@
-
-running 2 tests
-test it_works ... ok
-test it_works_too ... ok
-
-test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
-
diff --git a/tests/ui/test-attrs/test-passed.rs b/tests/ui/test-attrs/test-passed.rs
index afd715322ac..f43f66a6edf 100644
--- a/tests/ui/test-attrs/test-passed.rs
+++ b/tests/ui/test-attrs/test-passed.rs
@@ -4,7 +4,6 @@
 //@ run-pass
 //@ check-run-results
 //@ normalize-stdout-test "finished in \d+\.\d+s" -> "finished in $$TIME"
-//@ ignore-wasm32 no support for `Instant`
 
 // Tests the output of the test harness with only passed tests.
 
diff --git a/tests/ui/threads-sendsync/sync-send-in-std.rs b/tests/ui/threads-sendsync/sync-send-in-std.rs
index 375e884877a..3a97cbb0c68 100644
--- a/tests/ui/threads-sendsync/sync-send-in-std.rs
+++ b/tests/ui/threads-sendsync/sync-send-in-std.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 
-//@ ignore-wasm32-bare networking not available
+//@ ignore-wasm32 networking not available
 //@ ignore-sgx ToSocketAddrs cannot be used for DNS Resolution
 //@ ignore-fuchsia Req. test-harness networking privileges
 
diff --git a/tests/ui/traits/augmented-assignments-trait.rs b/tests/ui/traits/augmented-assignments-trait.rs
index 37fe42ce1c6..a0f8b39eb7a 100644
--- a/tests/ui/traits/augmented-assignments-trait.rs
+++ b/tests/ui/traits/augmented-assignments-trait.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 use std::ops::AddAssign;
 
 struct Int(#[allow(dead_code)] i32);
diff --git a/tests/ui/traits/deny-builtin-object-impl.current.stderr b/tests/ui/traits/deny-builtin-object-impl.current.stderr
index 0dbf8f0e668..8423a2519b2 100644
--- a/tests/ui/traits/deny-builtin-object-impl.current.stderr
+++ b/tests/ui/traits/deny-builtin-object-impl.current.stderr
@@ -1,16 +1,16 @@
 error[E0277]: the trait bound `dyn NotObject: NotObject` is not satisfied
-  --> $DIR/deny-builtin-object-impl.rs:18:23
+  --> $DIR/deny-builtin-object-impl.rs:19:23
    |
 LL |     test_not_object::<dyn NotObject>();
    |                       ^^^^^^^^^^^^^ the trait `NotObject` is not implemented for `dyn NotObject`
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/deny-builtin-object-impl.rs:10:1
+  --> $DIR/deny-builtin-object-impl.rs:11:1
    |
 LL | trait NotObject {}
    | ^^^^^^^^^^^^^^^
 note: required by a bound in `test_not_object`
-  --> $DIR/deny-builtin-object-impl.rs:14:23
+  --> $DIR/deny-builtin-object-impl.rs:15:23
    |
 LL | fn test_not_object<T: NotObject + ?Sized>() {}
    |                       ^^^^^^^^^ required by this bound in `test_not_object`
diff --git a/tests/ui/traits/deny-builtin-object-impl.next.stderr b/tests/ui/traits/deny-builtin-object-impl.next.stderr
index 0dbf8f0e668..8423a2519b2 100644
--- a/tests/ui/traits/deny-builtin-object-impl.next.stderr
+++ b/tests/ui/traits/deny-builtin-object-impl.next.stderr
@@ -1,16 +1,16 @@
 error[E0277]: the trait bound `dyn NotObject: NotObject` is not satisfied
-  --> $DIR/deny-builtin-object-impl.rs:18:23
+  --> $DIR/deny-builtin-object-impl.rs:19:23
    |
 LL |     test_not_object::<dyn NotObject>();
    |                       ^^^^^^^^^^^^^ the trait `NotObject` is not implemented for `dyn NotObject`
    |
 help: this trait has no implementations, consider adding one
-  --> $DIR/deny-builtin-object-impl.rs:10:1
+  --> $DIR/deny-builtin-object-impl.rs:11:1
    |
 LL | trait NotObject {}
    | ^^^^^^^^^^^^^^^
 note: required by a bound in `test_not_object`
-  --> $DIR/deny-builtin-object-impl.rs:14:23
+  --> $DIR/deny-builtin-object-impl.rs:15:23
    |
 LL | fn test_not_object<T: NotObject + ?Sized>() {}
    |                       ^^^^^^^^^ required by this bound in `test_not_object`
diff --git a/tests/ui/traits/deny-builtin-object-impl.rs b/tests/ui/traits/deny-builtin-object-impl.rs
index 8e4e44f6a67..c16dcca8fbc 100644
--- a/tests/ui/traits/deny-builtin-object-impl.rs
+++ b/tests/ui/traits/deny-builtin-object-impl.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 #![feature(rustc_attrs)]
diff --git a/tests/ui/traits/issue-24010.rs b/tests/ui/traits/issue-24010.rs
index a42a747b2d3..a3168fa4956 100644
--- a/tests/ui/traits/issue-24010.rs
+++ b/tests/ui/traits/issue-24010.rs
@@ -1,5 +1,6 @@
 //@ run-pass
-//@ revisions: classic next
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 trait Foo: Fn(i32) -> i32 + Send {}
diff --git a/tests/ui/traits/issue-33187.rs b/tests/ui/traits/issue-33187.rs
index 6a039527b3b..6ae7e150c51 100644
--- a/tests/ui/traits/issue-33187.rs
+++ b/tests/ui/traits/issue-33187.rs
@@ -1,4 +1,4 @@
-//@ run-pass
+//@ check-pass
 
 struct Foo<A: Repr>(<A as Repr>::Data);
 
diff --git a/tests/ui/traits/negative-impls/negative-impl-normalizes-to.rs b/tests/ui/traits/negative-impls/negative-impl-normalizes-to.rs
index 998b0d0c458..3316c5478a4 100644
--- a/tests/ui/traits/negative-impls/negative-impl-normalizes-to.rs
+++ b/tests/ui/traits/negative-impls/negative-impl-normalizes-to.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@ check-pass
 
diff --git a/tests/ui/traits/next-solver/env-shadows-impls/discard-impls-shadowed-by-env-2.rs b/tests/ui/traits/next-solver/env-shadows-impls/discard-impls-shadowed-by-env-2.rs
index 583d3c18faf..20329f467db 100644
--- a/tests/ui/traits/next-solver/env-shadows-impls/discard-impls-shadowed-by-env-2.rs
+++ b/tests/ui/traits/next-solver/env-shadows-impls/discard-impls-shadowed-by-env-2.rs
@@ -1,4 +1,5 @@
-//@ revisions: next current
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@ check-pass
 
diff --git a/tests/ui/traits/next-solver/normalize-param-env-4.next.stderr b/tests/ui/traits/next-solver/normalize-param-env-4.next.stderr
index 1bee8ee88ff..e91a48f62ae 100644
--- a/tests/ui/traits/next-solver/normalize-param-env-4.next.stderr
+++ b/tests/ui/traits/next-solver/normalize-param-env-4.next.stderr
@@ -1,23 +1,23 @@
 error[E0275]: overflow evaluating the requirement `<T as Trait>::Assoc: Trait`
-  --> $DIR/normalize-param-env-4.rs:18:26
+  --> $DIR/normalize-param-env-4.rs:19:26
    |
 LL |     <T as Trait>::Assoc: Trait,
    |                          ^^^^^
 
 error[E0275]: overflow evaluating the requirement `<T as Trait>::Assoc well-formed`
-  --> $DIR/normalize-param-env-4.rs:18:26
+  --> $DIR/normalize-param-env-4.rs:19:26
    |
 LL |     <T as Trait>::Assoc: Trait,
    |                          ^^^^^
 
 error[E0275]: overflow evaluating the requirement `T: Trait`
-  --> $DIR/normalize-param-env-4.rs:31:19
+  --> $DIR/normalize-param-env-4.rs:32:19
    |
 LL |     impls_trait::<T>();
    |                   ^
    |
 note: required by a bound in `impls_trait`
-  --> $DIR/normalize-param-env-4.rs:14:19
+  --> $DIR/normalize-param-env-4.rs:15:19
    |
 LL | fn impls_trait<T: Trait>() {}
    |                   ^^^^^ required by this bound in `impls_trait`
diff --git a/tests/ui/traits/next-solver/normalize-param-env-4.rs b/tests/ui/traits/next-solver/normalize-param-env-4.rs
index b28fe5c3bd8..ed7f6899bde 100644
--- a/tests/ui/traits/next-solver/normalize-param-env-4.rs
+++ b/tests/ui/traits/next-solver/normalize-param-env-4.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@[next] known-bug: #92505
 //@[current] check-pass
diff --git a/tests/ui/traits/non-lifetime-via-dyn-builtin.current.stderr b/tests/ui/traits/non-lifetime-via-dyn-builtin.current.stderr
index 9f373cc50f0..5393db6b105 100644
--- a/tests/ui/traits/non-lifetime-via-dyn-builtin.current.stderr
+++ b/tests/ui/traits/non-lifetime-via-dyn-builtin.current.stderr
@@ -1,5 +1,5 @@
 warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/non-lifetime-via-dyn-builtin.rs:5:12
+  --> $DIR/non-lifetime-via-dyn-builtin.rs:6:12
    |
 LL | #![feature(non_lifetime_binders)]
    |            ^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/traits/non-lifetime-via-dyn-builtin.next.stderr b/tests/ui/traits/non-lifetime-via-dyn-builtin.next.stderr
index 9f373cc50f0..5393db6b105 100644
--- a/tests/ui/traits/non-lifetime-via-dyn-builtin.next.stderr
+++ b/tests/ui/traits/non-lifetime-via-dyn-builtin.next.stderr
@@ -1,5 +1,5 @@
 warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/non-lifetime-via-dyn-builtin.rs:5:12
+  --> $DIR/non-lifetime-via-dyn-builtin.rs:6:12
    |
 LL | #![feature(non_lifetime_binders)]
    |            ^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/traits/non-lifetime-via-dyn-builtin.rs b/tests/ui/traits/non-lifetime-via-dyn-builtin.rs
index 26cf6105c50..ac61f8b614c 100644
--- a/tests/ui/traits/non-lifetime-via-dyn-builtin.rs
+++ b/tests/ui/traits/non-lifetime-via-dyn-builtin.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@ check-pass
 
diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.current.stderr b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.current.stderr
index 4082d6d47e7..3e5854ea1c8 100644
--- a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.current.stderr
+++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.current.stderr
@@ -1,5 +1,5 @@
 warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/unifying-placeholders-in-query-response-2.rs:5:12
+  --> $DIR/unifying-placeholders-in-query-response-2.rs:6:12
    |
 LL | #![feature(non_lifetime_binders)]
    |            ^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.next.stderr b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.next.stderr
index 4082d6d47e7..3e5854ea1c8 100644
--- a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.next.stderr
+++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.next.stderr
@@ -1,5 +1,5 @@
 warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/unifying-placeholders-in-query-response-2.rs:5:12
+  --> $DIR/unifying-placeholders-in-query-response-2.rs:6:12
    |
 LL | #![feature(non_lifetime_binders)]
    |            ^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.rs b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.rs
index 0749cbe1140..2066887ea59 100644
--- a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.rs
+++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@ check-pass
 
diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.current.stderr b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.current.stderr
index 040009efbde..0224e5763e0 100644
--- a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.current.stderr
+++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.current.stderr
@@ -1,5 +1,5 @@
 warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/unifying-placeholders-in-query-response.rs:5:12
+  --> $DIR/unifying-placeholders-in-query-response.rs:6:12
    |
 LL | #![feature(non_lifetime_binders)]
    |            ^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.next.stderr b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.next.stderr
index 040009efbde..0224e5763e0 100644
--- a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.next.stderr
+++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.next.stderr
@@ -1,5 +1,5 @@
 warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/unifying-placeholders-in-query-response.rs:5:12
+  --> $DIR/unifying-placeholders-in-query-response.rs:6:12
    |
 LL | #![feature(non_lifetime_binders)]
    |            ^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.rs b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.rs
index 333f4f80386..5334118e9ac 100644
--- a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.rs
+++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@ check-pass
 
diff --git a/tests/ui/traits/pointee-tail-is-generic.rs b/tests/ui/traits/pointee-tail-is-generic.rs
index e33b2b2f2bc..14bdf0880c7 100644
--- a/tests/ui/traits/pointee-tail-is-generic.rs
+++ b/tests/ui/traits/pointee-tail-is-generic.rs
@@ -4,10 +4,12 @@
 #![feature(ptr_metadata)]
 #![feature(type_alias_impl_trait)]
 
-type Opaque = impl std::future::Future;
+mod opaque {
+    pub type Opaque = impl std::future::Future;
 
-fn opaque() -> Opaque {
-    async {}
+    fn opaque() -> Opaque {
+        async {}
+    }
 }
 
 fn a<T>() {
@@ -16,7 +18,7 @@ fn a<T>() {
     // tail of ADT (which is a type param) is known to be sized
     is_thin::<std::cell::Cell<T>>();
     // opaque type is known to be sized
-    is_thin::<Opaque>();
+    is_thin::<opaque::Opaque>();
 }
 
 fn a2<T: Iterator>() {
diff --git a/tests/ui/traits/trait-upcasting/add-supertrait-auto-traits.rs b/tests/ui/traits/trait-upcasting/add-supertrait-auto-traits.rs
index 5983b13185f..ffc21a4a9ea 100644
--- a/tests/ui/traits/trait-upcasting/add-supertrait-auto-traits.rs
+++ b/tests/ui/traits/trait-upcasting/add-supertrait-auto-traits.rs
@@ -1,5 +1,6 @@
 //@ check-pass
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 #![feature(trait_upcasting)]
diff --git a/tests/ui/traits/trait-upcasting/fewer-associated.rs b/tests/ui/traits/trait-upcasting/fewer-associated.rs
index 214293b0840..45e8673b859 100644
--- a/tests/ui/traits/trait-upcasting/fewer-associated.rs
+++ b/tests/ui/traits/trait-upcasting/fewer-associated.rs
@@ -1,6 +1,7 @@
 //@ check-pass
 // issue: 114035
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 #![feature(trait_upcasting)]
diff --git a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.current.stderr b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.current.stderr
index 1538e2f3fd7..28be189ff1e 100644
--- a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.current.stderr
+++ b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.current.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/illegal-upcast-from-impl.rs:16:66
+  --> $DIR/illegal-upcast-from-impl.rs:17:66
    |
 LL | fn illegal(x: &dyn Sub<Assoc = ()>) -> &dyn Super<Assoc = i32> { x }
    |                                        -----------------------   ^ expected trait `Super`, found trait `Sub`
diff --git a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.next.stderr b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.next.stderr
index 1538e2f3fd7..28be189ff1e 100644
--- a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.next.stderr
+++ b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.next.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/illegal-upcast-from-impl.rs:16:66
+  --> $DIR/illegal-upcast-from-impl.rs:17:66
    |
 LL | fn illegal(x: &dyn Sub<Assoc = ()>) -> &dyn Super<Assoc = i32> { x }
    |                                        -----------------------   ^ expected trait `Super`, found trait `Sub`
diff --git a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.rs b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.rs
index 2f15d343f9f..0c771db4121 100644
--- a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.rs
+++ b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 #![feature(trait_upcasting)]
diff --git a/tests/ui/traits/trait-upcasting/issue-11515.current.stderr b/tests/ui/traits/trait-upcasting/issue-11515.current.stderr
index ce799dcb7ef..8ce7d46012f 100644
--- a/tests/ui/traits/trait-upcasting/issue-11515.current.stderr
+++ b/tests/ui/traits/trait-upcasting/issue-11515.current.stderr
@@ -1,5 +1,5 @@
 error[E0658]: cannot cast `dyn Fn()` to `dyn FnMut()`, trait upcasting coercion is experimental
-  --> $DIR/issue-11515.rs:10:38
+  --> $DIR/issue-11515.rs:11:38
    |
 LL |     let test = Box::new(Test { func: closure });
    |                                      ^^^^^^^
diff --git a/tests/ui/traits/trait-upcasting/issue-11515.next.stderr b/tests/ui/traits/trait-upcasting/issue-11515.next.stderr
index ce799dcb7ef..8ce7d46012f 100644
--- a/tests/ui/traits/trait-upcasting/issue-11515.next.stderr
+++ b/tests/ui/traits/trait-upcasting/issue-11515.next.stderr
@@ -1,5 +1,5 @@
 error[E0658]: cannot cast `dyn Fn()` to `dyn FnMut()`, trait upcasting coercion is experimental
-  --> $DIR/issue-11515.rs:10:38
+  --> $DIR/issue-11515.rs:11:38
    |
 LL |     let test = Box::new(Test { func: closure });
    |                                      ^^^^^^^
diff --git a/tests/ui/traits/trait-upcasting/issue-11515.rs b/tests/ui/traits/trait-upcasting/issue-11515.rs
index 174be31d139..d251e804c3e 100644
--- a/tests/ui/traits/trait-upcasting/issue-11515.rs
+++ b/tests/ui/traits/trait-upcasting/issue-11515.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 struct Test {
diff --git a/tests/ui/traits/trait-upcasting/normalization.rs b/tests/ui/traits/trait-upcasting/normalization.rs
index e4b65740ca4..ae5a6a5243c 100644
--- a/tests/ui/traits/trait-upcasting/normalization.rs
+++ b/tests/ui/traits/trait-upcasting/normalization.rs
@@ -1,6 +1,7 @@
 //@ check-pass
 // issue: 114113
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 #![feature(trait_upcasting)]
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr
index 10c22440a83..9a9ad9bbf77 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr
@@ -1,5 +1,5 @@
 error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>`
-  --> $DIR/type-checking-test-1.rs:19:13
+  --> $DIR/type-checking-test-1.rs:20:13
    |
 LL |     let _ = x as &dyn Bar<_>; // Ambiguous
    |             ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.next.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-1.next.stderr
index 10c22440a83..9a9ad9bbf77 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-1.next.stderr
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.next.stderr
@@ -1,5 +1,5 @@
 error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>`
-  --> $DIR/type-checking-test-1.rs:19:13
+  --> $DIR/type-checking-test-1.rs:20:13
    |
 LL |     let _ = x as &dyn Bar<_>; // Ambiguous
    |             ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.rs b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs
index 0246b7d0566..fd902fd87e0 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-1.rs
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 #![feature(trait_upcasting)]
diff --git a/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.current.stderr b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.current.stderr
index 86de78f858c..239f8279194 100644
--- a/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.current.stderr
+++ b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.current.stderr
@@ -1,5 +1,5 @@
 error[E0658]: cannot cast `dyn A` to `dyn B`, trait upcasting coercion is experimental
-  --> $DIR/upcast-through-struct-tail.rs:10:5
+  --> $DIR/upcast-through-struct-tail.rs:11:5
    |
 LL |     x
    |     ^
diff --git a/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.next.stderr b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.next.stderr
index 86de78f858c..239f8279194 100644
--- a/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.next.stderr
+++ b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.next.stderr
@@ -1,5 +1,5 @@
 error[E0658]: cannot cast `dyn A` to `dyn B`, trait upcasting coercion is experimental
-  --> $DIR/upcast-through-struct-tail.rs:10:5
+  --> $DIR/upcast-through-struct-tail.rs:11:5
    |
 LL |     x
    |     ^
diff --git a/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.rs b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.rs
index 40850b45a00..e40cca4e0a8 100644
--- a/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.rs
+++ b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 struct Wrapper<T: ?Sized>(T);
diff --git a/tests/ui/transmutability/primitives/bool.current.stderr b/tests/ui/transmutability/primitives/bool.current.stderr
index d6376342c9c..98e4a1029c9 100644
--- a/tests/ui/transmutability/primitives/bool.current.stderr
+++ b/tests/ui/transmutability/primitives/bool.current.stderr
@@ -1,11 +1,11 @@
 error[E0277]: `u8` cannot be safely transmuted into `bool`
-  --> $DIR/bool.rs:20:35
+  --> $DIR/bool.rs:21:35
    |
 LL |     assert::is_transmutable::<u8, bool>();
    |                                   ^^^^ At least one value of `u8` isn't a bit-valid value of `bool`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/bool.rs:10:14
+  --> $DIR/bool.rs:11:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
diff --git a/tests/ui/transmutability/primitives/bool.next.stderr b/tests/ui/transmutability/primitives/bool.next.stderr
index d6376342c9c..98e4a1029c9 100644
--- a/tests/ui/transmutability/primitives/bool.next.stderr
+++ b/tests/ui/transmutability/primitives/bool.next.stderr
@@ -1,11 +1,11 @@
 error[E0277]: `u8` cannot be safely transmuted into `bool`
-  --> $DIR/bool.rs:20:35
+  --> $DIR/bool.rs:21:35
    |
 LL |     assert::is_transmutable::<u8, bool>();
    |                                   ^^^^ At least one value of `u8` isn't a bit-valid value of `bool`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/bool.rs:10:14
+  --> $DIR/bool.rs:11:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
diff --git a/tests/ui/transmutability/primitives/bool.rs b/tests/ui/transmutability/primitives/bool.rs
index 1be3b28b643..19236a1ae2e 100644
--- a/tests/ui/transmutability/primitives/bool.rs
+++ b/tests/ui/transmutability/primitives/bool.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 #![feature(transmutability)]
diff --git a/tests/ui/transmutability/primitives/numbers.current.stderr b/tests/ui/transmutability/primitives/numbers.current.stderr
index 7a80e444149..009e377af99 100644
--- a/tests/ui/transmutability/primitives/numbers.current.stderr
+++ b/tests/ui/transmutability/primitives/numbers.current.stderr
@@ -1,11 +1,11 @@
 error[E0277]: `i8` cannot be safely transmuted into `i16`
-  --> $DIR/numbers.rs:64:40
+  --> $DIR/numbers.rs:65:40
    |
 LL |     assert::is_transmutable::<   i8,   i16>();
    |                                        ^^^ The size of `i8` is smaller than the size of `i16`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -14,13 +14,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `u16`
-  --> $DIR/numbers.rs:65:40
+  --> $DIR/numbers.rs:66:40
    |
 LL |     assert::is_transmutable::<   i8,   u16>();
    |                                        ^^^ The size of `i8` is smaller than the size of `u16`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -29,13 +29,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `i32`
-  --> $DIR/numbers.rs:66:40
+  --> $DIR/numbers.rs:67:40
    |
 LL |     assert::is_transmutable::<   i8,   i32>();
    |                                        ^^^ The size of `i8` is smaller than the size of `i32`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -44,13 +44,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `f32`
-  --> $DIR/numbers.rs:67:40
+  --> $DIR/numbers.rs:68:40
    |
 LL |     assert::is_transmutable::<   i8,   f32>();
    |                                        ^^^ The size of `i8` is smaller than the size of `f32`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -59,13 +59,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `u32`
-  --> $DIR/numbers.rs:68:40
+  --> $DIR/numbers.rs:69:40
    |
 LL |     assert::is_transmutable::<   i8,   u32>();
    |                                        ^^^ The size of `i8` is smaller than the size of `u32`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -74,13 +74,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `u64`
-  --> $DIR/numbers.rs:69:40
+  --> $DIR/numbers.rs:70:40
    |
 LL |     assert::is_transmutable::<   i8,   u64>();
    |                                        ^^^ The size of `i8` is smaller than the size of `u64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -89,13 +89,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `i64`
-  --> $DIR/numbers.rs:70:40
+  --> $DIR/numbers.rs:71:40
    |
 LL |     assert::is_transmutable::<   i8,   i64>();
    |                                        ^^^ The size of `i8` is smaller than the size of `i64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -104,13 +104,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `f64`
-  --> $DIR/numbers.rs:71:40
+  --> $DIR/numbers.rs:72:40
    |
 LL |     assert::is_transmutable::<   i8,   f64>();
    |                                        ^^^ The size of `i8` is smaller than the size of `f64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -119,13 +119,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `u128`
-  --> $DIR/numbers.rs:72:39
+  --> $DIR/numbers.rs:73:39
    |
 LL |     assert::is_transmutable::<   i8,  u128>();
    |                                       ^^^^ The size of `i8` is smaller than the size of `u128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -134,13 +134,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `i128`
-  --> $DIR/numbers.rs:73:39
+  --> $DIR/numbers.rs:74:39
    |
 LL |     assert::is_transmutable::<   i8,  i128>();
    |                                       ^^^^ The size of `i8` is smaller than the size of `i128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -149,13 +149,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `i16`
-  --> $DIR/numbers.rs:75:40
+  --> $DIR/numbers.rs:76:40
    |
 LL |     assert::is_transmutable::<   u8,   i16>();
    |                                        ^^^ The size of `u8` is smaller than the size of `i16`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -164,13 +164,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `u16`
-  --> $DIR/numbers.rs:76:40
+  --> $DIR/numbers.rs:77:40
    |
 LL |     assert::is_transmutable::<   u8,   u16>();
    |                                        ^^^ The size of `u8` is smaller than the size of `u16`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -179,13 +179,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `i32`
-  --> $DIR/numbers.rs:77:40
+  --> $DIR/numbers.rs:78:40
    |
 LL |     assert::is_transmutable::<   u8,   i32>();
    |                                        ^^^ The size of `u8` is smaller than the size of `i32`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -194,13 +194,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `f32`
-  --> $DIR/numbers.rs:78:40
+  --> $DIR/numbers.rs:79:40
    |
 LL |     assert::is_transmutable::<   u8,   f32>();
    |                                        ^^^ The size of `u8` is smaller than the size of `f32`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -209,13 +209,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `u32`
-  --> $DIR/numbers.rs:79:40
+  --> $DIR/numbers.rs:80:40
    |
 LL |     assert::is_transmutable::<   u8,   u32>();
    |                                        ^^^ The size of `u8` is smaller than the size of `u32`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -224,13 +224,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `u64`
-  --> $DIR/numbers.rs:80:40
+  --> $DIR/numbers.rs:81:40
    |
 LL |     assert::is_transmutable::<   u8,   u64>();
    |                                        ^^^ The size of `u8` is smaller than the size of `u64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -239,13 +239,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `i64`
-  --> $DIR/numbers.rs:81:40
+  --> $DIR/numbers.rs:82:40
    |
 LL |     assert::is_transmutable::<   u8,   i64>();
    |                                        ^^^ The size of `u8` is smaller than the size of `i64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -254,13 +254,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `f64`
-  --> $DIR/numbers.rs:82:40
+  --> $DIR/numbers.rs:83:40
    |
 LL |     assert::is_transmutable::<   u8,   f64>();
    |                                        ^^^ The size of `u8` is smaller than the size of `f64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -269,13 +269,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `u128`
-  --> $DIR/numbers.rs:83:39
+  --> $DIR/numbers.rs:84:39
    |
 LL |     assert::is_transmutable::<   u8,  u128>();
    |                                       ^^^^ The size of `u8` is smaller than the size of `u128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -284,13 +284,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `i128`
-  --> $DIR/numbers.rs:84:39
+  --> $DIR/numbers.rs:85:39
    |
 LL |     assert::is_transmutable::<   u8,  i128>();
    |                                       ^^^^ The size of `u8` is smaller than the size of `i128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -299,13 +299,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `i32`
-  --> $DIR/numbers.rs:86:40
+  --> $DIR/numbers.rs:87:40
    |
 LL |     assert::is_transmutable::<  i16,   i32>();
    |                                        ^^^ The size of `i16` is smaller than the size of `i32`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -314,13 +314,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `f32`
-  --> $DIR/numbers.rs:87:40
+  --> $DIR/numbers.rs:88:40
    |
 LL |     assert::is_transmutable::<  i16,   f32>();
    |                                        ^^^ The size of `i16` is smaller than the size of `f32`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -329,13 +329,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `u32`
-  --> $DIR/numbers.rs:88:40
+  --> $DIR/numbers.rs:89:40
    |
 LL |     assert::is_transmutable::<  i16,   u32>();
    |                                        ^^^ The size of `i16` is smaller than the size of `u32`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -344,13 +344,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `u64`
-  --> $DIR/numbers.rs:89:40
+  --> $DIR/numbers.rs:90:40
    |
 LL |     assert::is_transmutable::<  i16,   u64>();
    |                                        ^^^ The size of `i16` is smaller than the size of `u64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -359,13 +359,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `i64`
-  --> $DIR/numbers.rs:90:40
+  --> $DIR/numbers.rs:91:40
    |
 LL |     assert::is_transmutable::<  i16,   i64>();
    |                                        ^^^ The size of `i16` is smaller than the size of `i64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -374,13 +374,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `f64`
-  --> $DIR/numbers.rs:91:40
+  --> $DIR/numbers.rs:92:40
    |
 LL |     assert::is_transmutable::<  i16,   f64>();
    |                                        ^^^ The size of `i16` is smaller than the size of `f64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -389,13 +389,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `u128`
-  --> $DIR/numbers.rs:92:39
+  --> $DIR/numbers.rs:93:39
    |
 LL |     assert::is_transmutable::<  i16,  u128>();
    |                                       ^^^^ The size of `i16` is smaller than the size of `u128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -404,13 +404,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `i128`
-  --> $DIR/numbers.rs:93:39
+  --> $DIR/numbers.rs:94:39
    |
 LL |     assert::is_transmutable::<  i16,  i128>();
    |                                       ^^^^ The size of `i16` is smaller than the size of `i128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -419,13 +419,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `i32`
-  --> $DIR/numbers.rs:95:40
+  --> $DIR/numbers.rs:96:40
    |
 LL |     assert::is_transmutable::<  u16,   i32>();
    |                                        ^^^ The size of `u16` is smaller than the size of `i32`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -434,13 +434,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `f32`
-  --> $DIR/numbers.rs:96:40
+  --> $DIR/numbers.rs:97:40
    |
 LL |     assert::is_transmutable::<  u16,   f32>();
    |                                        ^^^ The size of `u16` is smaller than the size of `f32`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -449,13 +449,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `u32`
-  --> $DIR/numbers.rs:97:40
+  --> $DIR/numbers.rs:98:40
    |
 LL |     assert::is_transmutable::<  u16,   u32>();
    |                                        ^^^ The size of `u16` is smaller than the size of `u32`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -464,13 +464,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `u64`
-  --> $DIR/numbers.rs:98:40
+  --> $DIR/numbers.rs:99:40
    |
 LL |     assert::is_transmutable::<  u16,   u64>();
    |                                        ^^^ The size of `u16` is smaller than the size of `u64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -479,13 +479,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `i64`
-  --> $DIR/numbers.rs:99:40
+  --> $DIR/numbers.rs:100:40
    |
 LL |     assert::is_transmutable::<  u16,   i64>();
    |                                        ^^^ The size of `u16` is smaller than the size of `i64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -494,13 +494,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `f64`
-  --> $DIR/numbers.rs:100:40
+  --> $DIR/numbers.rs:101:40
    |
 LL |     assert::is_transmutable::<  u16,   f64>();
    |                                        ^^^ The size of `u16` is smaller than the size of `f64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -509,13 +509,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `u128`
-  --> $DIR/numbers.rs:101:39
+  --> $DIR/numbers.rs:102:39
    |
 LL |     assert::is_transmutable::<  u16,  u128>();
    |                                       ^^^^ The size of `u16` is smaller than the size of `u128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -524,13 +524,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `i128`
-  --> $DIR/numbers.rs:102:39
+  --> $DIR/numbers.rs:103:39
    |
 LL |     assert::is_transmutable::<  u16,  i128>();
    |                                       ^^^^ The size of `u16` is smaller than the size of `i128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -539,13 +539,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i32` cannot be safely transmuted into `u64`
-  --> $DIR/numbers.rs:104:40
+  --> $DIR/numbers.rs:105:40
    |
 LL |     assert::is_transmutable::<  i32,   u64>();
    |                                        ^^^ The size of `i32` is smaller than the size of `u64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -554,13 +554,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i32` cannot be safely transmuted into `i64`
-  --> $DIR/numbers.rs:105:40
+  --> $DIR/numbers.rs:106:40
    |
 LL |     assert::is_transmutable::<  i32,   i64>();
    |                                        ^^^ The size of `i32` is smaller than the size of `i64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -569,13 +569,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i32` cannot be safely transmuted into `f64`
-  --> $DIR/numbers.rs:106:40
+  --> $DIR/numbers.rs:107:40
    |
 LL |     assert::is_transmutable::<  i32,   f64>();
    |                                        ^^^ The size of `i32` is smaller than the size of `f64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -584,13 +584,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i32` cannot be safely transmuted into `u128`
-  --> $DIR/numbers.rs:107:39
+  --> $DIR/numbers.rs:108:39
    |
 LL |     assert::is_transmutable::<  i32,  u128>();
    |                                       ^^^^ The size of `i32` is smaller than the size of `u128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -599,13 +599,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i32` cannot be safely transmuted into `i128`
-  --> $DIR/numbers.rs:108:39
+  --> $DIR/numbers.rs:109:39
    |
 LL |     assert::is_transmutable::<  i32,  i128>();
    |                                       ^^^^ The size of `i32` is smaller than the size of `i128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -614,13 +614,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f32` cannot be safely transmuted into `u64`
-  --> $DIR/numbers.rs:110:40
+  --> $DIR/numbers.rs:111:40
    |
 LL |     assert::is_transmutable::<  f32,   u64>();
    |                                        ^^^ The size of `f32` is smaller than the size of `u64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -629,13 +629,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f32` cannot be safely transmuted into `i64`
-  --> $DIR/numbers.rs:111:40
+  --> $DIR/numbers.rs:112:40
    |
 LL |     assert::is_transmutable::<  f32,   i64>();
    |                                        ^^^ The size of `f32` is smaller than the size of `i64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -644,13 +644,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f32` cannot be safely transmuted into `f64`
-  --> $DIR/numbers.rs:112:40
+  --> $DIR/numbers.rs:113:40
    |
 LL |     assert::is_transmutable::<  f32,   f64>();
    |                                        ^^^ The size of `f32` is smaller than the size of `f64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -659,13 +659,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f32` cannot be safely transmuted into `u128`
-  --> $DIR/numbers.rs:113:39
+  --> $DIR/numbers.rs:114:39
    |
 LL |     assert::is_transmutable::<  f32,  u128>();
    |                                       ^^^^ The size of `f32` is smaller than the size of `u128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -674,13 +674,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f32` cannot be safely transmuted into `i128`
-  --> $DIR/numbers.rs:114:39
+  --> $DIR/numbers.rs:115:39
    |
 LL |     assert::is_transmutable::<  f32,  i128>();
    |                                       ^^^^ The size of `f32` is smaller than the size of `i128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -689,13 +689,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u32` cannot be safely transmuted into `u64`
-  --> $DIR/numbers.rs:116:40
+  --> $DIR/numbers.rs:117:40
    |
 LL |     assert::is_transmutable::<  u32,   u64>();
    |                                        ^^^ The size of `u32` is smaller than the size of `u64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -704,13 +704,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u32` cannot be safely transmuted into `i64`
-  --> $DIR/numbers.rs:117:40
+  --> $DIR/numbers.rs:118:40
    |
 LL |     assert::is_transmutable::<  u32,   i64>();
    |                                        ^^^ The size of `u32` is smaller than the size of `i64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -719,13 +719,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u32` cannot be safely transmuted into `f64`
-  --> $DIR/numbers.rs:118:40
+  --> $DIR/numbers.rs:119:40
    |
 LL |     assert::is_transmutable::<  u32,   f64>();
    |                                        ^^^ The size of `u32` is smaller than the size of `f64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -734,13 +734,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u32` cannot be safely transmuted into `u128`
-  --> $DIR/numbers.rs:119:39
+  --> $DIR/numbers.rs:120:39
    |
 LL |     assert::is_transmutable::<  u32,  u128>();
    |                                       ^^^^ The size of `u32` is smaller than the size of `u128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -749,13 +749,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u32` cannot be safely transmuted into `i128`
-  --> $DIR/numbers.rs:120:39
+  --> $DIR/numbers.rs:121:39
    |
 LL |     assert::is_transmutable::<  u32,  i128>();
    |                                       ^^^^ The size of `u32` is smaller than the size of `i128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -764,13 +764,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u64` cannot be safely transmuted into `u128`
-  --> $DIR/numbers.rs:122:39
+  --> $DIR/numbers.rs:123:39
    |
 LL |     assert::is_transmutable::<  u64,  u128>();
    |                                       ^^^^ The size of `u64` is smaller than the size of `u128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -779,13 +779,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u64` cannot be safely transmuted into `i128`
-  --> $DIR/numbers.rs:123:39
+  --> $DIR/numbers.rs:124:39
    |
 LL |     assert::is_transmutable::<  u64,  i128>();
    |                                       ^^^^ The size of `u64` is smaller than the size of `i128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -794,13 +794,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i64` cannot be safely transmuted into `u128`
-  --> $DIR/numbers.rs:125:39
+  --> $DIR/numbers.rs:126:39
    |
 LL |     assert::is_transmutable::<  i64,  u128>();
    |                                       ^^^^ The size of `i64` is smaller than the size of `u128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -809,13 +809,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i64` cannot be safely transmuted into `i128`
-  --> $DIR/numbers.rs:126:39
+  --> $DIR/numbers.rs:127:39
    |
 LL |     assert::is_transmutable::<  i64,  i128>();
    |                                       ^^^^ The size of `i64` is smaller than the size of `i128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -824,13 +824,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f64` cannot be safely transmuted into `u128`
-  --> $DIR/numbers.rs:128:39
+  --> $DIR/numbers.rs:129:39
    |
 LL |     assert::is_transmutable::<  f64,  u128>();
    |                                       ^^^^ The size of `f64` is smaller than the size of `u128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -839,13 +839,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f64` cannot be safely transmuted into `i128`
-  --> $DIR/numbers.rs:129:39
+  --> $DIR/numbers.rs:130:39
    |
 LL |     assert::is_transmutable::<  f64,  i128>();
    |                                       ^^^^ The size of `f64` is smaller than the size of `i128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
diff --git a/tests/ui/transmutability/primitives/numbers.next.stderr b/tests/ui/transmutability/primitives/numbers.next.stderr
index 7a80e444149..009e377af99 100644
--- a/tests/ui/transmutability/primitives/numbers.next.stderr
+++ b/tests/ui/transmutability/primitives/numbers.next.stderr
@@ -1,11 +1,11 @@
 error[E0277]: `i8` cannot be safely transmuted into `i16`
-  --> $DIR/numbers.rs:64:40
+  --> $DIR/numbers.rs:65:40
    |
 LL |     assert::is_transmutable::<   i8,   i16>();
    |                                        ^^^ The size of `i8` is smaller than the size of `i16`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -14,13 +14,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `u16`
-  --> $DIR/numbers.rs:65:40
+  --> $DIR/numbers.rs:66:40
    |
 LL |     assert::is_transmutable::<   i8,   u16>();
    |                                        ^^^ The size of `i8` is smaller than the size of `u16`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -29,13 +29,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `i32`
-  --> $DIR/numbers.rs:66:40
+  --> $DIR/numbers.rs:67:40
    |
 LL |     assert::is_transmutable::<   i8,   i32>();
    |                                        ^^^ The size of `i8` is smaller than the size of `i32`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -44,13 +44,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `f32`
-  --> $DIR/numbers.rs:67:40
+  --> $DIR/numbers.rs:68:40
    |
 LL |     assert::is_transmutable::<   i8,   f32>();
    |                                        ^^^ The size of `i8` is smaller than the size of `f32`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -59,13 +59,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `u32`
-  --> $DIR/numbers.rs:68:40
+  --> $DIR/numbers.rs:69:40
    |
 LL |     assert::is_transmutable::<   i8,   u32>();
    |                                        ^^^ The size of `i8` is smaller than the size of `u32`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -74,13 +74,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `u64`
-  --> $DIR/numbers.rs:69:40
+  --> $DIR/numbers.rs:70:40
    |
 LL |     assert::is_transmutable::<   i8,   u64>();
    |                                        ^^^ The size of `i8` is smaller than the size of `u64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -89,13 +89,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `i64`
-  --> $DIR/numbers.rs:70:40
+  --> $DIR/numbers.rs:71:40
    |
 LL |     assert::is_transmutable::<   i8,   i64>();
    |                                        ^^^ The size of `i8` is smaller than the size of `i64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -104,13 +104,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `f64`
-  --> $DIR/numbers.rs:71:40
+  --> $DIR/numbers.rs:72:40
    |
 LL |     assert::is_transmutable::<   i8,   f64>();
    |                                        ^^^ The size of `i8` is smaller than the size of `f64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -119,13 +119,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `u128`
-  --> $DIR/numbers.rs:72:39
+  --> $DIR/numbers.rs:73:39
    |
 LL |     assert::is_transmutable::<   i8,  u128>();
    |                                       ^^^^ The size of `i8` is smaller than the size of `u128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -134,13 +134,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i8` cannot be safely transmuted into `i128`
-  --> $DIR/numbers.rs:73:39
+  --> $DIR/numbers.rs:74:39
    |
 LL |     assert::is_transmutable::<   i8,  i128>();
    |                                       ^^^^ The size of `i8` is smaller than the size of `i128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -149,13 +149,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `i16`
-  --> $DIR/numbers.rs:75:40
+  --> $DIR/numbers.rs:76:40
    |
 LL |     assert::is_transmutable::<   u8,   i16>();
    |                                        ^^^ The size of `u8` is smaller than the size of `i16`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -164,13 +164,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `u16`
-  --> $DIR/numbers.rs:76:40
+  --> $DIR/numbers.rs:77:40
    |
 LL |     assert::is_transmutable::<   u8,   u16>();
    |                                        ^^^ The size of `u8` is smaller than the size of `u16`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -179,13 +179,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `i32`
-  --> $DIR/numbers.rs:77:40
+  --> $DIR/numbers.rs:78:40
    |
 LL |     assert::is_transmutable::<   u8,   i32>();
    |                                        ^^^ The size of `u8` is smaller than the size of `i32`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -194,13 +194,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `f32`
-  --> $DIR/numbers.rs:78:40
+  --> $DIR/numbers.rs:79:40
    |
 LL |     assert::is_transmutable::<   u8,   f32>();
    |                                        ^^^ The size of `u8` is smaller than the size of `f32`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -209,13 +209,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `u32`
-  --> $DIR/numbers.rs:79:40
+  --> $DIR/numbers.rs:80:40
    |
 LL |     assert::is_transmutable::<   u8,   u32>();
    |                                        ^^^ The size of `u8` is smaller than the size of `u32`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -224,13 +224,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `u64`
-  --> $DIR/numbers.rs:80:40
+  --> $DIR/numbers.rs:81:40
    |
 LL |     assert::is_transmutable::<   u8,   u64>();
    |                                        ^^^ The size of `u8` is smaller than the size of `u64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -239,13 +239,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `i64`
-  --> $DIR/numbers.rs:81:40
+  --> $DIR/numbers.rs:82:40
    |
 LL |     assert::is_transmutable::<   u8,   i64>();
    |                                        ^^^ The size of `u8` is smaller than the size of `i64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -254,13 +254,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `f64`
-  --> $DIR/numbers.rs:82:40
+  --> $DIR/numbers.rs:83:40
    |
 LL |     assert::is_transmutable::<   u8,   f64>();
    |                                        ^^^ The size of `u8` is smaller than the size of `f64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -269,13 +269,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `u128`
-  --> $DIR/numbers.rs:83:39
+  --> $DIR/numbers.rs:84:39
    |
 LL |     assert::is_transmutable::<   u8,  u128>();
    |                                       ^^^^ The size of `u8` is smaller than the size of `u128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -284,13 +284,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u8` cannot be safely transmuted into `i128`
-  --> $DIR/numbers.rs:84:39
+  --> $DIR/numbers.rs:85:39
    |
 LL |     assert::is_transmutable::<   u8,  i128>();
    |                                       ^^^^ The size of `u8` is smaller than the size of `i128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -299,13 +299,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `i32`
-  --> $DIR/numbers.rs:86:40
+  --> $DIR/numbers.rs:87:40
    |
 LL |     assert::is_transmutable::<  i16,   i32>();
    |                                        ^^^ The size of `i16` is smaller than the size of `i32`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -314,13 +314,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `f32`
-  --> $DIR/numbers.rs:87:40
+  --> $DIR/numbers.rs:88:40
    |
 LL |     assert::is_transmutable::<  i16,   f32>();
    |                                        ^^^ The size of `i16` is smaller than the size of `f32`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -329,13 +329,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `u32`
-  --> $DIR/numbers.rs:88:40
+  --> $DIR/numbers.rs:89:40
    |
 LL |     assert::is_transmutable::<  i16,   u32>();
    |                                        ^^^ The size of `i16` is smaller than the size of `u32`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -344,13 +344,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `u64`
-  --> $DIR/numbers.rs:89:40
+  --> $DIR/numbers.rs:90:40
    |
 LL |     assert::is_transmutable::<  i16,   u64>();
    |                                        ^^^ The size of `i16` is smaller than the size of `u64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -359,13 +359,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `i64`
-  --> $DIR/numbers.rs:90:40
+  --> $DIR/numbers.rs:91:40
    |
 LL |     assert::is_transmutable::<  i16,   i64>();
    |                                        ^^^ The size of `i16` is smaller than the size of `i64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -374,13 +374,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `f64`
-  --> $DIR/numbers.rs:91:40
+  --> $DIR/numbers.rs:92:40
    |
 LL |     assert::is_transmutable::<  i16,   f64>();
    |                                        ^^^ The size of `i16` is smaller than the size of `f64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -389,13 +389,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `u128`
-  --> $DIR/numbers.rs:92:39
+  --> $DIR/numbers.rs:93:39
    |
 LL |     assert::is_transmutable::<  i16,  u128>();
    |                                       ^^^^ The size of `i16` is smaller than the size of `u128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -404,13 +404,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i16` cannot be safely transmuted into `i128`
-  --> $DIR/numbers.rs:93:39
+  --> $DIR/numbers.rs:94:39
    |
 LL |     assert::is_transmutable::<  i16,  i128>();
    |                                       ^^^^ The size of `i16` is smaller than the size of `i128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -419,13 +419,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `i32`
-  --> $DIR/numbers.rs:95:40
+  --> $DIR/numbers.rs:96:40
    |
 LL |     assert::is_transmutable::<  u16,   i32>();
    |                                        ^^^ The size of `u16` is smaller than the size of `i32`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -434,13 +434,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `f32`
-  --> $DIR/numbers.rs:96:40
+  --> $DIR/numbers.rs:97:40
    |
 LL |     assert::is_transmutable::<  u16,   f32>();
    |                                        ^^^ The size of `u16` is smaller than the size of `f32`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -449,13 +449,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `u32`
-  --> $DIR/numbers.rs:97:40
+  --> $DIR/numbers.rs:98:40
    |
 LL |     assert::is_transmutable::<  u16,   u32>();
    |                                        ^^^ The size of `u16` is smaller than the size of `u32`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -464,13 +464,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `u64`
-  --> $DIR/numbers.rs:98:40
+  --> $DIR/numbers.rs:99:40
    |
 LL |     assert::is_transmutable::<  u16,   u64>();
    |                                        ^^^ The size of `u16` is smaller than the size of `u64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -479,13 +479,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `i64`
-  --> $DIR/numbers.rs:99:40
+  --> $DIR/numbers.rs:100:40
    |
 LL |     assert::is_transmutable::<  u16,   i64>();
    |                                        ^^^ The size of `u16` is smaller than the size of `i64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -494,13 +494,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `f64`
-  --> $DIR/numbers.rs:100:40
+  --> $DIR/numbers.rs:101:40
    |
 LL |     assert::is_transmutable::<  u16,   f64>();
    |                                        ^^^ The size of `u16` is smaller than the size of `f64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -509,13 +509,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `u128`
-  --> $DIR/numbers.rs:101:39
+  --> $DIR/numbers.rs:102:39
    |
 LL |     assert::is_transmutable::<  u16,  u128>();
    |                                       ^^^^ The size of `u16` is smaller than the size of `u128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -524,13 +524,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u16` cannot be safely transmuted into `i128`
-  --> $DIR/numbers.rs:102:39
+  --> $DIR/numbers.rs:103:39
    |
 LL |     assert::is_transmutable::<  u16,  i128>();
    |                                       ^^^^ The size of `u16` is smaller than the size of `i128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -539,13 +539,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i32` cannot be safely transmuted into `u64`
-  --> $DIR/numbers.rs:104:40
+  --> $DIR/numbers.rs:105:40
    |
 LL |     assert::is_transmutable::<  i32,   u64>();
    |                                        ^^^ The size of `i32` is smaller than the size of `u64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -554,13 +554,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i32` cannot be safely transmuted into `i64`
-  --> $DIR/numbers.rs:105:40
+  --> $DIR/numbers.rs:106:40
    |
 LL |     assert::is_transmutable::<  i32,   i64>();
    |                                        ^^^ The size of `i32` is smaller than the size of `i64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -569,13 +569,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i32` cannot be safely transmuted into `f64`
-  --> $DIR/numbers.rs:106:40
+  --> $DIR/numbers.rs:107:40
    |
 LL |     assert::is_transmutable::<  i32,   f64>();
    |                                        ^^^ The size of `i32` is smaller than the size of `f64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -584,13 +584,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i32` cannot be safely transmuted into `u128`
-  --> $DIR/numbers.rs:107:39
+  --> $DIR/numbers.rs:108:39
    |
 LL |     assert::is_transmutable::<  i32,  u128>();
    |                                       ^^^^ The size of `i32` is smaller than the size of `u128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -599,13 +599,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i32` cannot be safely transmuted into `i128`
-  --> $DIR/numbers.rs:108:39
+  --> $DIR/numbers.rs:109:39
    |
 LL |     assert::is_transmutable::<  i32,  i128>();
    |                                       ^^^^ The size of `i32` is smaller than the size of `i128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -614,13 +614,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f32` cannot be safely transmuted into `u64`
-  --> $DIR/numbers.rs:110:40
+  --> $DIR/numbers.rs:111:40
    |
 LL |     assert::is_transmutable::<  f32,   u64>();
    |                                        ^^^ The size of `f32` is smaller than the size of `u64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -629,13 +629,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f32` cannot be safely transmuted into `i64`
-  --> $DIR/numbers.rs:111:40
+  --> $DIR/numbers.rs:112:40
    |
 LL |     assert::is_transmutable::<  f32,   i64>();
    |                                        ^^^ The size of `f32` is smaller than the size of `i64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -644,13 +644,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f32` cannot be safely transmuted into `f64`
-  --> $DIR/numbers.rs:112:40
+  --> $DIR/numbers.rs:113:40
    |
 LL |     assert::is_transmutable::<  f32,   f64>();
    |                                        ^^^ The size of `f32` is smaller than the size of `f64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -659,13 +659,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f32` cannot be safely transmuted into `u128`
-  --> $DIR/numbers.rs:113:39
+  --> $DIR/numbers.rs:114:39
    |
 LL |     assert::is_transmutable::<  f32,  u128>();
    |                                       ^^^^ The size of `f32` is smaller than the size of `u128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -674,13 +674,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f32` cannot be safely transmuted into `i128`
-  --> $DIR/numbers.rs:114:39
+  --> $DIR/numbers.rs:115:39
    |
 LL |     assert::is_transmutable::<  f32,  i128>();
    |                                       ^^^^ The size of `f32` is smaller than the size of `i128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -689,13 +689,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u32` cannot be safely transmuted into `u64`
-  --> $DIR/numbers.rs:116:40
+  --> $DIR/numbers.rs:117:40
    |
 LL |     assert::is_transmutable::<  u32,   u64>();
    |                                        ^^^ The size of `u32` is smaller than the size of `u64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -704,13 +704,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u32` cannot be safely transmuted into `i64`
-  --> $DIR/numbers.rs:117:40
+  --> $DIR/numbers.rs:118:40
    |
 LL |     assert::is_transmutable::<  u32,   i64>();
    |                                        ^^^ The size of `u32` is smaller than the size of `i64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -719,13 +719,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u32` cannot be safely transmuted into `f64`
-  --> $DIR/numbers.rs:118:40
+  --> $DIR/numbers.rs:119:40
    |
 LL |     assert::is_transmutable::<  u32,   f64>();
    |                                        ^^^ The size of `u32` is smaller than the size of `f64`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -734,13 +734,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u32` cannot be safely transmuted into `u128`
-  --> $DIR/numbers.rs:119:39
+  --> $DIR/numbers.rs:120:39
    |
 LL |     assert::is_transmutable::<  u32,  u128>();
    |                                       ^^^^ The size of `u32` is smaller than the size of `u128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -749,13 +749,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u32` cannot be safely transmuted into `i128`
-  --> $DIR/numbers.rs:120:39
+  --> $DIR/numbers.rs:121:39
    |
 LL |     assert::is_transmutable::<  u32,  i128>();
    |                                       ^^^^ The size of `u32` is smaller than the size of `i128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -764,13 +764,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u64` cannot be safely transmuted into `u128`
-  --> $DIR/numbers.rs:122:39
+  --> $DIR/numbers.rs:123:39
    |
 LL |     assert::is_transmutable::<  u64,  u128>();
    |                                       ^^^^ The size of `u64` is smaller than the size of `u128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -779,13 +779,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `u64` cannot be safely transmuted into `i128`
-  --> $DIR/numbers.rs:123:39
+  --> $DIR/numbers.rs:124:39
    |
 LL |     assert::is_transmutable::<  u64,  i128>();
    |                                       ^^^^ The size of `u64` is smaller than the size of `i128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -794,13 +794,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i64` cannot be safely transmuted into `u128`
-  --> $DIR/numbers.rs:125:39
+  --> $DIR/numbers.rs:126:39
    |
 LL |     assert::is_transmutable::<  i64,  u128>();
    |                                       ^^^^ The size of `i64` is smaller than the size of `u128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -809,13 +809,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `i64` cannot be safely transmuted into `i128`
-  --> $DIR/numbers.rs:126:39
+  --> $DIR/numbers.rs:127:39
    |
 LL |     assert::is_transmutable::<  i64,  i128>();
    |                                       ^^^^ The size of `i64` is smaller than the size of `i128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -824,13 +824,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f64` cannot be safely transmuted into `u128`
-  --> $DIR/numbers.rs:128:39
+  --> $DIR/numbers.rs:129:39
    |
 LL |     assert::is_transmutable::<  f64,  u128>();
    |                                       ^^^^ The size of `f64` is smaller than the size of `u128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
@@ -839,13 +839,13 @@ LL |         Dst: BikeshedIntrinsicFrom<Src>
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable`
 
 error[E0277]: `f64` cannot be safely transmuted into `i128`
-  --> $DIR/numbers.rs:129:39
+  --> $DIR/numbers.rs:130:39
    |
 LL |     assert::is_transmutable::<  f64,  i128>();
    |                                       ^^^^ The size of `f64` is smaller than the size of `i128`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/numbers.rs:14:14
+  --> $DIR/numbers.rs:15:14
    |
 LL |     pub fn is_transmutable<Src, Dst>()
    |            --------------- required by a bound in this function
diff --git a/tests/ui/transmutability/primitives/numbers.rs b/tests/ui/transmutability/primitives/numbers.rs
index 2b7d8a79860..896f5f49f67 100644
--- a/tests/ui/transmutability/primitives/numbers.rs
+++ b/tests/ui/transmutability/primitives/numbers.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 #![crate_type = "lib"]
diff --git a/tests/ui/transmutability/primitives/unit.current.stderr b/tests/ui/transmutability/primitives/unit.current.stderr
index 37088a69698..b2831dbf842 100644
--- a/tests/ui/transmutability/primitives/unit.current.stderr
+++ b/tests/ui/transmutability/primitives/unit.current.stderr
@@ -1,11 +1,11 @@
 error[E0277]: `()` cannot be safely transmuted into `u8`
-  --> $DIR/unit.rs:30:35
+  --> $DIR/unit.rs:31:35
    |
 LL |     assert::is_transmutable::<(), u8>();
    |                                   ^^ The size of `()` is smaller than the size of `u8`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/unit.rs:15:14
+  --> $DIR/unit.rs:16:14
    |
 LL |       pub fn is_transmutable<Src, Dst>()
    |              --------------- required by a bound in this function
diff --git a/tests/ui/transmutability/primitives/unit.next.stderr b/tests/ui/transmutability/primitives/unit.next.stderr
index 37088a69698..b2831dbf842 100644
--- a/tests/ui/transmutability/primitives/unit.next.stderr
+++ b/tests/ui/transmutability/primitives/unit.next.stderr
@@ -1,11 +1,11 @@
 error[E0277]: `()` cannot be safely transmuted into `u8`
-  --> $DIR/unit.rs:30:35
+  --> $DIR/unit.rs:31:35
    |
 LL |     assert::is_transmutable::<(), u8>();
    |                                   ^^ The size of `()` is smaller than the size of `u8`
    |
 note: required by a bound in `is_transmutable`
-  --> $DIR/unit.rs:15:14
+  --> $DIR/unit.rs:16:14
    |
 LL |       pub fn is_transmutable<Src, Dst>()
    |              --------------- required by a bound in this function
diff --git a/tests/ui/transmutability/primitives/unit.rs b/tests/ui/transmutability/primitives/unit.rs
index 24649443565..44216950f55 100644
--- a/tests/ui/transmutability/primitives/unit.rs
+++ b/tests/ui/transmutability/primitives/unit.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 //! The unit type, `()`, should be one byte.
diff --git a/tests/ui/type-alias-impl-trait/assoc-type-const.rs b/tests/ui/type-alias-impl-trait/assoc-type-const.rs
index 3591773209a..cc55fc2a41f 100644
--- a/tests/ui/type-alias-impl-trait/assoc-type-const.rs
+++ b/tests/ui/type-alias-impl-trait/assoc-type-const.rs
@@ -3,6 +3,7 @@
 
 //@ check-pass
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 #![feature(impl_trait_in_assoc_type)]
 
diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr
index f6f75455799..6bdc76aab45 100644
--- a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr
+++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr
@@ -6,16 +6,12 @@ LL |         is_send(foo());
    |         |
    |         required by a bound introduced by this call
    |
+   = note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
 note: opaque type is declared here
   --> $DIR/auto-trait-leakage3.rs:7:20
    |
 LL |     pub type Foo = impl std::fmt::Debug;
    |                    ^^^^^^^^^^^^^^^^^^^^
-note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
-  --> $DIR/auto-trait-leakage3.rs:12:12
-   |
-LL |     pub fn bar() {
-   |            ^^^
 note: required by a bound in `is_send`
   --> $DIR/auto-trait-leakage3.rs:17:19
    |
diff --git a/tests/ui/type-alias-impl-trait/cross_inference.rs b/tests/ui/type-alias-impl-trait/cross_inference.rs
index 50777e57112..2f0d1e89d47 100644
--- a/tests/ui/type-alias-impl-trait/cross_inference.rs
+++ b/tests/ui/type-alias-impl-trait/cross_inference.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@ check-pass
 
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
index 495308a6cac..73570de5326 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
@@ -35,18 +35,6 @@ LL | type TwoLifetimes<'a, 'b> = impl Debug;
    |                             ^^^^^^^^^^
 
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use.rs:29:5
-   |
-LL |     t
-   |     ^
-   |
-note: lifetime used multiple times
-  --> $DIR/generic_duplicate_param_use.rs:17:19
-   |
-LL | type TwoLifetimes<'a, 'b> = impl Debug;
-   |                   ^^  ^^
-
-error: non-defining opaque type use in defining scope
   --> $DIR/generic_duplicate_param_use.rs:33:50
    |
 LL | fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> {
@@ -59,6 +47,18 @@ LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug;
    |                                                  ^^^^^^^^^^
 
 error: non-defining opaque type use in defining scope
+  --> $DIR/generic_duplicate_param_use.rs:29:5
+   |
+LL |     t
+   |     ^
+   |
+note: lifetime used multiple times
+  --> $DIR/generic_duplicate_param_use.rs:17:19
+   |
+LL | type TwoLifetimes<'a, 'b> = impl Debug;
+   |                   ^^  ^^
+
+error: non-defining opaque type use in defining scope
   --> $DIR/generic_duplicate_param_use.rs:35:5
    |
 LL |     t
diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr b/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr
index e3b7b1a76b0..bd68b4e3ea4 100644
--- a/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr
@@ -31,15 +31,6 @@ note: for this opaque type
 LL | type OneLifetime<'a> = impl Debug;
    |                        ^^^^^^^^^^
 
-error[E0792]: expected generic lifetime parameter, found `'static`
-  --> $DIR/generic_nondefining_use.rs:23:5
-   |
-LL | type OneLifetime<'a> = impl Debug;
-   |                  -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
-...
-LL |     6u32
-   |     ^^^^
-
 error[E0792]: non-defining opaque type use in defining scope
   --> $DIR/generic_nondefining_use.rs:27:24
    |
@@ -52,6 +43,15 @@ note: for this opaque type
 LL | type OneConst<const X: usize> = impl Debug;
    |                                 ^^^^^^^^^^
 
+error[E0792]: expected generic lifetime parameter, found `'static`
+  --> $DIR/generic_nondefining_use.rs:23:5
+   |
+LL | type OneLifetime<'a> = impl Debug;
+   |                  -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
+...
+LL |     6u32
+   |     ^^^^
+
 error[E0792]: expected generic constant parameter, found `123`
   --> $DIR/generic_nondefining_use.rs:29:5
    |
diff --git a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.rs b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.rs
index 12ce6b14e31..5b5acb31812 100644
--- a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.rs
+++ b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.rs
@@ -9,7 +9,6 @@
 mod sus {
     use super::*;
     pub type Sep = impl Sized + std::fmt::Display;
-    //~^ ERROR: concrete type differs from previous defining opaque type use
     pub fn mk_sep() -> Sep {
         String::from("hello")
     }
@@ -42,6 +41,7 @@ mod sus {
         (): Proj<Assoc = i32>,
     {
         Bar { inner: 1i32, _marker: () }
+        //~^ ERROR type mismatch
     }
 }
 
diff --git a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr
index 5a6998f4165..21d9ed93366 100644
--- a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr
+++ b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr
@@ -1,14 +1,27 @@
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/hidden_type_mismatch.rs:11:20
+error[E0271]: type mismatch resolving `<() as Proj>::Assoc == i32`
+  --> $DIR/hidden_type_mismatch.rs:43:9
    |
 LL |     pub type Sep = impl Sized + std::fmt::Display;
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, got `String`
+   |                    ------------------------------ the expected opaque type
+...
+LL |         Bar { inner: 1i32, _marker: () }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<() as Proj>::Assoc == i32`
    |
-note: previous use here
-  --> $DIR/hidden_type_mismatch.rs:37:21
+note: expected this to be `Sep`
+  --> $DIR/hidden_type_mismatch.rs:20:22
    |
-LL |     pub type Tait = impl Copy + From<Bar<()>> + Into<Bar<()>>;
-   |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |         type Assoc = sus::Sep;
+   |                      ^^^^^^^^
+   = note: expected opaque type `Sep`
+                     found type `i32`
+note: required for `Bar<()>` to implement `Copy`
+  --> $DIR/hidden_type_mismatch.rs:32:39
+   |
+LL |     impl<T: Proj<Assoc = i32> + Copy> Copy for Bar<T> {}
+   |                  -----------          ^^^^     ^^^^^^
+   |                  |
+   |                  unsatisfied trait bound introduced here
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params2.rs b/tests/ui/type-alias-impl-trait/higher_kinded_params2.rs
index 1022e5c4ece..19c6099135d 100644
--- a/tests/ui/type-alias-impl-trait/higher_kinded_params2.rs
+++ b/tests/ui/type-alias-impl-trait/higher_kinded_params2.rs
@@ -24,7 +24,7 @@ type Successors<'a> = impl std::fmt::Debug + 'a;
 impl Terminator {
     fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> {
         f = g;
-        //~^ ERROR item constrains opaque type that is not in its signature
+        //~^ ERROR mismatched types
     }
 }
 
diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params2.stderr b/tests/ui/type-alias-impl-trait/higher_kinded_params2.stderr
index e037dede2e0..790e7fe8580 100644
--- a/tests/ui/type-alias-impl-trait/higher_kinded_params2.stderr
+++ b/tests/ui/type-alias-impl-trait/higher_kinded_params2.stderr
@@ -1,11 +1,15 @@
-error: item constrains opaque type that is not in its signature
+error[E0308]: mismatched types
   --> $DIR/higher_kinded_params2.rs:26:13
    |
+LL | type Tait = impl std::fmt::Debug;
+   |             -------------------- the expected opaque type
+...
 LL |         f = g;
-   |             ^
+   |             ^ expected fn pointer, found fn item
    |
-   = note: this item must mention the opaque type in its signature in order to be able to register hidden types
-note: this item must mention the opaque type in its signature in order to be able to register hidden types
+   = note: expected fn pointer `for<'x> fn(&'x ()) -> Tait`
+                 found fn item `for<'a> fn(&'a ()) -> String {g}`
+note: this item must have the opaque type in its signature in order to be able to register hidden types
   --> $DIR/higher_kinded_params2.rs:25:8
    |
 LL |     fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> {
@@ -13,3 +17,4 @@ LL |     fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> S
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs b/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs
index e0bb1e2d02f..3845cde29fa 100644
--- a/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs
+++ b/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs
@@ -25,7 +25,6 @@ impl Terminator {
     fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> {
         f = g;
         //~^ ERROR mismatched types
-        //~| ERROR item constrains opaque type that is not in its signature
     }
 }
 
diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr b/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr
index 14372d8f3e6..41a3f9ce268 100644
--- a/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr
+++ b/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr
@@ -1,28 +1,20 @@
-error: item constrains opaque type that is not in its signature
-  --> $DIR/higher_kinded_params3.rs:26:13
-   |
-LL |         f = g;
-   |             ^
-   |
-   = note: this item must mention the opaque type in its signature in order to be able to register hidden types
-note: this item must mention the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/higher_kinded_params3.rs:25:8
-   |
-LL |     fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> {
-   |        ^^^^^^^^^^
-
 error[E0308]: mismatched types
-  --> $DIR/higher_kinded_params3.rs:26:9
+  --> $DIR/higher_kinded_params3.rs:26:13
    |
 LL | type Tait<'a> = impl std::fmt::Debug + 'a;
    |                 ------------------------- the expected opaque type
 ...
 LL |         f = g;
-   |         ^^^^^ one type is more general than the other
+   |             ^ expected fn pointer, found fn item
    |
    = note: expected fn pointer `for<'x> fn(&'x ()) -> Tait<'x>`
-              found fn pointer `for<'a> fn(&'a ()) -> &'a ()`
+                 found fn item `for<'a> fn(&'a ()) -> &'a () {g}`
+note: this item must have the opaque type in its signature in order to be able to register hidden types
+  --> $DIR/higher_kinded_params3.rs:25:8
+   |
+LL |     fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> {
+   |        ^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/implied_bounds_from_types.rs b/tests/ui/type-alias-impl-trait/implied_bounds_from_types.rs
index 8023cd24f0b..239fcc6a5e6 100644
--- a/tests/ui/type-alias-impl-trait/implied_bounds_from_types.rs
+++ b/tests/ui/type-alias-impl-trait/implied_bounds_from_types.rs
@@ -12,6 +12,7 @@ impl<'a> Convert<'a> for () {
     type Witness = WithLifetime<&'a ()>;
 
     fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<&'a ()>, x: &'a T) -> &'b T {
+        //~^ ERROR non-defining opaque type use
         // compiler used to think it gets to assume 'a: 'b here because
         // of the `&'b WithLifetime<&'a ()>` argument
         x
diff --git a/tests/ui/type-alias-impl-trait/implied_bounds_from_types.stderr b/tests/ui/type-alias-impl-trait/implied_bounds_from_types.stderr
index 5967a946830..23dbf0e8f60 100644
--- a/tests/ui/type-alias-impl-trait/implied_bounds_from_types.stderr
+++ b/tests/ui/type-alias-impl-trait/implied_bounds_from_types.stderr
@@ -1,5 +1,17 @@
+error[E0792]: non-defining opaque type use in defining scope
+  --> $DIR/implied_bounds_from_types.rs:14:39
+   |
+LL |     fn convert<'b, T: ?Sized>(_proof: &'b WithLifetime<&'a ()>, x: &'a T) -> &'b T {
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^ argument `&'a ()` is not a generic parameter
+   |
+note: for this opaque type
+  --> $DIR/implied_bounds_from_types.rs:3:24
+   |
+LL | type WithLifetime<T> = impl Equals<SelfType = ()>;
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error: lifetime may not live long enough
-  --> $DIR/implied_bounds_from_types.rs:17:9
+  --> $DIR/implied_bounds_from_types.rs:18:9
    |
 LL | impl<'a> Convert<'a> for () {
    |      -- lifetime `'a` defined here
@@ -12,5 +24,6 @@ LL |         x
    |
    = help: consider adding the following bound: `'a: 'b`
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/in-where-clause.rs b/tests/ui/type-alias-impl-trait/in-where-clause.rs
index 0ad6e7a6f60..7c0de39c7c9 100644
--- a/tests/ui/type-alias-impl-trait/in-where-clause.rs
+++ b/tests/ui/type-alias-impl-trait/in-where-clause.rs
@@ -1,5 +1,5 @@
 //! We evaluate `1 + 2` with `Reveal::All` during typeck, causing
-//! us to to get the concrete type of `Bar` while computing it.
+//! us to get the concrete type of `Bar` while computing it.
 //! This again requires type checking `foo`.
 #![feature(type_alias_impl_trait)]
 type Bar = impl Sized;
diff --git a/tests/ui/type-alias-impl-trait/inference-cycle.stderr b/tests/ui/type-alias-impl-trait/inference-cycle.stderr
index fd7488fa260..8b809ba014d 100644
--- a/tests/ui/type-alias-impl-trait/inference-cycle.stderr
+++ b/tests/ui/type-alias-impl-trait/inference-cycle.stderr
@@ -6,16 +6,12 @@ LL |         is_send(foo());
    |         |
    |         required by a bound introduced by this call
    |
+   = note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
 note: opaque type is declared here
   --> $DIR/inference-cycle.rs:5:20
    |
 LL |     pub type Foo = impl std::fmt::Debug;
    |                    ^^^^^^^^^^^^^^^^^^^^
-note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
-  --> $DIR/inference-cycle.rs:11:12
-   |
-LL |     pub fn bar() {
-   |            ^^^
 note: required by a bound in `is_send`
   --> $DIR/inference-cycle.rs:21:19
    |
diff --git a/tests/ui/type-alias-impl-trait/issue-53092-2.rs b/tests/ui/type-alias-impl-trait/issue-53092-2.rs
index 057930f0c1c..61b23a3a933 100644
--- a/tests/ui/type-alias-impl-trait/issue-53092-2.rs
+++ b/tests/ui/type-alias-impl-trait/issue-53092-2.rs
@@ -4,6 +4,7 @@
 type Bug<T, U> = impl Fn(T) -> U + Copy; //~ ERROR cycle detected
 
 const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
+//~^ ERROR: non-defining opaque type use
 
 fn make_bug<T, U: From<T>>() -> Bug<T, U> {
     |x| x.into() //~ ERROR the trait bound `U: From<T>` is not satisfied
diff --git a/tests/ui/type-alias-impl-trait/issue-53092-2.stderr b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr
index e805a71ea6f..c2da5fc265c 100644
--- a/tests/ui/type-alias-impl-trait/issue-53092-2.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr
@@ -1,3 +1,15 @@
+error[E0792]: non-defining opaque type use in defining scope
+  --> $DIR/issue-53092-2.rs:6:18
+   |
+LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
+   |                  ^^^^^^^^^^^ argument `u8` is not a generic parameter
+   |
+note: for this opaque type
+  --> $DIR/issue-53092-2.rs:4:18
+   |
+LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
+   |                  ^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0391]: cycle detected when computing type of `Bug::{opaque#0}`
   --> $DIR/issue-53092-2.rs:4:18
    |
@@ -25,13 +37,13 @@ LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
    = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
 
 error[E0277]: the trait bound `U: From<T>` is not satisfied
-  --> $DIR/issue-53092-2.rs:9:5
+  --> $DIR/issue-53092-2.rs:10:5
    |
 LL |     |x| x.into()
    |     ^^^^^^^^^^^^ the trait `From<T>` is not implemented for `U`
    |
 note: required by a bound in `make_bug`
-  --> $DIR/issue-53092-2.rs:8:19
+  --> $DIR/issue-53092-2.rs:9:19
    |
 LL | fn make_bug<T, U: From<T>>() -> Bug<T, U> {
    |                   ^^^^^^^ required by this bound in `make_bug`
@@ -40,7 +52,7 @@ help: consider restricting type parameter `U`
 LL | type Bug<T, U: std::convert::From<T>> = impl Fn(T) -> U + Copy;
    |              +++++++++++++++++++++++
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0277, E0391.
+Some errors have detailed explanations: E0277, E0391, E0792.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/type-alias-impl-trait/issue-53092.rs b/tests/ui/type-alias-impl-trait/issue-53092.rs
index 1be5b46d6df..34bab026088 100644
--- a/tests/ui/type-alias-impl-trait/issue-53092.rs
+++ b/tests/ui/type-alias-impl-trait/issue-53092.rs
@@ -9,6 +9,7 @@ union Moo {
 }
 
 const CONST_BUG: Bug<u8, ()> = unsafe { Moo { y: () }.x };
+//~^ ERROR non-defining opaque type use
 
 fn make_bug<T, U: From<T>>() -> Bug<T, U> {
     |x| x.into() //~ ERROR the trait bound `U: From<T>` is not satisfied
diff --git a/tests/ui/type-alias-impl-trait/issue-53092.stderr b/tests/ui/type-alias-impl-trait/issue-53092.stderr
index 8605a098193..0c4cacd6655 100644
--- a/tests/ui/type-alias-impl-trait/issue-53092.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-53092.stderr
@@ -1,11 +1,23 @@
+error[E0792]: non-defining opaque type use in defining scope
+  --> $DIR/issue-53092.rs:11:18
+   |
+LL | const CONST_BUG: Bug<u8, ()> = unsafe { Moo { y: () }.x };
+   |                  ^^^^^^^^^^^ argument `u8` is not a generic parameter
+   |
+note: for this opaque type
+  --> $DIR/issue-53092.rs:4:18
+   |
+LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
+   |                  ^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0277]: the trait bound `U: From<T>` is not satisfied
-  --> $DIR/issue-53092.rs:14:5
+  --> $DIR/issue-53092.rs:15:5
    |
 LL |     |x| x.into()
    |     ^^^^^^^^^^^^ the trait `From<T>` is not implemented for `U`
    |
 note: required by a bound in `make_bug`
-  --> $DIR/issue-53092.rs:13:19
+  --> $DIR/issue-53092.rs:14:19
    |
 LL | fn make_bug<T, U: From<T>>() -> Bug<T, U> {
    |                   ^^^^^^^ required by this bound in `make_bug`
@@ -14,6 +26,7 @@ help: consider restricting type parameter `U`
 LL | type Bug<T, U: std::convert::From<T>> = impl Fn(T) -> U + Copy;
    |              +++++++++++++++++++++++
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0277`.
+Some errors have detailed explanations: E0277, E0792.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/type-alias-impl-trait/issue-70121.rs b/tests/ui/type-alias-impl-trait/issue-70121.rs
index bfd8d8872e3..b90bd312a0b 100644
--- a/tests/ui/type-alias-impl-trait/issue-70121.rs
+++ b/tests/ui/type-alias-impl-trait/issue-70121.rs
@@ -15,8 +15,8 @@ impl<'a> Tr for &'a () {
 }
 
 pub fn kazusa<'a>() -> <&'a () as Tr>::Item {
-    //~^ ERROR item constrains opaque type that is not in its signature
     None.into_iter()
+    //~^ ERROR mismatched types
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-70121.stderr b/tests/ui/type-alias-impl-trait/issue-70121.stderr
index d6ab26e30da..ed2eb17fbea 100644
--- a/tests/ui/type-alias-impl-trait/issue-70121.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-70121.stderr
@@ -1,11 +1,17 @@
-error: item constrains opaque type that is not in its signature
-  --> $DIR/issue-70121.rs:17:24
+error[E0308]: mismatched types
+  --> $DIR/issue-70121.rs:18:5
    |
+LL | pub type Successors<'a> = impl Iterator<Item = &'a ()>;
+   |                           ---------------------------- the expected opaque type
+...
 LL | pub fn kazusa<'a>() -> <&'a () as Tr>::Item {
-   |                        ^^^^^^^^^^^^^^^^^^^^
+   |                        -------------------- expected `Successors<'a>` because of return type
+LL |     None.into_iter()
+   |     ^^^^^^^^^^^^^^^^ expected opaque type, found `IntoIter<_>`
    |
-   = note: this item must mention the opaque type in its signature in order to be able to register hidden types
-note: this item must mention the opaque type in its signature in order to be able to register hidden types
+   = note: expected opaque type `Successors<'a>`
+                   found struct `std::option::IntoIter<_>`
+note: this item must have the opaque type in its signature in order to be able to register hidden types
   --> $DIR/issue-70121.rs:17:8
    |
 LL | pub fn kazusa<'a>() -> <&'a () as Tr>::Item {
@@ -13,3 +19,4 @@ LL | pub fn kazusa<'a>() -> <&'a () as Tr>::Item {
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs b/tests/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs
index f072bb88792..9ceef0139f0 100644
--- a/tests/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs
+++ b/tests/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs
@@ -2,6 +2,7 @@
 // Tests that we don't ICE when we have a trait impl on a TAIT.
 
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@ check-pass
 #![feature(type_alias_impl_trait)]
diff --git a/tests/ui/type-alias-impl-trait/issue-77179.rs b/tests/ui/type-alias-impl-trait/issue-77179.rs
index 2d9345a3e5e..1dc74c6b5fe 100644
--- a/tests/ui/type-alias-impl-trait/issue-77179.rs
+++ b/tests/ui/type-alias-impl-trait/issue-77179.rs
@@ -7,7 +7,7 @@ type Pointer<T> = impl std::ops::Deref<Target = T>;
 fn test() -> Pointer<_> {
     //~^ ERROR: the placeholder `_` is not allowed within types
     Box::new(1)
-    //~^ ERROR: expected generic type parameter, found `i32`
+    //~^ ERROR: mismatched types
 }
 
 fn main() {
diff --git a/tests/ui/type-alias-impl-trait/issue-77179.stderr b/tests/ui/type-alias-impl-trait/issue-77179.stderr
index ebd78e5b7a5..85a943c26e2 100644
--- a/tests/ui/type-alias-impl-trait/issue-77179.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-77179.stderr
@@ -1,11 +1,28 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-77179.rs:9:5
+   |
+LL | type Pointer<T> = impl std::ops::Deref<Target = T>;
+   |                   -------------------------------- the expected opaque type
+LL |
+LL | fn test() -> Pointer<_> {
+   |              ---------- expected `Pointer<_>` because of return type
+LL |
+LL |     Box::new(1)
+   |     ^^^^^^^^^^^ expected opaque type, found `Box<{integer}>`
+   |
+   = note: expected opaque type `Pointer<_>`
+                   found struct `Box<{integer}>`
+note: this item must have the opaque type in its signature in order to be able to register hidden types
+  --> $DIR/issue-77179.rs:7:4
+   |
+LL | fn test() -> Pointer<_> {
+   |    ^^^^
+
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
   --> $DIR/issue-77179.rs:7:22
    |
 LL | fn test() -> Pointer<_> {
-   |              --------^-
-   |              |       |
-   |              |       not allowed in type signatures
-   |              help: replace with the correct return type: `Pointer<i32>`
+   |                      ^ not allowed in type signatures
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
   --> $DIR/issue-77179.rs:18:25
@@ -16,16 +33,7 @@ LL |     fn bar() -> Pointer<_>;
    |                         not allowed in type signatures
    |                         help: use type parameters instead: `T`
 
-error[E0792]: expected generic type parameter, found `i32`
-  --> $DIR/issue-77179.rs:9:5
-   |
-LL | type Pointer<T> = impl std::ops::Deref<Target = T>;
-   |              - this generic parameter must be used with a generic type parameter
-...
-LL |     Box::new(1)
-   |     ^^^^^^^^^^^
-
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0121, E0792.
+Some errors have detailed explanations: E0121, E0308.
 For more information about an error, try `rustc --explain E0121`.
diff --git a/tests/ui/type-alias-impl-trait/issue-78450.rs b/tests/ui/type-alias-impl-trait/issue-78450.rs
index d1328be8475..7d749b1a349 100644
--- a/tests/ui/type-alias-impl-trait/issue-78450.rs
+++ b/tests/ui/type-alias-impl-trait/issue-78450.rs
@@ -1,5 +1,6 @@
 //@ check-pass
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 #![feature(impl_trait_in_assoc_type)]
diff --git a/tests/ui/type-alias-impl-trait/multi-error.rs b/tests/ui/type-alias-impl-trait/multi-error.rs
index b5ff06572d0..cb4ad4dc633 100644
--- a/tests/ui/type-alias-impl-trait/multi-error.rs
+++ b/tests/ui/type-alias-impl-trait/multi-error.rs
@@ -17,6 +17,7 @@ impl Foo for () {
     fn foo() -> (Self::Bar<u32>, Self::Baz) {
         //~^ ERROR non-defining opaque type use
         ((), ())
+        //~^ ERROR expected generic type parameter
     }
 }
 
diff --git a/tests/ui/type-alias-impl-trait/multi-error.stderr b/tests/ui/type-alias-impl-trait/multi-error.stderr
index b0e6d13b0e1..761f01b32ac 100644
--- a/tests/ui/type-alias-impl-trait/multi-error.stderr
+++ b/tests/ui/type-alias-impl-trait/multi-error.stderr
@@ -10,6 +10,15 @@ note: for this opaque type
 LL |     type Bar<T> = impl Sized;
    |                   ^^^^^^^^^^
 
-error: aborting due to 1 previous error
+error[E0792]: expected generic type parameter, found `u32`
+  --> $DIR/multi-error.rs:19:9
+   |
+LL |     type Bar<T> = impl Sized;
+   |              - this generic parameter must be used with a generic type parameter
+...
+LL |         ((), ())
+   |         ^^^^^^^^
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/nested_inference_failure.rs b/tests/ui/type-alias-impl-trait/nested_inference_failure.rs
index 08acfea0004..004e79d6738 100644
--- a/tests/ui/type-alias-impl-trait/nested_inference_failure.rs
+++ b/tests/ui/type-alias-impl-trait/nested_inference_failure.rs
@@ -1,6 +1,7 @@
 //@ check-pass
-//@ revisions: new old
-//@[new] compile-flags: -Znext-solver
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
 
 //! This test checks that we can successfully infer
 //! the hidden type of `FooImpl` to be `Foo<i32, {closure}>`
diff --git a/tests/ui/type-alias-impl-trait/non-defining-method.rs b/tests/ui/type-alias-impl-trait/non-defining-method.rs
index 2f4a7052f72..8551806b3cb 100644
--- a/tests/ui/type-alias-impl-trait/non-defining-method.rs
+++ b/tests/ui/type-alias-impl-trait/non-defining-method.rs
@@ -15,6 +15,7 @@ impl Foo for () {
     type Bar<T> = impl Sized;
     fn foo() -> Self::Bar<u32> {}
     //~^ ERROR non-defining opaque type use
+    //~| ERROR expected generic type parameter, found `u32`
     fn bar<T>() -> Self::Bar<T> {}
 }
 
diff --git a/tests/ui/type-alias-impl-trait/non-defining-method.stderr b/tests/ui/type-alias-impl-trait/non-defining-method.stderr
index 2ba4c90a1c4..49a393ca745 100644
--- a/tests/ui/type-alias-impl-trait/non-defining-method.stderr
+++ b/tests/ui/type-alias-impl-trait/non-defining-method.stderr
@@ -10,6 +10,14 @@ note: for this opaque type
 LL |     type Bar<T> = impl Sized;
    |                   ^^^^^^^^^^
 
-error: aborting due to 1 previous error
+error[E0792]: expected generic type parameter, found `u32`
+  --> $DIR/non-defining-method.rs:16:32
+   |
+LL |     type Bar<T> = impl Sized;
+   |              - this generic parameter must be used with a generic type parameter
+LL |     fn foo() -> Self::Bar<u32> {}
+   |                                ^^
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr b/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr
index dd2737c706d..a40dac06a01 100644
--- a/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr
+++ b/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr
@@ -1,5 +1,5 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/normalize-hidden-types.rs:25:20
+  --> $DIR/normalize-hidden-types.rs:26:20
    |
 LL |     fn define() -> Opaque {
    |                    ^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(<u8 as Trait>::Gat<'a>)`
@@ -23,7 +23,7 @@ LL |     fn define_1() -> Opaque { dyn_hoops::<_>(0) }
    |                               ^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
-  --> $DIR/normalize-hidden-types.rs:44:25
+  --> $DIR/normalize-hidden-types.rs:43:25
    |
 LL |     type Opaque = impl Sized;
    |                   ---------- the expected opaque type
@@ -39,13 +39,13 @@ LL |         let _: Opaque = dyn_hoops::<u8>(0);
    = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
 
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/normalize-hidden-types.rs:54:25
+  --> $DIR/normalize-hidden-types.rs:52:25
    |
 LL |         let _: Opaque = dyn_hoops::<_>(0);
    |                         ^^^^^^^^^^^^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(<u8 as Trait>::Gat<'a>)`
    |
 note: previous use here
-  --> $DIR/normalize-hidden-types.rs:56:9
+  --> $DIR/normalize-hidden-types.rs:53:9
    |
 LL |         None
    |         ^^^^
diff --git a/tests/ui/type-alias-impl-trait/normalize-hidden-types.rs b/tests/ui/type-alias-impl-trait/normalize-hidden-types.rs
index e78e6cf7690..4028dba82bf 100644
--- a/tests/ui/type-alias-impl-trait/normalize-hidden-types.rs
+++ b/tests/ui/type-alias-impl-trait/normalize-hidden-types.rs
@@ -1,9 +1,10 @@
 // Regression test for #112691
 //
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@ [next] compile-flags: -Znext-solver
 //@ [next] check-pass
-//@ [current]: known-bug: #112691
+//@ [current] known-bug: #112691
 
 #![feature(type_alias_impl_trait)]
 
@@ -23,7 +24,6 @@ mod typeof_1 {
     use super::*;
     type Opaque = impl Sized;
     fn define() -> Opaque {
-        //[current]~^ ERROR concrete type differs
         dyn_hoops::<_>(0)
     }
 }
@@ -32,7 +32,6 @@ mod typeof_2 {
     use super::*;
     type Opaque = impl Sized;
     fn define_1() -> Opaque { dyn_hoops::<_>(0) }
-    //[current]~^ ERROR concrete type differs
     fn define_2() -> Opaque { dyn_hoops::<u8>(0) }
 }
 
@@ -42,7 +41,6 @@ mod typeck {
     fn define() -> Option<Opaque> {
         let _: Opaque = dyn_hoops::<_>(0);
         let _: Opaque = dyn_hoops::<u8>(0);
-        //[current]~^ ERROR mismatched types
         None
     }
 }
@@ -52,7 +50,6 @@ mod borrowck {
     type Opaque = impl Sized;
     fn define() -> Option<Opaque> {
         let _: Opaque = dyn_hoops::<_>(0);
-        //[current]~^ ERROR concrete type differs
         None
     }
 }
diff --git a/tests/ui/type-alias-impl-trait/reveal_local.stderr b/tests/ui/type-alias-impl-trait/reveal_local.stderr
index 796e2d011dc..e1b320cc38e 100644
--- a/tests/ui/type-alias-impl-trait/reveal_local.stderr
+++ b/tests/ui/type-alias-impl-trait/reveal_local.stderr
@@ -4,16 +4,12 @@ error: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque
 LL |     is_send::<Foo>();
    |               ^^^
    |
+   = note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
 note: opaque type is declared here
   --> $DIR/reveal_local.rs:5:12
    |
 LL | type Foo = impl Debug;
    |            ^^^^^^^^^^
-note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
-  --> $DIR/reveal_local.rs:9:4
-   |
-LL | fn not_good() {
-   |    ^^^^^^^^
 note: required by a bound in `is_send`
   --> $DIR/reveal_local.rs:7:15
    |
@@ -26,16 +22,12 @@ error: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque
 LL |     is_send::<Foo>();
    |               ^^^
    |
+   = note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
 note: opaque type is declared here
   --> $DIR/reveal_local.rs:5:12
    |
 LL | type Foo = impl Debug;
    |            ^^^^^^^^^^
-note: this item depends on auto traits of the hidden type, but may also be registering the hidden type. This is not supported right now. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
-  --> $DIR/reveal_local.rs:16:4
-   |
-LL | fn not_gooder() -> Foo {
-   |    ^^^^^^^^^^
 note: required by a bound in `is_send`
   --> $DIR/reveal_local.rs:7:15
    |
diff --git a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr
index 069292239bc..1c36fda4ae1 100644
--- a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr
+++ b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.current.stderr
@@ -8,13 +8,13 @@ error: internal compiler error: {OpaqueTypeKey { def_id: DefId(get_rpit::{opaque
            
 
 error: internal compiler error: error performing ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing }, value: ProvePredicate { predicate: Binder { value: ProjectionPredicate(AliasTy { args: [FnDef(DefId(get_rpit), []), ()], def_id: DefId(ops::function::FnOnce::Output) }, Term::Ty(Alias(Opaque, AliasTy { args: [], def_id: DefId(Opaque::{opaque#0}) }))), bound_vars: [] } } }
-  --> $DIR/rpit_tait_equality_in_canonical_query.rs:31:5
+  --> $DIR/rpit_tait_equality_in_canonical_query.rs:32:5
    |
 LL |     query(get_rpit);
    |     ^^^^^^^^^^^^^^^
    |
 
-  --> $DIR/rpit_tait_equality_in_canonical_query.rs:31:5
+  --> $DIR/rpit_tait_equality_in_canonical_query.rs:32:5
    |
 LL |     query(get_rpit);
    |     ^^^^^^^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs
index 88a8f6e11a5..7524cebf9e6 100644
--- a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs
+++ b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs
@@ -6,6 +6,7 @@
 //! have a situation where the RPIT gets constrained outside its anchor.
 
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@[next] check-pass
 
diff --git a/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr b/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr
index 019e01a07d3..3ae3590ca7f 100644
--- a/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr
+++ b/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr
@@ -1,5 +1,5 @@
 error[E0277]: can't compare `i32` with `Foo`
-  --> $DIR/self-referential-2.rs:9:13
+  --> $DIR/self-referential-2.rs:10:13
    |
 LL | fn bar() -> Bar {
    |             ^^^ no implementation for `i32 == Foo`
diff --git a/tests/ui/type-alias-impl-trait/self-referential-2.rs b/tests/ui/type-alias-impl-trait/self-referential-2.rs
index abba5b3a203..f96364ccfcd 100644
--- a/tests/ui/type-alias-impl-trait/self-referential-2.rs
+++ b/tests/ui/type-alias-impl-trait/self-referential-2.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@[next] check-pass
 #![feature(type_alias_impl_trait)]
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.next.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.next.stderr
index b380dc66f03..036ab66f79d 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.next.stderr
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.next.stderr
@@ -1,11 +1,11 @@
 error[E0284]: type annotations needed: cannot satisfy `Foo == _`
-  --> $DIR/type-alias-impl-trait-tuple.rs:21:24
+  --> $DIR/type-alias-impl-trait-tuple.rs:22:24
    |
 LL |         Blah { my_foo: make_foo(), my_u8: 12 }
    |                        ^^^^^^^^^^ cannot satisfy `Foo == _`
 
 error[E0284]: type annotations needed: cannot satisfy `Foo == _`
-  --> $DIR/type-alias-impl-trait-tuple.rs:25:10
+  --> $DIR/type-alias-impl-trait-tuple.rs:26:10
    |
 LL |         (self.my_foo, self.my_u8, make_foo())
    |          ^^^^^^^^^^^ cannot satisfy `Foo == _`
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs
index 8d0456e587c..fadb92ab440 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@[current] check-pass
 
diff --git a/tests/ui/type-alias-impl-trait/type_of_a_let.current.stderr b/tests/ui/type-alias-impl-trait/type_of_a_let.current.stderr
index 22a3d7bd32f..7cf2fe42da8 100644
--- a/tests/ui/type-alias-impl-trait/type_of_a_let.current.stderr
+++ b/tests/ui/type-alias-impl-trait/type_of_a_let.current.stderr
@@ -1,5 +1,5 @@
 error[E0382]: use of moved value: `x`
-  --> $DIR/type_of_a_let.rs:20:16
+  --> $DIR/type_of_a_let.rs:21:16
    |
 LL |     let x: Foo = 22_u32;
    |         - move occurs because `x` has type `Foo`, which does not implement the `Copy` trait
@@ -9,7 +9,7 @@ LL |     same_type((x, y));
    |                ^ value used here after move
 
 error[E0382]: use of moved value: `y`
-  --> $DIR/type_of_a_let.rs:21:6
+  --> $DIR/type_of_a_let.rs:22:6
    |
 LL |     let y: Foo = x;
    |         - move occurs because `y` has type `Foo`, which does not implement the `Copy` trait
diff --git a/tests/ui/type-alias-impl-trait/type_of_a_let.rs b/tests/ui/type-alias-impl-trait/type_of_a_let.rs
index 48fcac92bec..cc8caf886cf 100644
--- a/tests/ui/type-alias-impl-trait/type_of_a_let.rs
+++ b/tests/ui/type-alias-impl-trait/type_of_a_let.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@[next] check-pass
 
diff --git a/tests/ui/type-alias-impl-trait/variance.stderr b/tests/ui/type-alias-impl-trait/variance.stderr
index 1aaf36223b7..3daacacdb4a 100644
--- a/tests/ui/type-alias-impl-trait/variance.stderr
+++ b/tests/ui/type-alias-impl-trait/variance.stderr
@@ -1,3 +1,69 @@
+error: [*, o]
+  --> $DIR/variance.rs:8:29
+   |
+LL | type NotCapturedEarly<'a> = impl Sized;
+   |                             ^^^^^^^^^^
+
+error: [*, o]
+  --> $DIR/variance.rs:11:26
+   |
+LL | type CapturedEarly<'a> = impl Sized + Captures<'a>;
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: [*, o, o]
+  --> $DIR/variance.rs:14:56
+   |
+LL | type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>;
+   |                                                        ^^^^^^^^^^
+
+error: [*, o, o]
+  --> $DIR/variance.rs:18:49
+   |
+LL | type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>;
+   |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: [*, *, o, o, o]
+  --> $DIR/variance.rs:22:27
+   |
+LL | type Bar<'a, 'b: 'b, T> = impl Sized;
+   |                           ^^^^^^^^^^
+
+error: [*, *, o, o]
+  --> $DIR/variance.rs:34:32
+   |
+LL |     type ImplicitCapture<'a> = impl Sized;
+   |                                ^^^^^^^^^^
+
+error: [*, *, o, o]
+  --> $DIR/variance.rs:37:42
+   |
+LL |     type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>;
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: [*, *, o, o]
+  --> $DIR/variance.rs:40:39
+   |
+LL |     type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>;
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: [*, *, o, o]
+  --> $DIR/variance.rs:45:32
+   |
+LL |     type ImplicitCapture<'a> = impl Sized;
+   |                                ^^^^^^^^^^
+
+error: [*, *, o, o]
+  --> $DIR/variance.rs:48:42
+   |
+LL |     type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>;
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: [*, *, o, o]
+  --> $DIR/variance.rs:51:39
+   |
+LL |     type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>;
+   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from `dyn` type
   --> $DIR/variance.rs:14:56
    |
@@ -110,72 +176,6 @@ LL |     type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>;
    |
    = note: `ExplicitCaptureFromGat` must be used in combination with a concrete type within the same impl
 
-error: [*, o]
-  --> $DIR/variance.rs:8:29
-   |
-LL | type NotCapturedEarly<'a> = impl Sized;
-   |                             ^^^^^^^^^^
-
-error: [*, o]
-  --> $DIR/variance.rs:11:26
-   |
-LL | type CapturedEarly<'a> = impl Sized + Captures<'a>;
-   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: [*, o, o]
-  --> $DIR/variance.rs:14:56
-   |
-LL | type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>;
-   |                                                        ^^^^^^^^^^
-
-error: [*, o, o]
-  --> $DIR/variance.rs:18:49
-   |
-LL | type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>;
-   |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: [*, *, o, o, o]
-  --> $DIR/variance.rs:22:27
-   |
-LL | type Bar<'a, 'b: 'b, T> = impl Sized;
-   |                           ^^^^^^^^^^
-
-error: [*, *, o, o]
-  --> $DIR/variance.rs:34:32
-   |
-LL |     type ImplicitCapture<'a> = impl Sized;
-   |                                ^^^^^^^^^^
-
-error: [*, *, o, o]
-  --> $DIR/variance.rs:37:42
-   |
-LL |     type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>;
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: [*, *, o, o]
-  --> $DIR/variance.rs:40:39
-   |
-LL |     type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>;
-   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: [*, *, o, o]
-  --> $DIR/variance.rs:45:32
-   |
-LL |     type ImplicitCapture<'a> = impl Sized;
-   |                                ^^^^^^^^^^
-
-error: [*, *, o, o]
-  --> $DIR/variance.rs:48:42
-   |
-LL |     type ExplicitCaptureFromHeader<'a> = impl Sized + Captures<'i>;
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: [*, *, o, o]
-  --> $DIR/variance.rs:51:39
-   |
-LL |     type ExplicitCaptureFromGat<'a> = impl Sized + Captures<'a>;
-   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error: aborting due to 24 previous errors
 
 For more information about this error, try `rustc --explain E0657`.
diff --git a/tests/ui/typeck/issue-103899.rs b/tests/ui/typeck/issue-103899.rs
index 5876a34ef55..38882e9dc54 100644
--- a/tests/ui/typeck/issue-103899.rs
+++ b/tests/ui/typeck/issue-103899.rs
@@ -1,7 +1,11 @@
-//@ check-fail
-//@ failure-status: 101
-//@ dont-check-compiler-stderr
-//@ known-bug: #103899
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@[next] check-pass
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[current] check-fail
+//@[current] failure-status: 101
+//@[current] dont-check-compiler-stderr
+//@[current] known-bug: #103899
 
 trait BaseWithAssoc {
     type Assoc;
diff --git a/tests/ui/unsized/issue-71659.current.stderr b/tests/ui/unsized/issue-71659.current.stderr
index df0b998fd88..f7de668ba3a 100644
--- a/tests/ui/unsized/issue-71659.current.stderr
+++ b/tests/ui/unsized/issue-71659.current.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `dyn Foo: CastTo<[i32]>` is not satisfied
-  --> $DIR/issue-71659.rs:33:15
+  --> $DIR/issue-71659.rs:34:15
    |
 LL |     let x = x.cast::<[i32]>();
    |               ^^^^ the trait `CastTo<[i32]>` is not implemented for `dyn Foo`
    |
 note: required by a bound in `Cast::cast`
-  --> $DIR/issue-71659.rs:22:15
+  --> $DIR/issue-71659.rs:23:15
    |
 LL |     fn cast<T: ?Sized>(&self) -> &T
    |        ---- required by a bound in this associated function
diff --git a/tests/ui/unsized/issue-71659.next.stderr b/tests/ui/unsized/issue-71659.next.stderr
index df0b998fd88..f7de668ba3a 100644
--- a/tests/ui/unsized/issue-71659.next.stderr
+++ b/tests/ui/unsized/issue-71659.next.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `dyn Foo: CastTo<[i32]>` is not satisfied
-  --> $DIR/issue-71659.rs:33:15
+  --> $DIR/issue-71659.rs:34:15
    |
 LL |     let x = x.cast::<[i32]>();
    |               ^^^^ the trait `CastTo<[i32]>` is not implemented for `dyn Foo`
    |
 note: required by a bound in `Cast::cast`
-  --> $DIR/issue-71659.rs:22:15
+  --> $DIR/issue-71659.rs:23:15
    |
 LL |     fn cast<T: ?Sized>(&self) -> &T
    |        ---- required by a bound in this associated function
diff --git a/tests/ui/unsized/issue-71659.rs b/tests/ui/unsized/issue-71659.rs
index fd0b799d889..c463ed125bb 100644
--- a/tests/ui/unsized/issue-71659.rs
+++ b/tests/ui/unsized/issue-71659.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
 #![feature(unsize)]
diff --git a/tests/ui/unsized/issue-75899.rs b/tests/ui/unsized/issue-75899.rs
index 9cfcf0aa13e..2cc3c0dd51d 100644
--- a/tests/ui/unsized/issue-75899.rs
+++ b/tests/ui/unsized/issue-75899.rs
@@ -1,4 +1,5 @@
 //@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 //@ check-pass
 
diff --git a/tests/ui/variance/variance-associated-consts.stderr b/tests/ui/variance/variance-associated-consts.stderr
index f41574ca3a3..b910f668db5 100644
--- a/tests/ui/variance/variance-associated-consts.stderr
+++ b/tests/ui/variance/variance-associated-consts.stderr
@@ -1,3 +1,9 @@
+error: [o]
+  --> $DIR/variance-associated-consts.rs:13:1
+   |
+LL | struct Foo<T: Trait> {
+   | ^^^^^^^^^^^^^^^^^^^^
+
 error: unconstrained generic constant
   --> $DIR/variance-associated-consts.rs:14:12
    |
@@ -6,11 +12,5 @@ LL |     field: [u8; <T as Trait>::Const]
    |
    = help: try adding a `where` bound using this expression: `where [(); <T as Trait>::Const]:`
 
-error: [o]
-  --> $DIR/variance-associated-consts.rs:13:1
-   |
-LL | struct Foo<T: Trait> {
-   | ^^^^^^^^^^^^^^^^^^^^
-
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/variance/variance-regions-direct.stderr b/tests/ui/variance/variance-regions-direct.stderr
index edfc888f656..5ac538982aa 100644
--- a/tests/ui/variance/variance-regions-direct.stderr
+++ b/tests/ui/variance/variance-regions-direct.stderr
@@ -1,11 +1,3 @@
-error[E0392]: lifetime parameter `'a` is never used
-  --> $DIR/variance-regions-direct.rs:52:14
-   |
-LL | struct Test7<'a> {
-   |              ^^ unused lifetime parameter
-   |
-   = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData`
-
 error: [+, +, +]
   --> $DIR/variance-regions-direct.rs:9:1
    |
@@ -48,6 +40,14 @@ error: [-, +, o]
 LL | enum Test8<'a, 'b, 'c:'b> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error[E0392]: lifetime parameter `'a` is never used
+  --> $DIR/variance-regions-direct.rs:52:14
+   |
+LL | struct Test7<'a> {
+   |              ^^ unused lifetime parameter
+   |
+   = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData`
+
 error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0392`.
diff --git a/tests/ui/variance/variance-regions-indirect.stderr b/tests/ui/variance/variance-regions-indirect.stderr
index 901ec0c6a76..b6b943026eb 100644
--- a/tests/ui/variance/variance-regions-indirect.stderr
+++ b/tests/ui/variance/variance-regions-indirect.stderr
@@ -1,3 +1,33 @@
+error: [-, +, o, *]
+  --> $DIR/variance-regions-indirect.rs:8:1
+   |
+LL | enum Base<'a, 'b, 'c:'b, 'd> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: [*, o, +, -]
+  --> $DIR/variance-regions-indirect.rs:16:1
+   |
+LL | struct Derived1<'w, 'x:'y, 'y, 'z> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: [o, o, *]
+  --> $DIR/variance-regions-indirect.rs:22:1
+   |
+LL | struct Derived2<'a, 'b:'a, 'c> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: [o, +, *]
+  --> $DIR/variance-regions-indirect.rs:28:1
+   |
+LL | struct Derived3<'a:'b, 'b, 'c> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: [-, +, o]
+  --> $DIR/variance-regions-indirect.rs:34:1
+   |
+LL | struct Derived4<'a, 'b, 'c:'b> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0392]: lifetime parameter `'d` is never used
   --> $DIR/variance-regions-indirect.rs:8:26
    |
@@ -30,36 +60,6 @@ LL | struct Derived3<'a:'b, 'b, 'c> {
    |
    = help: consider removing `'c`, referring to it in a field, or using a marker such as `PhantomData`
 
-error: [-, +, o, *]
-  --> $DIR/variance-regions-indirect.rs:8:1
-   |
-LL | enum Base<'a, 'b, 'c:'b, 'd> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: [*, o, +, -]
-  --> $DIR/variance-regions-indirect.rs:16:1
-   |
-LL | struct Derived1<'w, 'x:'y, 'y, 'z> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: [o, o, *]
-  --> $DIR/variance-regions-indirect.rs:22:1
-   |
-LL | struct Derived2<'a, 'b:'a, 'c> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: [o, +, *]
-  --> $DIR/variance-regions-indirect.rs:28:1
-   |
-LL | struct Derived3<'a:'b, 'b, 'c> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: [-, +, o]
-  --> $DIR/variance-regions-indirect.rs:34:1
-   |
-LL | struct Derived4<'a, 'b, 'c:'b> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error: aborting due to 9 previous errors
 
 For more information about this error, try `rustc --explain E0392`.
diff --git a/tests/ui/variance/variance-trait-bounds.stderr b/tests/ui/variance/variance-trait-bounds.stderr
index 95ed18c1ad2..9d106fb11f6 100644
--- a/tests/ui/variance/variance-trait-bounds.stderr
+++ b/tests/ui/variance/variance-trait-bounds.stderr
@@ -1,3 +1,27 @@
+error: [+, +]
+  --> $DIR/variance-trait-bounds.rs:16:1
+   |
+LL | struct TestStruct<U,T:Setter<U>> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: [*, +]
+  --> $DIR/variance-trait-bounds.rs:21:1
+   |
+LL | enum TestEnum<U,T:Setter<U>> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: [*, +]
+  --> $DIR/variance-trait-bounds.rs:27:1
+   |
+LL | struct TestContraStruct<U,T:Setter<U>> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: [*, +]
+  --> $DIR/variance-trait-bounds.rs:33:1
+   |
+LL | struct TestBox<U,T:Getter<U>+Setter<U>> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
 error[E0392]: type parameter `U` is never used
   --> $DIR/variance-trait-bounds.rs:21:15
    |
@@ -25,30 +49,6 @@ LL | struct TestBox<U,T:Getter<U>+Setter<U>> {
    = help: consider removing `U`, referring to it in a field, or using a marker such as `PhantomData`
    = help: if you intended `U` to be a const parameter, use `const U: /* Type */` instead
 
-error: [+, +]
-  --> $DIR/variance-trait-bounds.rs:16:1
-   |
-LL | struct TestStruct<U,T:Setter<U>> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: [*, +]
-  --> $DIR/variance-trait-bounds.rs:21:1
-   |
-LL | enum TestEnum<U,T:Setter<U>> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: [*, +]
-  --> $DIR/variance-trait-bounds.rs:27:1
-   |
-LL | struct TestContraStruct<U,T:Setter<U>> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: [*, +]
-  --> $DIR/variance-trait-bounds.rs:33:1
-   |
-LL | struct TestBox<U,T:Getter<U>+Setter<U>> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error: aborting due to 7 previous errors
 
 For more information about this error, try `rustc --explain E0392`.
diff --git a/tests/ui/wait-forked-but-failed-child.rs b/tests/ui/wait-forked-but-failed-child.rs
index a5a6cca0637..3d052cc193c 100644
--- a/tests/ui/wait-forked-but-failed-child.rs
+++ b/tests/ui/wait-forked-but-failed-child.rs
@@ -1,5 +1,5 @@
 //@ run-pass
-//@ ignore-emscripten no processes
+//@ ignore-wasm32 no processes
 //@ ignore-sgx no processes
 //@ ignore-vxworks no 'ps'
 //@ ignore-fuchsia no 'ps'
diff --git a/tests/ui/wf/wf-normalization-sized.next.stderr b/tests/ui/wf/wf-normalization-sized.next.stderr
new file mode 100644
index 00000000000..599b1f3d45e
--- /dev/null
+++ b/tests/ui/wf/wf-normalization-sized.next.stderr
@@ -0,0 +1,30 @@
+error: the type `<[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize` is not well-formed
+  --> $DIR/wf-normalization-sized.rs:19:10
+   |
+LL | const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = ();
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the type `<[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize` is not well-formed
+  --> $DIR/wf-normalization-sized.rs:19:10
+   |
+LL | const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = ();
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: the type `<Vec<str> as WellUnformed>::RequestNormalize` is not well-formed
+  --> $DIR/wf-normalization-sized.rs:22:10
+   |
+LL | const _: <Vec<str> as WellUnformed>::RequestNormalize = ();
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: the type `<Vec<str> as WellUnformed>::RequestNormalize` is not well-formed
+  --> $DIR/wf-normalization-sized.rs:22:10
+   |
+LL | const _: <Vec<str> as WellUnformed>::RequestNormalize = ();
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/wf/wf-normalization-sized.rs b/tests/ui/wf/wf-normalization-sized.rs
index e14be6b62bb..e6e24ff9e85 100644
--- a/tests/ui/wf/wf-normalization-sized.rs
+++ b/tests/ui/wf/wf-normalization-sized.rs
@@ -1,5 +1,8 @@
-//@ check-pass
-//@ known-bug: #100041
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[current] check-pass
+//@[current] known-bug: #100041
 
 // Should fail. Normalization can bypass well-formedness checking.
 // `[[[[[[u8]]]]]]` is not a well-formed type since size of type `[u8]` cannot
@@ -14,6 +17,10 @@ impl<T: ?Sized> WellUnformed for T {
 }
 
 const _: <[[[[[[u8]]]]]] as WellUnformed>::RequestNormalize = ();
+//[next]~^ the type
+//[next]~| the type
 const _: <Vec<str> as WellUnformed>::RequestNormalize = ();
+//[next]~^ the type
+//[next]~| the type
 
 fn main() {}
diff --git a/triagebot.toml b/triagebot.toml
index 802079f496e..98f31743d4a 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -665,6 +665,7 @@ compiler-team-contributors = [
     "@Nadrieril",
     "@nnethercote",
     "@fmease",
+    "@fee1-dead",
 ]
 compiler = [
     "compiler-team",