about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock2
-rw-r--r--compiler/rustc_abi/src/layout.rs13
-rw-r--r--compiler/rustc_abi/src/lib.rs32
-rw-r--r--compiler/rustc_ast/src/ast.rs11
-rw-r--r--compiler/rustc_ast_lowering/src/asm.rs7
-rw-r--r--compiler/rustc_ast_lowering/src/delegation.rs3
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs9
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs29
-rw-r--r--compiler/rustc_ast_lowering/src/pat.rs5
-rw-r--r--compiler/rustc_ast_lowering/src/path.rs80
-rw-r--r--compiler/rustc_borrowck/messages.ftl2
-rw-r--r--compiler/rustc_borrowck/src/session_diagnostics.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/mod.rs3
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs11
-rw-r--r--compiler/rustc_codegen_cranelift/src/common.rs8
-rw-r--r--compiler/rustc_codegen_cranelift/src/debuginfo/types.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs5
-rw-r--r--compiler/rustc_codegen_cranelift/src/unsize.rs8
-rw-r--r--compiler/rustc_codegen_gcc/src/abi.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/asm.rs6
-rw-r--r--compiler/rustc_codegen_gcc/src/base.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs15
-rw-r--r--compiler/rustc_codegen_gcc/src/common.rs38
-rw-r--r--compiler/rustc_codegen_gcc/src/consts.rs6
-rw-r--r--compiler/rustc_codegen_gcc/src/context.rs11
-rw-r--r--compiler/rustc_codegen_gcc/src/debuginfo.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/declare.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/int.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/mod.rs8
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/simd.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/mono_item.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/type_.rs8
-rw-r--r--compiler/rustc_codegen_gcc/src/type_of.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/abi.rs17
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs545
-rw-r--r--compiler/rustc_codegen_llvm/src/attributes.rs11
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs12
-rw-r--r--compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs12
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs33
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs145
-rw-r--r--compiler/rustc_codegen_llvm/src/callee.rs83
-rw-r--r--compiler/rustc_codegen_llvm/src/common.rs40
-rw-r--r--compiler/rustc_codegen_llvm/src/consts.rs77
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs23
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs17
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs28
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs3
-rw-r--r--compiler/rustc_codegen_llvm/src/declare.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs12
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs168
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs40
-rw-r--r--compiler/rustc_codegen_llvm/src/mono_item.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/type_.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/va_arg.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs18
-rw-r--r--compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs6
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/analyze.rs25
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/mod.rs26
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs18
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/place.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs7
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/asm.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/backend.rs21
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/builder.rs40
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/consts.rs14
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/debuginfo.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/declare.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/intrinsic.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/misc.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/mod.rs86
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/statics.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/type_.rs39
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs9
-rw-r--r--compiler/rustc_const_eval/src/errors.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/call.rs1
-rw-r--r--compiler/rustc_driver_impl/src/signal_handler.rs2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0775.md7
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0776.md4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0796.md6
-rw-r--r--compiler/rustc_error_codes/src/lib.rs2
-rw-r--r--compiler/rustc_errors/src/lib.rs2
-rw-r--r--compiler/rustc_expand/src/expand.rs12
-rw-r--r--compiler/rustc_expand/src/module.rs2
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs10
-rw-r--r--compiler/rustc_feature/src/unstable.rs6
-rw-r--r--compiler/rustc_hir/src/hir.rs3
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl25
-rw-r--r--compiler/rustc_hir_analysis/src/bounds.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/check/region.rs6
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs5
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs32
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs67
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs181
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs65
-rw-r--r--compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs13
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs336
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs128
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs62
-rw-r--r--compiler/rustc_hir_typeck/src/expr_use_visitor.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/intrinsicck.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs13
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs37
-rw-r--r--compiler/rustc_lint/messages.ftl9
-rw-r--r--compiler/rustc_lint/src/context/diagnostics/check_cfg.rs14
-rw-r--r--compiler/rustc_lint/src/lib.rs3
-rw-r--r--compiler/rustc_lint/src/lints.rs35
-rw-r--r--compiler/rustc_lint/src/nonstandard_style.rs3
-rw-r--r--compiler/rustc_lint/src/static_mut_refs.rs154
-rw-r--r--compiler/rustc_lint/src/types.rs439
-rw-r--r--compiler/rustc_lint/src/types/literal.rs386
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs52
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs2
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp4
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp13
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp66
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp27
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp2
-rw-r--r--compiler/rustc_middle/messages.ftl2
-rw-r--r--compiler/rustc_middle/src/lib.rs1
-rw-r--r--compiler/rustc_middle/src/middle/codegen_fn_attrs.rs4
-rw-r--r--compiler/rustc_middle/src/mir/basic_blocks.rs2
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs13
-rw-r--r--compiler/rustc_middle/src/mir/terminator.rs11
-rw-r--r--compiler/rustc_middle/src/mir/traversal.rs85
-rw-r--r--compiler/rustc_middle/src/ty/adjustment.rs3
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs4
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs7
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs23
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/expr.rs64
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs11
-rw-r--r--compiler/rustc_parse/messages.ftl20
-rw-r--r--compiler/rustc_parse/src/errors.rs89
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs4
-rw-r--r--compiler/rustc_parse/src/parser/item.rs6
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs21
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs354
-rw-r--r--compiler/rustc_parse/src/parser/path.rs25
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs10
-rw-r--r--compiler/rustc_passes/src/check_attr.rs33
-rw-r--r--compiler/rustc_passes/src/layout_test.rs4
-rw-r--r--compiler/rustc_resolve/src/def_collector.rs104
-rw-r--r--compiler/rustc_resolve/src/late.rs40
-rw-r--r--compiler/rustc_resolve/src/lib.rs5
-rw-r--r--compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs4
-rw-r--r--compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs5
-rw-r--r--compiler/rustc_smir/src/rustc_internal/internal.rs1
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/abi.rs1
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/ty.rs1
-rw-r--r--compiler/rustc_span/src/symbol.rs57
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs46
-rw-r--r--compiler/rustc_target/src/abi/call/m68k.rs2
-rw-r--r--compiler/rustc_target/src/abi/call/mod.rs9
-rw-r--r--compiler/rustc_target/src/abi/call/wasm.rs2
-rw-r--r--compiler/rustc_target/src/abi/call/x86.rs2
-rw-r--r--compiler/rustc_target/src/abi/call/x86_64.rs2
-rw-r--r--compiler/rustc_target/src/abi/call/xtensa.rs2
-rw-r--r--compiler/rustc_target/src/json.rs1
-rw-r--r--compiler/rustc_target/src/spec/abi/mod.rs23
-rw-r--r--compiler/rustc_target/src/spec/mod.rs7
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs24
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i386_apple_ios.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs3
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs1
-rw-r--r--compiler/stable_mir/src/abi.rs1
-rw-r--r--compiler/stable_mir/src/ty.rs1
-rw-r--r--config.example.toml2
-rw-r--r--library/alloc/src/alloc.rs8
-rw-r--r--library/alloc/src/collections/binary_heap/mod.rs1
-rw-r--r--library/alloc/src/collections/btree/map.rs2
-rw-r--r--library/alloc/src/collections/btree/set.rs1
-rw-r--r--library/alloc/src/collections/linked_list/tests.rs3
-rw-r--r--library/alloc/src/collections/vec_deque/mod.rs1
-rw-r--r--library/alloc/src/collections/vec_deque/tests.rs3
-rw-r--r--library/alloc/src/ffi/c_str.rs1
-rw-r--r--library/alloc/src/lib.rs1
-rw-r--r--library/alloc/src/slice.rs1
-rw-r--r--library/alloc/src/string.rs32
-rw-r--r--library/alloc/src/vec/mod.rs78
-rw-r--r--library/alloc/tests/fmt.rs2
-rw-r--r--library/alloc/tests/lib.rs1
-rw-r--r--library/alloc/tests/string.rs37
-rw-r--r--library/alloc/tests/vec.rs5
-rw-r--r--library/alloc/tests/vec_deque.rs3
-rw-r--r--library/core/src/bool.rs1
-rw-r--r--library/core/src/cell/lazy.rs124
-rw-r--r--library/core/src/char/methods.rs42
-rw-r--r--library/core/src/iter/traits/iterator.rs3
-rw-r--r--library/core/src/lib.rs3
-rw-r--r--library/core/src/mem/maybe_uninit.rs7
-rw-r--r--library/core/src/num/f32.rs1
-rw-r--r--library/core/src/num/f64.rs1
-rw-r--r--library/core/src/num/mod.rs69
-rw-r--r--library/core/src/num/nonzero.rs10
-rw-r--r--library/core/src/option.rs2
-rw-r--r--library/core/src/panic/panic_info.rs12
-rw-r--r--library/core/src/panicking.rs4
-rw-r--r--library/core/src/primitive_docs.rs2
-rw-r--r--library/core/src/result.rs1
-rw-r--r--library/core/src/slice/mod.rs1
-rw-r--r--library/core/src/str/mod.rs4
-rw-r--r--library/core/src/task/wake.rs1
-rw-r--r--library/core/tests/atomic.rs2
-rw-r--r--library/core/tests/lazy.rs21
-rw-r--r--library/core/tests/lib.rs2
-rw-r--r--library/core/tests/num/int_macros.rs2
-rw-r--r--library/panic_unwind/src/seh.rs2
-rw-r--r--library/proc_macro/src/bridge/buffer.rs4
-rw-r--r--library/std/src/collections/hash/map.rs8
-rw-r--r--library/std/src/collections/hash/set.rs3
-rw-r--r--library/std/src/ffi/os_str.rs2
-rw-r--r--library/std/src/fs.rs27
-rw-r--r--library/std/src/io/mod.rs1
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/os/unix/fs.rs1
-rw-r--r--library/std/src/path.rs3
-rw-r--r--library/std/src/sync/lazy_lock.rs117
-rw-r--r--library/std/src/sync/lazy_lock/tests.rs21
-rw-r--r--library/std/src/sync/mod.rs3
-rw-r--r--library/std/src/sync/once.rs10
-rw-r--r--library/std/src/sys/alloc/wasm.rs3
-rw-r--r--library/std/src/sys/pal/unsupported/process.rs11
-rw-r--r--library/std/src/sys/pal/windows/fs/remove_dir_all.rs15
-rw-r--r--library/std/src/sys/sync/once/futex.rs9
-rw-r--r--library/std/src/sys/sync/once/no_threads.rs9
-rw-r--r--library/std/src/sys/sync/once/queue.rs9
-rw-r--r--library/std/src/thread/local/tests.rs3
-rw-r--r--library/std/src/thread/mod.rs48
-rw-r--r--library/std/src/time.rs1
-rw-r--r--src/bootstrap/Cargo.lock13
-rw-r--r--src/bootstrap/Cargo.toml2
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs4
-rw-r--r--src/bootstrap/src/core/build_steps/doc.rs7
-rw-r--r--src/bootstrap/src/core/build_steps/llvm.rs4
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs5
-rw-r--r--src/bootstrap/src/core/builder.rs7
-rw-r--r--src/bootstrap/src/core/config/config.rs11
-rw-r--r--src/bootstrap/src/core/config/tests.rs2
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs5
-rw-r--r--src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile1
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile62
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-18/Dockerfile1
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile1
-rw-r--r--src/ci/github-actions/jobs.yml7
-rw-r--r--src/doc/rustc/src/SUMMARY.md1
-rw-r--r--src/doc/rustc/src/platform-support.md3
-rw-r--r--src/doc/rustc/src/platform-support/arm64e-apple-tvos.md37
-rw-r--r--src/doc/unstable-book/src/language-features/cmse-nonsecure-entry.md8
-rw-r--r--src/librustdoc/doctest/rust.rs13
-rw-r--r--src/librustdoc/html/markdown.rs4
-rw-r--r--src/librustdoc/html/markdown/tests.rs6
-rw-r--r--src/librustdoc/html/render/mod.rs1
-rw-r--r--src/librustdoc/html/sources.rs1
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css11
-rw-r--r--src/librustdoc/html/static/js/main.js30
-rw-r--r--src/librustdoc/html/static/js/scrape-examples.js51
-rw-r--r--src/librustdoc/html/templates/scraped_source.html15
-rw-r--r--src/tools/build-manifest/src/main.rs5
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/entry.rs12
-rw-r--r--src/tools/clippy/clippy_lints/src/format_push_string.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/instant_subtraction.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/iter_over_hash_type.rs38
-rw-r--r--src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs14
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_retain.rs34
-rw-r--r--src/tools/clippy/clippy_lints/src/manual_strip.rs10
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs5
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/open_options.rs23
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs24
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/single_char_add_str.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/waker_clone_wake.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/operators/float_equality_without_abs.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/redundant_clone.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/repeat_vec_with_capacity.rs6
-rw-r--r--src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs8
-rw-r--r--src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs3
-rw-r--r--src/tools/clippy/clippy_utils/src/higher.rs8
-rw-r--r--src/tools/clippy/clippy_utils/src/lib.rs28
-rw-r--r--src/tools/clippy/clippy_utils/src/mir/mod.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/paths.rs88
-rw-r--r--src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr13
-rw-r--r--src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs1
-rw-r--r--src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.stderr58
-rw-r--r--src/tools/clippy/tests/ui/must_use_candidates.fixed7
-rw-r--r--src/tools/clippy/tests/ui/must_use_candidates.rs7
-rw-r--r--src/tools/clippy/tests/ui/must_use_candidates.stderr10
-rw-r--r--src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed2
-rw-r--r--src/tools/clippy/tests/ui/redundant_static_lifetimes.rs2
-rw-r--r--src/tools/clippy/tests/ui/redundant_static_lifetimes.stderr36
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.fixed2
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.rs2
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.stderr74
-rw-r--r--src/tools/compiletest/src/common.rs3
-rw-r--r--src/tools/compiletest/src/header.rs12
-rw-r--r--src/tools/compiletest/src/lib.rs3
-rw-r--r--src/tools/compiletest/src/runtest.rs2141
-rw-r--r--src/tools/compiletest/src/runtest/assembly.rs19
-rw-r--r--src/tools/compiletest/src/runtest/codegen.rs22
-rw-r--r--src/tools/compiletest/src/runtest/codegen_units.rs191
-rw-r--r--src/tools/compiletest/src/runtest/coverage.rs4
-rw-r--r--src/tools/compiletest/src/runtest/crash.rs25
-rw-r--r--src/tools/compiletest/src/runtest/debuginfo.rs509
-rw-r--r--src/tools/compiletest/src/runtest/incremental.rs128
-rw-r--r--src/tools/compiletest/src/runtest/js_doc.rs32
-rw-r--r--src/tools/compiletest/src/runtest/mir_opt.rs155
-rw-r--r--src/tools/compiletest/src/runtest/pretty.rs104
-rw-r--r--src/tools/compiletest/src/runtest/run_make.rs526
-rw-r--r--src/tools/compiletest/src/runtest/rustdoc.rs34
-rw-r--r--src/tools/compiletest/src/runtest/rustdoc_json.rs48
-rw-r--r--src/tools/compiletest/src/runtest/ui.rs233
-rw-r--r--src/tools/compiletest/src/runtest/valgrind.rs34
-rw-r--r--src/tools/miri/tests/fail/type-too-large.stderr4
-rw-r--r--src/tools/miri/tests/fail/uninit/padding-enum.rs5
-rw-r--r--src/tools/miri/tests/fail/uninit/padding-enum.stderr4
-rw-r--r--src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs3
-rw-r--r--src/tools/miri/tests/pass-dep/concurrency/tls_pthread_drop_order.rs3
-rw-r--r--src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs3
-rw-r--r--src/tools/miri/tests/pass-dep/libc/libc-pipe.rs2
-rw-r--r--src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs4
-rw-r--r--src/tools/miri/tests/pass/atomic.rs4
-rw-r--r--src/tools/miri/tests/pass/drop_on_array_elements.rs2
-rw-r--r--src/tools/miri/tests/pass/drop_on_fat_ptr_array_elements.rs2
-rw-r--r--src/tools/miri/tests/pass/drop_on_zst_array_elements.rs2
-rw-r--r--src/tools/miri/tests/pass/drop_through_owned_slice.rs2
-rw-r--r--src/tools/miri/tests/pass/static_memory_modification.rs3
-rw-r--r--src/tools/miri/tests/pass/static_mut.rs3
-rw-r--r--src/tools/miri/tests/pass/tls/tls_static.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lib.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs1
-rw-r--r--src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs1
-rw-r--r--src/tools/rustfmt/.github/workflows/check_diff.yml2
-rw-r--r--src/tools/rustfmt/.github/workflows/integration.yml2
-rw-r--r--src/tools/rustfmt/.github/workflows/linux.yml2
-rw-r--r--src/tools/rustfmt/.github/workflows/mac.yml3
-rw-r--r--src/tools/rustfmt/.github/workflows/rustdoc_check.yml2
-rw-r--r--src/tools/rustfmt/.github/workflows/upload-assets.yml2
-rw-r--r--src/tools/rustfmt/.github/workflows/windows.yml2
-rw-r--r--src/tools/rustfmt/CHANGELOG.md64
-rw-r--r--src/tools/rustfmt/Cargo.lock14
-rw-r--r--src/tools/rustfmt/Cargo.toml4
-rw-r--r--src/tools/rustfmt/Configurations.md17
-rw-r--r--src/tools/rustfmt/Contributing.md21
-rw-r--r--src/tools/rustfmt/build.rs19
-rw-r--r--src/tools/rustfmt/check_diff/Cargo.lock290
-rw-r--r--src/tools/rustfmt/check_diff/Cargo.toml4
-rw-r--r--src/tools/rustfmt/check_diff/src/lib.rs58
-rw-r--r--src/tools/rustfmt/check_diff/src/main.rs8
-rw-r--r--src/tools/rustfmt/check_diff/tests/bash_commands.rs12
-rw-r--r--src/tools/rustfmt/check_diff/tests/git.rs16
-rwxr-xr-xsrc/tools/rustfmt/ci/build_and_test.bat8
-rwxr-xr-xsrc/tools/rustfmt/ci/build_and_test.sh8
-rw-r--r--src/tools/rustfmt/config_proc_macro/Cargo.toml4
-rw-r--r--src/tools/rustfmt/config_proc_macro/src/utils.rs2
-rw-r--r--src/tools/rustfmt/rust-toolchain2
-rw-r--r--src/tools/rustfmt/rustfmt.toml3
-rw-r--r--src/tools/rustfmt/src/attr.rs76
-rw-r--r--src/tools/rustfmt/src/bin/main.rs334
-rw-r--r--src/tools/rustfmt/src/chains.rs191
-rw-r--r--src/tools/rustfmt/src/closures.rs93
-rw-r--r--src/tools/rustfmt/src/comment.rs60
-rw-r--r--src/tools/rustfmt/src/config/config_type.rs149
-rw-r--r--src/tools/rustfmt/src/config/file_lines.rs6
-rw-r--r--src/tools/rustfmt/src/config/mod.rs580
-rw-r--r--src/tools/rustfmt/src/config/options.rs201
-rw-r--r--src/tools/rustfmt/src/config/style_edition.rs2
-rw-r--r--src/tools/rustfmt/src/emitter/checkstyle.rs2
-rw-r--r--src/tools/rustfmt/src/emitter/json.rs2
-rw-r--r--src/tools/rustfmt/src/emitter/modified_lines.rs2
-rw-r--r--src/tools/rustfmt/src/expr.rs476
-rw-r--r--src/tools/rustfmt/src/formatting.rs2
-rw-r--r--src/tools/rustfmt/src/git-rustfmt/main.rs13
-rw-r--r--src/tools/rustfmt/src/ignore_path.rs9
-rw-r--r--src/tools/rustfmt/src/imports.rs218
-rw-r--r--src/tools/rustfmt/src/items.rs433
-rw-r--r--src/tools/rustfmt/src/lib.rs8
-rw-r--r--src/tools/rustfmt/src/lists.rs31
-rw-r--r--src/tools/rustfmt/src/macros.rs265
-rw-r--r--src/tools/rustfmt/src/matches.rs143
-rw-r--r--src/tools/rustfmt/src/missed_spans.rs14
-rw-r--r--src/tools/rustfmt/src/modules.rs2
-rw-r--r--src/tools/rustfmt/src/overflow.rs58
-rw-r--r--src/tools/rustfmt/src/pairs.rs99
-rw-r--r--src/tools/rustfmt/src/parse/macros/asm.rs2
-rw-r--r--src/tools/rustfmt/src/parse/macros/cfg_if.rs2
-rw-r--r--src/tools/rustfmt/src/parse/macros/mod.rs4
-rw-r--r--src/tools/rustfmt/src/parse/parser.rs6
-rw-r--r--src/tools/rustfmt/src/parse/session.rs9
-rw-r--r--src/tools/rustfmt/src/patterns.rs143
-rw-r--r--src/tools/rustfmt/src/reorder.rs27
-rw-r--r--src/tools/rustfmt/src/rewrite.rs68
-rw-r--r--src/tools/rustfmt/src/rustfmt_diff.rs2
-rw-r--r--src/tools/rustfmt/src/sort.rs368
-rw-r--r--src/tools/rustfmt/src/source_file.rs2
-rw-r--r--src/tools/rustfmt/src/spanned.rs9
-rw-r--r--src/tools/rustfmt/src/stmt.rs41
-rw-r--r--src/tools/rustfmt/src/string.rs4
-rw-r--r--src/tools/rustfmt/src/test/configuration_snippet.rs4
-rw-r--r--src/tools/rustfmt/src/test/mod.rs76
-rw-r--r--src/tools/rustfmt/src/types.rs371
-rw-r--r--src/tools/rustfmt/src/utils.rs16
-rw-r--r--src/tools/rustfmt/src/vertical.rs47
-rw-r--r--src/tools/rustfmt/src/visitor.rs48
-rw-r--r--src/tools/rustfmt/tests/config/issue-5801-v2.toml2
-rw-r--r--src/tools/rustfmt/tests/config/issue-6302.toml1
-rw-r--r--src/tools/rustfmt/tests/config/style-edition/just-style-edition/rustfmt.toml1
-rw-r--r--src/tools/rustfmt/tests/config/style-edition/just-version/rustfmt.toml1
-rw-r--r--src/tools/rustfmt/tests/config/style-edition/overrides/rustfmt.toml2
-rw-r--r--src/tools/rustfmt/tests/config/style-edition/style-edition-and-edition/rustfmt.toml2
-rw-r--r--src/tools/rustfmt/tests/config/style-edition/version-edition/rustfmt.toml2
-rw-r--r--src/tools/rustfmt/tests/config/style-edition/version-style-edition-and-edition/rustfmt.toml3
-rw-r--r--src/tools/rustfmt/tests/config/style-edition/version-style-edition/rustfmt.toml2
-rw-r--r--src/tools/rustfmt/tests/rustfmt/main.rs27
-rw-r--r--src/tools/rustfmt/tests/source/arrow_in_comments/arrow_in_single_comment.rs2
-rw-r--r--src/tools/rustfmt/tests/source/arrow_in_comments/multiple_arrows.rs2
-rw-r--r--src/tools/rustfmt/tests/source/configs/indent_style/block_trailing_comma_call/one.rs2
-rw-r--r--src/tools/rustfmt/tests/source/configs/indent_style/block_trailing_comma_call/two.rs2
-rw-r--r--src/tools/rustfmt/tests/source/configs/style_edition/overflow_delim_expr_2015.rs155
-rw-r--r--src/tools/rustfmt/tests/source/configs/style_edition/overflow_delim_expr_2024.rs155
-rw-r--r--src/tools/rustfmt/tests/source/fn-single-line/version_one.rs2
-rw-r--r--src/tools/rustfmt/tests/source/fn-single-line/version_two.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-2179/one.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-2179/two.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-3213/version_one.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-3213/version_two.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-3227/two.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-3270/one.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-3270/two.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-3272/v1.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-3272/v2.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-3278/version_one.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-3278/version_two.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-3295/two.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-3302.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-3701/one.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-3701/two.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-3805.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-3840/version-two_hard-tabs.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-3840/version-two_soft-tabs.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-4381/style_edition_2015.rs3
-rw-r--r--src/tools/rustfmt/tests/source/issue-4530.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-4689/one.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-4689/two.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-5586.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-5655/one.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-5655/two.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-5801/comment_unexpectedly_wraps_before_max_width.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-5987/two.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-6147/case_rustfmt_v1.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-6147/case_rustfmt_v2.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue_5027.rs2
-rw-r--r--src/tools/rustfmt/tests/source/let_else_v2.rs2
-rw-r--r--src/tools/rustfmt/tests/source/long-fn-1/version_one.rs2
-rw-r--r--src/tools/rustfmt/tests/source/long-fn-1/version_two.rs2
-rw-r--r--src/tools/rustfmt/tests/source/one_line_if_v1.rs2
-rw-r--r--src/tools/rustfmt/tests/source/one_line_if_v2.rs2
-rw-r--r--src/tools/rustfmt/tests/source/single-line-macro/v1.rs2
-rw-r--r--src/tools/rustfmt/tests/source/single-line-macro/v2.rs2
-rw-r--r--src/tools/rustfmt/tests/source/trailing_comments/hard_tabs.rs2
-rw-r--r--src/tools/rustfmt/tests/source/trailing_comments/soft_tabs.rs2
-rw-r--r--src/tools/rustfmt/tests/source/tuple_v2.rs2
-rw-r--r--src/tools/rustfmt/tests/source/type-alias-where-clauses-with-comments.rs31
-rw-r--r--src/tools/rustfmt/tests/source/type-alias-where-clauses.rs20
-rw-r--r--src/tools/rustfmt/tests/target/arrow_in_comments/arrow_in_single_comment.rs2
-rw-r--r--src/tools/rustfmt/tests/target/arrow_in_comments/multiple_arrows.rs2
-rw-r--r--src/tools/rustfmt/tests/target/configs/indent_style/block_trailing_comma_call/one.rs2
-rw-r--r--src/tools/rustfmt/tests/target/configs/indent_style/block_trailing_comma_call/two.rs2
-rw-r--r--src/tools/rustfmt/tests/target/configs/style_edition/overflow_delim_expr_2015.rs135
-rw-r--r--src/tools/rustfmt/tests/target/configs/style_edition/overflow_delim_expr_2024.rs120
-rw-r--r--src/tools/rustfmt/tests/target/configs/version/mapped.rs9
-rw-r--r--src/tools/rustfmt/tests/target/fn-single-line/version_one.rs2
-rw-r--r--src/tools/rustfmt/tests/target/fn-single-line/version_two.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-2179/one.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-2179/two.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-3132.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-3213/version_one.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-3213/version_two.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-3227/one.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-3227/two.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-3270/one.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-3270/two.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-3270/wrap.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-3272/v1.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-3272/v2.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-3278/version_one.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-3278/version_two.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-3295/two.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-3302.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-3614/version_one.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-3614/version_two.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-3701/one.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-3701/two.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-3805.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-3840/version-two_hard-tabs.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-3840/version-two_soft-tabs.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-3882.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-4381/style_edition_2015.rs3
-rw-r--r--src/tools/rustfmt/tests/target/issue-4381/style_edition_2024.rs3
-rw-r--r--src/tools/rustfmt/tests/target/issue-4530.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-4689/one.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-4689/two.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-5586.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-5655/one.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-5655/two.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-5801/comment_does_not_wrap_within_max_width.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-5801/comment_unexpectedly_wraps_before_max_width.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-5987/one.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-5987/two.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-6109.rs7
-rw-r--r--src/tools/rustfmt/tests/target/issue-6147/case_rustfmt_v1.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-6147/case_rustfmt_v2.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue_5027.rs2
-rw-r--r--src/tools/rustfmt/tests/target/let_else_v2.rs2
-rw-r--r--src/tools/rustfmt/tests/target/long-fn-1/version_one.rs2
-rw-r--r--src/tools/rustfmt/tests/target/long-fn-1/version_two.rs2
-rw-r--r--src/tools/rustfmt/tests/target/one_line_if_v1.rs2
-rw-r--r--src/tools/rustfmt/tests/target/one_line_if_v2.rs2
-rw-r--r--src/tools/rustfmt/tests/target/single-line-macro/v1.rs2
-rw-r--r--src/tools/rustfmt/tests/target/single-line-macro/v2.rs2
-rw-r--r--src/tools/rustfmt/tests/target/style_edition/default.rs10
-rw-r--r--src/tools/rustfmt/tests/target/style_edition/follows_edition.rs14
-rw-r--r--src/tools/rustfmt/tests/target/style_edition/overrides_edition_when_set.rs14
-rw-r--r--src/tools/rustfmt/tests/target/trailing_comments/hard_tabs.rs2
-rw-r--r--src/tools/rustfmt/tests/target/trailing_comments/soft_tabs.rs2
-rw-r--r--src/tools/rustfmt/tests/target/tuple_v2.rs2
-rw-r--r--src/tools/rustfmt/tests/target/type-alias-where-clauses-with-comments.rs39
-rw-r--r--src/tools/rustfmt/tests/target/type-alias-where-clauses.rs20
-rw-r--r--src/tools/tidy/src/issues.txt4
-rw-r--r--src/tools/tidy/src/lib.rs1
-rw-r--r--src/tools/tidy/src/main.rs1
-rw-r--r--src/tools/tidy/src/rustdoc_templates.rs58
-rw-r--r--tests/assembly/cmse.rs26
-rw-r--r--tests/assembly/simd-bitmask.rs1
-rw-r--r--tests/assembly/simd-intrinsic-gather.rs1
-rw-r--r--tests/assembly/simd-intrinsic-mask-reduce.rs1
-rw-r--r--tests/assembly/simd-intrinsic-scatter.rs1
-rw-r--r--tests/assembly/simd-intrinsic-select.rs1
-rw-r--r--tests/assembly/stack-probes.rs1
-rw-r--r--tests/assembly/stack-protector/stack-protector-heuristics-effect.rs1
-rw-r--r--tests/assembly/targets/targets-macho.rs5
-rw-r--r--tests/codegen/align-byval.rs28
-rw-r--r--tests/codegen/constant-branch.rs14
-rw-r--r--tests/codegen/enum/enum-early-otherwise-branch.rs1
-rw-r--r--tests/codegen/issue-97217.rs1
-rw-r--r--tests/codegen/issues/issue-110797-enum-jump-same.rs1
-rw-r--r--tests/codegen/issues/issue-118392.rs1
-rw-r--r--tests/codegen/issues/issue-44056-macos-tls-align.rs27
-rw-r--r--tests/codegen/maybeuninit-rvo.rs1
-rw-r--r--tests/codegen/no-alloca-inside-if-false.rs27
-rw-r--r--tests/codegen/option-niche-eq.rs1
-rw-r--r--tests/codegen/repr/transparent-byval-struct-ptr.rs4
-rw-r--r--tests/codegen/repr/transparent-opaque-ptr.rs4
-rw-r--r--tests/codegen/slice-pointer-nonnull-unwrap.rs1
-rw-r--r--tests/codegen/unwind-landingpad-cold.rs1
-rw-r--r--tests/codegen/unwind-landingpad-inline.rs1
-rw-r--r--tests/coverage/mcdc/condition-limit.cov-map8
-rw-r--r--tests/coverage/mcdc/condition-limit.coverage1
-rw-r--r--tests/coverage/mcdc/condition-limit.rs1
-rw-r--r--tests/coverage/mcdc/if.cov-map28
-rw-r--r--tests/coverage/mcdc/if.coverage1
-rw-r--r--tests/coverage/mcdc/if.rs1
-rw-r--r--tests/coverage/mcdc/inlined_expressions.cov-map4
-rw-r--r--tests/coverage/mcdc/inlined_expressions.coverage1
-rw-r--r--tests/coverage/mcdc/inlined_expressions.rs1
-rw-r--r--tests/coverage/mcdc/nested_if.cov-map16
-rw-r--r--tests/coverage/mcdc/nested_if.coverage1
-rw-r--r--tests/coverage/mcdc/nested_if.rs1
-rw-r--r--tests/coverage/mcdc/non_control_flow.cov-map28
-rw-r--r--tests/coverage/mcdc/non_control_flow.coverage1
-rw-r--r--tests/coverage/mcdc/non_control_flow.rs1
-rw-r--r--tests/crashes/125476.rs2
-rw-r--r--tests/crashes/130310.rs15
-rw-r--r--tests/run-make/compiler-builtins/rmake.rs4
-rw-r--r--tests/run-make/embed-source-dwarf/rmake.rs5
-rw-r--r--tests/run-make/thumb-none-cortex-m/rmake.rs6
-rw-r--r--tests/rustdoc-gui/docblock-code-block-line-number.goml118
-rw-r--r--tests/rustdoc-gui/scrape-examples-layout.goml8
-rw-r--r--tests/rustdoc-ui/doctest/doctest-output-include-fail.md7
-rw-r--r--tests/rustdoc-ui/doctest/doctest-output-include-fail.rs7
-rw-r--r--tests/rustdoc-ui/doctest/doctest-output-include-fail.stdout24
-rw-r--r--tests/rustdoc-ui/doctest/doctest-output.stdout2
-rw-r--r--tests/ui/abi/compatibility.rs1
-rw-r--r--tests/ui/abi/stack-probes-lto.rs1
-rw-r--r--tests/ui/abi/stack-probes.rs1
-rw-r--r--tests/ui/abi/statics/static-mut-foreign.rs5
-rw-r--r--tests/ui/abi/statics/static-mut-foreign.stderr31
-rw-r--r--tests/ui/array-slice-vec/slice-panic-1.rs2
-rw-r--r--tests/ui/array-slice-vec/slice-panic-2.rs2
-rw-r--r--tests/ui/array-slice-vec/slice.rs3
-rw-r--r--tests/ui/asm/inline-syntax.arm.stderr26
-rw-r--r--tests/ui/asm/inline-syntax.arm_llvm_18.stderr90
-rw-r--r--tests/ui/asm/inline-syntax.rs14
-rw-r--r--tests/ui/asm/inline-syntax.x86_64.stderr14
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs18
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr39
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/bare-path.rs5
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/bare-path.stderr51
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.rs52
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.stderr11
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/namespace-conflict.rs42
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/namespace-conflict.stderr11
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/non-rpitit.rs7
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/non-rpitit.stderr19
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/not-a-method.rs42
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/not-a-method.stderr49
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-ambiguous.rs27
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-ambiguous.stderr54
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.rs24
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.stderr11
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-higher-ranked.rs25
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-higher-ranked.stderr34
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-missing.rs25
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-missing.stderr33
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-no-qself.rs15
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-no-qself.stderr23
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-non-param-qself.rs21
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-non-param-qself.stderr30
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-self-qself.rs27
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-self-qself.stderr11
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-type-param.rs22
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-type-param.stderr29
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.rs25
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.stderr36
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-works.rs23
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/path-works.stderr11
-rw-r--r--tests/ui/async-await/issues/issue-67611-static-mut-refs.rs2
-rw-r--r--tests/ui/async-await/pin-reborrow-arg.rs36
-rw-r--r--tests/ui/async-await/pin-reborrow-const-as-mut.rs18
-rw-r--r--tests/ui/async-await/pin-reborrow-const-as-mut.stderr19
-rw-r--r--tests/ui/async-await/pin-reborrow-once.rs13
-rw-r--r--tests/ui/async-await/pin-reborrow-once.stderr12
-rw-r--r--tests/ui/async-await/pin-reborrow-self.rs24
-rw-r--r--tests/ui/async-await/pin-reborrow-shorter.rs14
-rw-r--r--tests/ui/attributes/issue-105594-invalid-attr-validation.rs6
-rw-r--r--tests/ui/attributes/issue-105594-invalid-attr-validation.stderr21
-rw-r--r--tests/ui/binding/order-drop-with-match.rs2
-rw-r--r--tests/ui/borrowck/borrowck-access-permissions.rs1
-rw-r--r--tests/ui/borrowck/borrowck-access-permissions.stderr25
-rw-r--r--tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr11
-rw-r--r--tests/ui/borrowck/issue-20801.rs1
-rw-r--r--tests/ui/borrowck/issue-20801.stderr25
-rw-r--r--tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs3
-rw-r--r--tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr55
-rw-r--r--tests/ui/cfg/cfg-false-feature.rs2
-rw-r--r--tests/ui/check-cfg/raw-keywords.edition2015.stderr40
-rw-r--r--tests/ui/check-cfg/raw-keywords.edition2021.stderr40
-rw-r--r--tests/ui/check-cfg/raw-keywords.rs40
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-call/callback-as-argument.rs20
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs7
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr18
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs9
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr11
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs12
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs17
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.aarch64.stderr9
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs25
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr9
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.thumb7.stderr9
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.x86.stderr9
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs16
-rw-r--r--tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr9
-rw-r--r--tests/ui/const-generics/early/trivial-const-arg-macro-braced-expansion.rs14
-rw-r--r--tests/ui/const-generics/early/trivial-const-arg-macro-braced-expansion.stderr14
-rw-r--r--tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces-2.rs15
-rw-r--r--tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces-2.stderr15
-rw-r--r--tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces.rs15
-rw-r--r--tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces.stderr15
-rw-r--r--tests/ui/const-generics/early/trivial-const-arg-nested-braces.rs9
-rw-r--r--tests/ui/const-generics/early/trivial-const-arg-nested-braces.stderr11
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-109141.rs3
-rw-r--r--tests/ui/const-generics/generic_const_exprs/issue-109141.stderr33
-rw-r--r--tests/ui/const-generics/generic_const_exprs/opaque_type.rs1
-rw-r--r--tests/ui/const-generics/generic_const_exprs/opaque_type.stderr14
-rw-r--r--tests/ui/const-generics/issue-112505-overflow.rs7
-rw-r--r--tests/ui/const-generics/issue-112505-overflow.stderr12
-rw-r--r--tests/ui/const-generics/transmute-fail.rs10
-rw-r--r--tests/ui/const-generics/transmute-fail.stderr43
-rw-r--r--tests/ui/consts/const-eval/stable-metric/evade-deduplication-issue-118612.rs24
-rw-r--r--tests/ui/consts/const-eval/stable-metric/evade-deduplication-issue-118612.stderr92
-rw-r--r--tests/ui/consts/const_let_assign2.stderr11
-rw-r--r--tests/ui/consts/issue-116186.rs2
-rw-r--r--tests/ui/consts/issue-116186.stderr11
-rw-r--r--tests/ui/consts/static-mut-refs.rs3
-rw-r--r--tests/ui/coroutine/static-mut-reference-across-yield.rs2
-rw-r--r--tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.rs2
-rw-r--r--tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.stderr2
-rw-r--r--tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs2
-rw-r--r--tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.stderr2
-rw-r--r--tests/ui/drop/drop-struct-as-object.rs3
-rw-r--r--tests/ui/drop/drop-struct-as-object.stderr2
-rw-r--r--tests/ui/drop/issue-23338-ensure-param-drop-order.rs3
-rw-r--r--tests/ui/drop/issue-23338-ensure-param-drop-order.stderr17
-rw-r--r--tests/ui/drop/issue-23611-enum-swap-in-drop.rs3
-rw-r--r--tests/ui/drop/issue-23611-enum-swap-in-drop.stderr17
-rw-r--r--tests/ui/drop/issue-48962.rs3
-rw-r--r--tests/ui/drop/repeat-drop.rs3
-rw-r--r--tests/ui/drop/static-issue-17302.rs (renamed from tests/ui/issues/issue-17302.rs)3
-rw-r--r--tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs19
-rw-r--r--tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr71
-rw-r--r--tests/ui/extern/extern-static-size-overflow.rs30
-rw-r--r--tests/ui/extern/extern-static-size-overflow.stderr12
-rw-r--r--tests/ui/feature-gates/feature-gate-pin_ergonomics.rs15
-rw-r--r--tests/ui/feature-gates/feature-gate-pin_ergonomics.stderr21
-rw-r--r--tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr3
-rw-r--r--tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs24
-rw-r--r--tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr41
-rw-r--r--tests/ui/for-loop-while/cleanup-rvalue-during-if-and-while.rs3
-rw-r--r--tests/ui/functional-struct-update/functional-struct-update-respects-privacy.rs4
-rw-r--r--tests/ui/functional-struct-update/functional-struct-update-respects-privacy.stderr2
-rw-r--r--tests/ui/half-open-range-patterns/range_pat_interactions1.stderr11
-rw-r--r--tests/ui/half-open-range-patterns/range_pat_interactions2.stderr23
-rw-r--r--tests/ui/instrument-coverage/mcdc-condition-limit.bad.stderr2
-rw-r--r--tests/ui/instrument-coverage/mcdc-condition-limit.rs1
-rw-r--r--tests/ui/issues/issue-10734.rs3
-rw-r--r--tests/ui/issues/issue-15858.rs2
-rw-r--r--tests/ui/issues/issue-15858.stderr2
-rw-r--r--tests/ui/issues/issue-16151.rs3
-rw-r--r--tests/ui/issues/issue-39367.rs1
-rw-r--r--tests/ui/issues/issue-39367.stderr17
-rw-r--r--tests/ui/issues/issue-4734.rs3
-rw-r--r--tests/ui/issues/issue-54410.rs1
-rw-r--r--tests/ui/issues/issue-54410.stderr17
-rw-r--r--tests/ui/issues/issue-6892.rs2
-rw-r--r--tests/ui/issues/issue-8860.rs2
-rw-r--r--tests/ui/layout/size-of-val-raw-too-big.rs2
-rw-r--r--tests/ui/layout/size-of-val-raw-too-big.stderr2
-rw-r--r--tests/ui/layout/too-big-with-padding.rs2
-rw-r--r--tests/ui/layout/too-big-with-padding.stderr2
-rw-r--r--tests/ui/limits/huge-array-simple-32.rs2
-rw-r--r--tests/ui/limits/huge-array-simple-32.stderr2
-rw-r--r--tests/ui/limits/huge-array-simple-64.rs2
-rw-r--r--tests/ui/limits/huge-array-simple-64.stderr2
-rw-r--r--tests/ui/limits/huge-array.stderr2
-rw-r--r--tests/ui/limits/huge-enum.rs4
-rw-r--r--tests/ui/limits/huge-enum.stderr2
-rw-r--r--tests/ui/limits/huge-static.rs (renamed from tests/ui/limits/issue-56762.rs)7
-rw-r--r--tests/ui/limits/huge-static.stderr (renamed from tests/ui/limits/issue-56762.stderr)8
-rw-r--r--tests/ui/limits/huge-struct.rs6
-rw-r--r--tests/ui/limits/huge-struct.stderr4
-rw-r--r--tests/ui/limits/issue-15919-32.stderr2
-rw-r--r--tests/ui/limits/issue-15919-64.stderr2
-rw-r--r--tests/ui/limits/issue-17913.rs2
-rw-r--r--tests/ui/limits/issue-17913.stderr2
-rw-r--r--tests/ui/limits/issue-55878.rs2
-rw-r--r--tests/ui/limits/issue-55878.stderr2
-rw-r--r--tests/ui/limits/issue-69485-var-size-diffs-too-large.rs2
-rw-r--r--tests/ui/limits/issue-69485-var-size-diffs-too-large.stderr2
-rw-r--r--tests/ui/limits/issue-75158-64.stderr2
-rw-r--r--tests/ui/link-section.rs3
-rw-r--r--tests/ui/linkage-attr/linkage-attr-mutable-static.rs2
-rw-r--r--tests/ui/linkage-attr/linkage-attr-mutable-static.stderr2
-rw-r--r--tests/ui/lint/extern-C-fnptr-lints-slices.rs9
-rw-r--r--tests/ui/lint/extern-C-fnptr-lints-slices.stderr16
-rw-r--r--tests/ui/lint/improper-types-stack-overflow-130310.rs20
-rw-r--r--tests/ui/lint/improper-types-stack-overflow-130310.stderr11
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin.rs7
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin2.rs7
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin3.rs8
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-cdylib.rs7
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-dylib.rs7
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-lib.rs7
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-proc-macro.rs7
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-proc-macro.stderr14
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-rlib.rs7
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-staticlib.rs7
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate-staticlib.stderr14
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr (renamed from tests/ui/lint/non-snake-case/lint-non-snake-case-crate-lib.stderr)4
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr (renamed from tests/ui/lint/non-snake-case/lint-non-snake-case-crate-rlib.stderr)4
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr (renamed from tests/ui/lint/non-snake-case/lint-non-snake-case-crate-dylib.stderr)4
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr (renamed from tests/ui/lint/non-snake-case/lint-non-snake-case-crate-cdylib.stderr)4
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr14
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs29
-rw-r--r--tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr14
-rw-r--r--tests/ui/lint/rust-cold-fn-accept-improper-ctypes.rs14
-rw-r--r--tests/ui/lint/static-mut-refs.e2021.stderr143
-rw-r--r--tests/ui/lint/static-mut-refs.e2024.stderr143
-rw-r--r--tests/ui/lint/static-mut-refs.rs95
-rw-r--r--tests/ui/lto/lto-still-runs-thread-dtors.rs3
-rw-r--r--tests/ui/macros/auxiliary/metavar_2018.rs14
-rw-r--r--tests/ui/macros/metavar_cross_edition_recursive_macros.rs38
-rw-r--r--tests/ui/methods/method-self-arg-trait.rs3
-rw-r--r--tests/ui/methods/method-self-arg.rs3
-rw-r--r--tests/ui/mir/mir_early_return_scope.rs2
-rw-r--r--tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr11
-rw-r--r--tests/ui/nll/issue-69114-static-mut-ty.rs3
-rw-r--r--tests/ui/nll/issue-69114-static-mut-ty.stderr4
-rw-r--r--tests/ui/numbers-arithmetic/shift-near-oflo.rs3
-rw-r--r--tests/ui/parser/bad-name.rs5
-rw-r--r--tests/ui/parser/bad-name.stderr20
-rw-r--r--tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/circular-module-with-doc-comment-issue-97589.rs6
-rw-r--r--tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/circular-module-with-doc-comment-issue-97589.stderr8
-rw-r--r--tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/recursive.rs6
-rw-r--r--tests/ui/parser/issues/issue-24375.stderr15
-rw-r--r--tests/ui/parser/pat-lt-bracket-6.stderr4
-rw-r--r--tests/ui/parser/pat-recover-exprs.rs28
-rw-r--r--tests/ui/parser/pat-recover-exprs.stderr76
-rw-r--r--tests/ui/parser/pat-recover-methodcalls.rs37
-rw-r--r--tests/ui/parser/pat-recover-methodcalls.stderr35
-rw-r--r--tests/ui/parser/pat-recover-ranges.stderr132
-rw-r--r--tests/ui/parser/recover/recover-pat-exprs.rs106
-rw-r--r--tests/ui/parser/recover/recover-pat-exprs.stderr772
-rw-r--r--tests/ui/parser/recover/recover-pat-issues.rs46
-rw-r--r--tests/ui/parser/recover/recover-pat-issues.stderr113
-rw-r--r--tests/ui/parser/recover/recover-pat-lets.rs20
-rw-r--r--tests/ui/parser/recover/recover-pat-lets.stderr52
-rw-r--r--tests/ui/parser/recover/recover-pat-ranges.rs (renamed from tests/ui/parser/pat-recover-ranges.rs)4
-rw-r--r--tests/ui/parser/recover/recover-pat-ranges.stderr216
-rw-r--r--tests/ui/parser/recover/recover-pat-wildcards.rs (renamed from tests/ui/parser/pat-recover-wildcards.rs)0
-rw-r--r--tests/ui/parser/recover/recover-pat-wildcards.stderr (renamed from tests/ui/parser/pat-recover-wildcards.stderr)43
-rw-r--r--tests/ui/parser/triple-colon-delegation.fixed44
-rw-r--r--tests/ui/parser/triple-colon-delegation.rs44
-rw-r--r--tests/ui/parser/triple-colon-delegation.stderr38
-rw-r--r--tests/ui/parser/triple-colon.fixed23
-rw-r--r--tests/ui/parser/triple-colon.rs23
-rw-r--r--tests/ui/parser/triple-colon.stderr146
-rw-r--r--tests/ui/print-calling-conventions.stdout1
-rw-r--r--tests/ui/rfcs/rfc-0000-never_patterns/never-pattern-is-a-read.rs16
-rw-r--r--tests/ui/rfcs/rfc-0000-never_patterns/never-pattern-is-a-read.stderr20
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs1
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr14
-rw-r--r--tests/ui/self/where-for-self.rs2
-rw-r--r--tests/ui/simd/simd-bitmask-notpow2.rs3
-rw-r--r--tests/ui/static/reference-to-mut-static-safe.e2021.stderr26
-rw-r--r--tests/ui/static/reference-to-mut-static-safe.e2024.stderr24
-rw-r--r--tests/ui/static/reference-to-mut-static-safe.rs13
-rw-r--r--tests/ui/static/reference-to-mut-static-unsafe-fn.rs28
-rw-r--r--tests/ui/static/reference-to-mut-static-unsafe-fn.stderr75
-rw-r--r--tests/ui/static/reference-to-mut-static.e2021.stderr91
-rw-r--r--tests/ui/static/reference-to-mut-static.e2024.stderr75
-rw-r--r--tests/ui/static/reference-to-mut-static.rs50
-rw-r--r--tests/ui/static/safe-extern-statics-mut.rs2
-rw-r--r--tests/ui/static/safe-extern-statics-mut.stderr35
-rw-r--r--tests/ui/statics/issue-15261.stderr11
-rw-r--r--tests/ui/statics/static-mut-xc.rs5
-rw-r--r--tests/ui/statics/static-mut-xc.stderr75
-rw-r--r--tests/ui/statics/static-recursive.rs1
-rw-r--r--tests/ui/statics/static-recursive.stderr22
-rw-r--r--tests/ui/structs-enums/type-sizes.rs20
-rw-r--r--tests/ui/suggestions/let-binding-init-expr-as-ty.rs4
-rw-r--r--tests/ui/suggestions/let-binding-init-expr-as-ty.stderr23
-rw-r--r--tests/ui/thread-local/thread-local-issue-37508.rs3
-rw-r--r--tests/ui/traits/coherence-alias-hang.rs2
-rw-r--r--tests/ui/traits/impl.rs3
-rw-r--r--tests/ui/traits/impl.stderr2
-rw-r--r--tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.stderr1
-rw-r--r--tests/ui/traits/next-solver/overflow/recursion-limit-zero-issue-115351.rs3
-rw-r--r--tests/ui/traits/next-solver/overflow/recursion-limit-zero-issue-115351.stderr11
-rw-r--r--tests/ui/traits/sized-coniductive.rs14
-rw-r--r--tests/ui/transmutability/arrays/huge-len.stderr4
-rw-r--r--tests/ui/union/union-drop-assign.rs3
-rw-r--r--tests/ui/union/union-drop.rs2
-rw-r--r--tests/ui/unsafe/union-pat-in-param.rs19
-rw-r--r--tests/ui/unsafe/union-pat-in-param.stderr19
889 files changed, 16110 insertions, 8027 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 1497d2d463a..e973d7f9a2a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4630,7 +4630,7 @@ dependencies = [
 
 [[package]]
 name = "rustfmt-nightly"
-version = "1.7.1"
+version = "1.8.0"
 dependencies = [
  "annotate-snippets 0.9.2",
  "anyhow",
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index f4de4e06d1b..01593d34c97 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -527,15 +527,10 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
             let count =
                 (niche_variants.end().index() as u128 - niche_variants.start().index() as u128) + 1;
 
-            // Find the field with the largest niche
-            let (field_index, niche, (niche_start, niche_scalar)) = variants[largest_variant_index]
-                .iter()
-                .enumerate()
-                .filter_map(|(j, field)| Some((j, field.largest_niche?)))
-                .max_by_key(|(_, niche)| niche.available(dl))
-                .and_then(|(j, niche)| Some((j, niche, niche.reserve(dl, count)?)))?;
-            let niche_offset =
-                niche.offset + variant_layouts[largest_variant_index].fields.offset(field_index);
+            // Use the largest niche in the largest variant.
+            let niche = variant_layouts[largest_variant_index].largest_niche?;
+            let (niche_start, niche_scalar) = niche.reserve(dl, count)?;
+            let niche_offset = niche.offset;
             let niche_size = niche.value.size(dl);
             let size = variant_layouts[largest_variant_index].size.align_to(align.abi);
 
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index 5668d8992c8..904c5933a18 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -337,23 +337,21 @@ impl TargetDataLayout {
         Ok(dl)
     }
 
-    /// Returns exclusive upper bound on object size.
+    /// Returns **exclusive** upper bound on object size in bytes.
     ///
     /// The theoretical maximum object size is defined as the maximum positive `isize` value.
     /// This ensures that the `offset` semantics remain well-defined by allowing it to correctly
     /// index every address within an object along with one byte past the end, along with allowing
     /// `isize` to store the difference between any two pointers into an object.
     ///
-    /// The upper bound on 64-bit currently needs to be lower because LLVM uses a 64-bit integer
-    /// to represent object size in bits. It would need to be 1 << 61 to account for this, but is
-    /// currently conservatively bounded to 1 << 47 as that is enough to cover the current usable
-    /// address space on 64-bit ARMv8 and x86_64.
+    /// LLVM uses a 64-bit integer to represent object size in *bits*, but we care only for bytes,
+    /// so we adopt such a more-constrained size bound due to its technical limitations.
     #[inline]
     pub fn obj_size_bound(&self) -> u64 {
         match self.pointer_size.bits() {
             16 => 1 << 15,
             32 => 1 << 31,
-            64 => 1 << 47,
+            64 => 1 << 61,
             bits => panic!("obj_size_bound: unknown pointer bit size {bits}"),
         }
     }
@@ -833,6 +831,28 @@ pub enum Integer {
 }
 
 impl Integer {
+    pub fn int_ty_str(self) -> &'static str {
+        use Integer::*;
+        match self {
+            I8 => "i8",
+            I16 => "i16",
+            I32 => "i32",
+            I64 => "i64",
+            I128 => "i128",
+        }
+    }
+
+    pub fn uint_ty_str(self) -> &'static str {
+        use Integer::*;
+        match self {
+            I8 => "u8",
+            I16 => "u16",
+            I32 => "u32",
+            I64 => "u64",
+            I128 => "u128",
+        }
+    }
+
     #[inline]
     pub fn size(self) -> Size {
         use Integer::*;
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index ac65b7b22bc..d49265de202 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -1187,8 +1187,8 @@ impl Expr {
     /// `min_const_generics` as more complex expressions are not supported.
     ///
     /// Does not ensure that the path resolves to a const param, the caller should check this.
-    pub fn is_potential_trivial_const_arg(&self) -> bool {
-        let this = self.maybe_unwrap_block();
+    pub fn is_potential_trivial_const_arg(&self, strip_identity_block: bool) -> bool {
+        let this = if strip_identity_block { self.maybe_unwrap_block().1 } else { self };
 
         if let ExprKind::Path(None, path) = &this.kind
             && path.is_potential_trivial_const_arg()
@@ -1199,14 +1199,15 @@ impl Expr {
         }
     }
 
-    pub fn maybe_unwrap_block(&self) -> &Expr {
+    /// Returns an expression with (when possible) *one* outter brace removed
+    pub fn maybe_unwrap_block(&self) -> (bool, &Expr) {
         if let ExprKind::Block(block, None) = &self.kind
             && let [stmt] = block.stmts.as_slice()
             && let StmtKind::Expr(expr) = &stmt.kind
         {
-            expr
+            (true, expr)
         } else {
-            self
+            (false, self)
         }
     }
 
diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs
index a9d1ee5c9c1..11867c39e02 100644
--- a/compiler/rustc_ast_lowering/src/asm.rs
+++ b/compiler/rustc_ast_lowering/src/asm.rs
@@ -20,8 +20,8 @@ use super::errors::{
 };
 use super::LoweringContext;
 use crate::{
-    fluent_generated as fluent, ImplTraitContext, ImplTraitPosition, ParamMode,
-    ResolverAstLoweringExt,
+    fluent_generated as fluent, AllowReturnTypeNotation, ImplTraitContext, ImplTraitPosition,
+    ParamMode, ResolverAstLoweringExt,
 };
 
 impl<'a, 'hir> LoweringContext<'a, 'hir> {
@@ -201,6 +201,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                                 &sym.qself,
                                 &sym.path,
                                 ParamMode::Optional,
+                                AllowReturnTypeNotation::No,
                                 ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                                 None,
                             );
@@ -220,7 +221,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             let parent_def_id = self.current_def_id_parent;
                             let node_id = self.next_node_id();
                             // HACK(min_generic_const_args): see lower_anon_const
-                            if !expr.is_potential_trivial_const_arg() {
+                            if !expr.is_potential_trivial_const_arg(true) {
                                 self.create_def(
                                     parent_def_id,
                                     node_id,
diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs
index ac527df474a..97483e85f77 100644
--- a/compiler/rustc_ast_lowering/src/delegation.rs
+++ b/compiler/rustc_ast_lowering/src/delegation.rs
@@ -52,7 +52,7 @@ use rustc_target::spec::abi;
 use {rustc_ast as ast, rustc_hir as hir};
 
 use super::{GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode};
-use crate::{ImplTraitPosition, ResolverAstLoweringExt};
+use crate::{AllowReturnTypeNotation, ImplTraitPosition, ResolverAstLoweringExt};
 
 pub(crate) struct DelegationResults<'hir> {
     pub body_id: hir::BodyId,
@@ -340,6 +340,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 &delegation.qself,
                 &delegation.path,
                 ParamMode::Optional,
+                AllowReturnTypeNotation::No,
                 ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                 None,
             );
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index e105026ebd1..d828c9856b9 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -23,7 +23,7 @@ use super::{
     GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt,
 };
 use crate::errors::YieldInClosure;
-use crate::{fluent_generated, FnDeclKind, ImplTraitPosition};
+use crate::{fluent_generated, AllowReturnTypeNotation, FnDeclKind, ImplTraitPosition};
 
 impl<'hir> LoweringContext<'_, 'hir> {
     fn lower_exprs(&mut self, exprs: &[AstP<Expr>]) -> &'hir [hir::Expr<'hir>] {
@@ -281,6 +281,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         qself,
                         path,
                         ParamMode::Optional,
+                        AllowReturnTypeNotation::No,
                         ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                         None,
                     );
@@ -328,6 +329,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                             &se.qself,
                             &se.path,
                             ParamMode::Optional,
+                            AllowReturnTypeNotation::No,
                             ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                             None,
                         )),
@@ -387,7 +389,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 let node_id = self.next_node_id();
 
                 // HACK(min_generic_const_args): see lower_anon_const
-                if !arg.is_potential_trivial_const_arg() {
+                if !arg.is_potential_trivial_const_arg(true) {
                     // Add a definition for the in-band const def.
                     self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, f.span);
                 }
@@ -1291,6 +1293,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         qself,
                         path,
                         ParamMode::Optional,
+                        AllowReturnTypeNotation::No,
                         ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                         None,
                     );
@@ -1311,6 +1314,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         qself,
                         path,
                         ParamMode::Optional,
+                        AllowReturnTypeNotation::No,
                         ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                         None,
                     );
@@ -1336,6 +1340,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     &se.qself,
                     &se.path,
                     ParamMode::Optional,
+                    AllowReturnTypeNotation::No,
                     ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                     None,
                 );
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index efd3ae336af..3f48fe67dbb 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -485,9 +485,23 @@ enum ParamMode {
     Optional,
 }
 
+#[derive(Copy, Clone, Debug)]
+enum AllowReturnTypeNotation {
+    /// Only in types, since RTN is denied later during HIR lowering.
+    Yes,
+    /// All other positions (path expr, method, use tree).
+    No,
+}
+
 enum GenericArgsMode {
+    /// Allow paren sugar, don't allow RTN.
     ParenSugar,
+    /// Allow RTN, don't allow paren sugar.
+    ReturnTypeNotation,
+    // Error if parenthesized generics or RTN are encountered.
     Err,
+    /// Silence errors when lowering generics. Only used with `Res::Err`.
+    Silence,
 }
 
 impl<'a, 'hir> LoweringContext<'a, 'hir> {
@@ -1226,7 +1240,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         }
 
         let id = self.lower_node_id(t.id);
-        let qpath = self.lower_qpath(t.id, qself, path, param_mode, itctx, None);
+        let qpath = self.lower_qpath(
+            t.id,
+            qself,
+            path,
+            param_mode,
+            AllowReturnTypeNotation::Yes,
+            itctx,
+            None,
+        );
         self.ty_path(id, t.span, qpath)
     }
 
@@ -2203,6 +2225,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             &None,
             &p.path,
             ParamMode::Explicit,
+            AllowReturnTypeNotation::No,
             itctx,
             Some(modifiers),
         ) {
@@ -2341,6 +2364,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     &None,
                     path,
                     ParamMode::Optional,
+                    AllowReturnTypeNotation::No,
                     ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                     None,
                 );
@@ -2419,6 +2443,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 qself,
                 path,
                 ParamMode::Optional,
+                AllowReturnTypeNotation::No,
                 ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                 None,
             );
@@ -2441,7 +2466,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     /// See [`hir::ConstArg`] for when to use this function vs
     /// [`Self::lower_anon_const_to_const_arg`].
     fn lower_anon_const_to_anon_const(&mut self, c: &AnonConst) -> &'hir hir::AnonConst {
-        if c.value.is_potential_trivial_const_arg() {
+        if c.value.is_potential_trivial_const_arg(true) {
             // HACK(min_generic_const_args): see DefCollector::visit_anon_const
             // Over there, we guess if this is a bare param and only create a def if
             // we think it's not. However we may can guess wrong (see there for example)
diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs
index d82bdd526b7..584d94ebe2d 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -11,7 +11,7 @@ use super::errors::{
     ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding,
 };
 use super::{ImplTraitContext, LoweringContext, ParamMode, ResolverAstLoweringExt};
-use crate::ImplTraitPosition;
+use crate::{AllowReturnTypeNotation, ImplTraitPosition};
 
 impl<'a, 'hir> LoweringContext<'a, 'hir> {
     pub(crate) fn lower_pat(&mut self, pattern: &Pat) -> &'hir hir::Pat<'hir> {
@@ -38,6 +38,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             qself,
                             path,
                             ParamMode::Optional,
+                            AllowReturnTypeNotation::No,
                             ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                             None,
                         );
@@ -55,6 +56,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             qself,
                             path,
                             ParamMode::Optional,
+                            AllowReturnTypeNotation::No,
                             ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                             None,
                         );
@@ -66,6 +68,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             qself,
                             path,
                             ParamMode::Optional,
+                            AllowReturnTypeNotation::No,
                             ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                             None,
                         );
diff --git a/compiler/rustc_ast_lowering/src/path.rs b/compiler/rustc_ast_lowering/src/path.rs
index 2ab30eff6d8..03c8097e4c3 100644
--- a/compiler/rustc_ast_lowering/src/path.rs
+++ b/compiler/rustc_ast_lowering/src/path.rs
@@ -5,6 +5,7 @@ use rustc_hir::def::{DefKind, PartialRes, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::GenericArg;
 use rustc_middle::span_bug;
+use rustc_session::parse::add_feature_diagnostics;
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::{BytePos, DesugaringKind, Span, Symbol, DUMMY_SP};
 use smallvec::{smallvec, SmallVec};
@@ -15,10 +16,9 @@ use super::errors::{
     GenericTypeWithParentheses, UseAngleBrackets,
 };
 use super::{
-    GenericArgsCtor, GenericArgsMode, ImplTraitContext, LifetimeRes, LoweringContext, ParamMode,
-    ResolverAstLoweringExt,
+    AllowReturnTypeNotation, GenericArgsCtor, GenericArgsMode, ImplTraitContext, ImplTraitPosition,
+    LifetimeRes, LoweringContext, ParamMode, ResolverAstLoweringExt,
 };
-use crate::ImplTraitPosition;
 
 impl<'a, 'hir> LoweringContext<'a, 'hir> {
     #[instrument(level = "trace", skip(self))]
@@ -28,6 +28,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         qself: &Option<ptr::P<QSelf>>,
         p: &Path,
         param_mode: ParamMode,
+        allow_return_type_notation: AllowReturnTypeNotation,
         itctx: ImplTraitContext,
         // modifiers of the impl/bound if this is a trait path
         modifiers: Option<ast::TraitBoundModifiers>,
@@ -103,8 +104,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                         {
                             GenericArgsMode::ParenSugar
                         }
+                        Res::Def(DefKind::AssocFn, _) if i + 1 == proj_start => {
+                            match allow_return_type_notation {
+                                AllowReturnTypeNotation::Yes => GenericArgsMode::ReturnTypeNotation,
+                                AllowReturnTypeNotation::No => GenericArgsMode::Err,
+                            }
+                        }
                         // Avoid duplicated errors.
-                        Res::Err => GenericArgsMode::ParenSugar,
+                        Res::Err => GenericArgsMode::Silence,
                         // An error
                         _ => GenericArgsMode::Err,
                     };
@@ -164,11 +171,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         //   3. `<<std::vec::Vec<T>>::IntoIter>::Item`
         // * final path is `<<<std::vec::Vec<T>>::IntoIter>::Item>::clone`
         for (i, segment) in p.segments.iter().enumerate().skip(proj_start) {
+            // If this is a type-dependent `T::method(..)`.
+            let generic_args_mode = if i + 1 == p.segments.len()
+                && matches!(allow_return_type_notation, AllowReturnTypeNotation::Yes)
+            {
+                GenericArgsMode::ReturnTypeNotation
+            } else {
+                GenericArgsMode::Err
+            };
+
             let hir_segment = self.arena.alloc(self.lower_path_segment(
                 p.span,
                 segment,
                 param_mode,
-                GenericArgsMode::Err,
+                generic_args_mode,
                 itctx,
                 None,
             ));
@@ -238,11 +254,46 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     self.lower_angle_bracketed_parameter_data(data, param_mode, itctx)
                 }
                 GenericArgs::Parenthesized(data) => match generic_args_mode {
-                    GenericArgsMode::ParenSugar => self.lower_parenthesized_parameter_data(
-                        data,
-                        itctx,
-                        bound_modifier_allowed_features,
-                    ),
+                    GenericArgsMode::ReturnTypeNotation => {
+                        let mut err = if !data.inputs.is_empty() {
+                            self.dcx().create_err(BadReturnTypeNotation::Inputs {
+                                span: data.inputs_span,
+                            })
+                        } else if let FnRetTy::Ty(ty) = &data.output {
+                            self.dcx().create_err(BadReturnTypeNotation::Output {
+                                span: data.inputs_span.shrink_to_hi().to(ty.span),
+                            })
+                        } else {
+                            self.dcx().create_err(BadReturnTypeNotation::NeedsDots {
+                                span: data.inputs_span,
+                            })
+                        };
+                        if !self.tcx.features().return_type_notation
+                            && self.tcx.sess.is_nightly_build()
+                        {
+                            add_feature_diagnostics(
+                                &mut err,
+                                &self.tcx.sess,
+                                sym::return_type_notation,
+                            );
+                        }
+                        err.emit();
+                        (
+                            GenericArgsCtor {
+                                args: Default::default(),
+                                constraints: &[],
+                                parenthesized: hir::GenericArgsParentheses::ReturnTypeNotation,
+                                span: path_span,
+                            },
+                            false,
+                        )
+                    }
+                    GenericArgsMode::ParenSugar | GenericArgsMode::Silence => self
+                        .lower_parenthesized_parameter_data(
+                            data,
+                            itctx,
+                            bound_modifier_allowed_features,
+                        ),
                     GenericArgsMode::Err => {
                         // Suggest replacing parentheses with angle brackets `Trait(params...)` to `Trait<params...>`
                         let sub = if !data.inputs.is_empty() {
@@ -279,7 +330,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     }
                 },
                 GenericArgs::ParenthesizedElided(span) => {
-                    self.dcx().emit_err(BadReturnTypeNotation::Position { span: *span });
+                    match generic_args_mode {
+                        GenericArgsMode::ReturnTypeNotation | GenericArgsMode::Silence => {
+                            // Ok
+                        }
+                        GenericArgsMode::ParenSugar | GenericArgsMode::Err => {
+                            self.dcx().emit_err(BadReturnTypeNotation::Position { span: *span });
+                        }
+                    }
                     (
                         GenericArgsCtor {
                             args: Default::default(),
diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl
index edb25e12864..ee4b2f95cb1 100644
--- a/compiler/rustc_borrowck/messages.ftl
+++ b/compiler/rustc_borrowck/messages.ftl
@@ -207,7 +207,7 @@ borrowck_simd_intrinsic_arg_const =
         *[other] {$arg}th
     } argument of `{$intrinsic}` is required to be a `const` item
 
-borrowck_suggest_create_freash_reborrow =
+borrowck_suggest_create_fresh_reborrow =
     consider reborrowing the `Pin` instead of moving it
 
 borrowck_suggest_iterate_over_slice =
diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs
index 4a50b0f0704..b6c6960d4ca 100644
--- a/compiler/rustc_borrowck/src/session_diagnostics.rs
+++ b/compiler/rustc_borrowck/src/session_diagnostics.rs
@@ -415,7 +415,7 @@ pub(crate) enum CaptureReasonSuggest<'tcx> {
         span: Span,
     },
     #[suggestion(
-        borrowck_suggest_create_freash_reborrow,
+        borrowck_suggest_create_fresh_reborrow,
         applicability = "maybe-incorrect",
         code = ".as_mut()",
         style = "verbose"
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index 24cf3f061a5..8838b15d29d 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -61,6 +61,9 @@ pub(crate) fn conv_to_call_conv(sess: &Session, c: Conv, default_call_conv: Call
         Conv::CCmseNonSecureCall => {
             sess.dcx().fatal("C-cmse-nonsecure-call call conv is not yet implemented");
         }
+        Conv::CCmseNonSecureEntry => {
+            sess.dcx().fatal("C-cmse-nonsecure-entry call conv is not yet implemented");
+        }
 
         Conv::Msp430Intr | Conv::PtxKernel | Conv::AvrInterrupt | Conv::AvrNonBlockingInterrupt => {
             unreachable!("tried to use {c:?} call conv which only exists on an unsupported target");
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 4af4b39cc5b..8839829e2f5 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -785,8 +785,10 @@ fn codegen_stmt<'tcx>(
                 }
                 Rvalue::Repeat(ref operand, times) => {
                     let operand = codegen_operand(fx, operand);
-                    let times =
-                        fx.monomorphize(times).eval_target_usize(fx.tcx, ParamEnv::reveal_all());
+                    let times = fx
+                        .monomorphize(times)
+                        .try_to_target_usize(fx.tcx)
+                        .expect("expected monomorphic const in codegen");
                     if operand.layout().size.bytes() == 0 {
                         // Do nothing for ZST's
                     } else if fx.clif_type(operand.layout().ty) == Some(types::I8) {
@@ -944,7 +946,10 @@ fn codegen_stmt<'tcx>(
 fn codegen_array_len<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, place: CPlace<'tcx>) -> Value {
     match *place.layout().ty.kind() {
         ty::Array(_elem_ty, len) => {
-            let len = fx.monomorphize(len).eval_target_usize(fx.tcx, ParamEnv::reveal_all()) as i64;
+            let len = fx
+                .monomorphize(len)
+                .try_to_target_usize(fx.tcx)
+                .expect("expected monomorphic const in codegen") as i64;
             fx.bcx.ins().iconst(fx.pointer_type, len)
         }
         ty::Slice(_elem_ty) => place.to_ptr_unsized().1,
diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs
index b9000a3874f..22ca2070715 100644
--- a/compiler/rustc_codegen_cranelift/src/common.rs
+++ b/compiler/rustc_codegen_cranelift/src/common.rs
@@ -309,8 +309,6 @@ pub(crate) struct FunctionCx<'m, 'clif, 'tcx: 'm> {
 }
 
 impl<'tcx> LayoutOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> {
-    type LayoutOfResult = TyAndLayout<'tcx>;
-
     #[inline]
     fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
         RevealAllLayoutCx(self.tcx).handle_layout_err(err, span, ty)
@@ -318,8 +316,6 @@ impl<'tcx> LayoutOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> {
 }
 
 impl<'tcx> FnAbiOfHelpers<'tcx> for FunctionCx<'_, '_, 'tcx> {
-    type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>;
-
     #[inline]
     fn handle_fn_abi_err(
         &self,
@@ -450,8 +446,6 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
 pub(crate) struct RevealAllLayoutCx<'tcx>(pub(crate) TyCtxt<'tcx>);
 
 impl<'tcx> LayoutOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> {
-    type LayoutOfResult = TyAndLayout<'tcx>;
-
     #[inline]
     fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
         if let LayoutError::SizeOverflow(_) | LayoutError::ReferencesError(_) = err {
@@ -466,8 +460,6 @@ impl<'tcx> LayoutOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> {
 }
 
 impl<'tcx> FnAbiOfHelpers<'tcx> for RevealAllLayoutCx<'tcx> {
-    type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>;
-
     #[inline]
     fn handle_fn_abi_err(
         &self,
diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/types.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/types.rs
index 7baf0a3868d..8a55a23128d 100644
--- a/compiler/rustc_codegen_cranelift/src/debuginfo/types.rs
+++ b/compiler/rustc_codegen_cranelift/src/debuginfo/types.rs
@@ -44,7 +44,7 @@ impl DebugContext {
                 type_dbg,
                 ty,
                 *elem_ty,
-                len.eval_target_usize(tcx, ty::ParamEnv::reveal_all()),
+                len.try_to_target_usize(tcx).expect("expected monomorphic const in codegen"),
             ),
             // ty::Slice(_) | ty::Str
             // ty::Dynamic
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
index a5621aec244..b96abb14b2e 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
@@ -131,9 +131,8 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
 
             let idx = generic_args[2]
                 .expect_const()
-                .eval(fx.tcx, ty::ParamEnv::reveal_all(), span)
-                .unwrap()
-                .1
+                .try_to_valtree()
+                .expect("expected monomorphic const in codegen")
                 .unwrap_branch();
 
             assert_eq!(x.layout(), y.layout());
diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs
index e09cd16e89a..8cfe93b4d9c 100644
--- a/compiler/rustc_codegen_cranelift/src/unsize.rs
+++ b/compiler/rustc_codegen_cranelift/src/unsize.rs
@@ -24,10 +24,10 @@ pub(crate) fn unsized_info<'tcx>(
     let (source, target) =
         fx.tcx.struct_lockstep_tails_for_codegen(source, target, ParamEnv::reveal_all());
     match (&source.kind(), &target.kind()) {
-        (&ty::Array(_, len), &ty::Slice(_)) => fx
-            .bcx
-            .ins()
-            .iconst(fx.pointer_type, len.eval_target_usize(fx.tcx, ParamEnv::reveal_all()) as i64),
+        (&ty::Array(_, len), &ty::Slice(_)) => fx.bcx.ins().iconst(
+            fx.pointer_type,
+            len.try_to_target_usize(fx.tcx).expect("expected monomorphic const in codegen") as i64,
+        ),
         (&ty::Dynamic(data_a, _, src_dyn_kind), &ty::Dynamic(data_b, _, target_dyn_kind))
             if src_dyn_kind == target_dyn_kind =>
         {
diff --git a/compiler/rustc_codegen_gcc/src/abi.rs b/compiler/rustc_codegen_gcc/src/abi.rs
index 0a99e7213be..ed78d4ef19f 100644
--- a/compiler/rustc_codegen_gcc/src/abi.rs
+++ b/compiler/rustc_codegen_gcc/src/abi.rs
@@ -1,7 +1,7 @@
 #[cfg(feature = "master")]
 use gccjit::FnAttribute;
 use gccjit::{ToLValue, ToRValue, Type};
-use rustc_codegen_ssa::traits::{AbiBuilderMethods, BaseTypeMethods};
+use rustc_codegen_ssa::traits::{AbiBuilderMethods, BaseTypeCodegenMethods};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::bug;
 use rustc_middle::ty::layout::LayoutOf;
diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs
index 7c135289958..13a00f7e08d 100644
--- a/compiler/rustc_codegen_gcc/src/asm.rs
+++ b/compiler/rustc_codegen_gcc/src/asm.rs
@@ -5,8 +5,8 @@ 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,
+    AsmBuilderMethods, AsmCodegenMethods, BaseTypeCodegenMethods, BuilderMethods,
+    GlobalAsmOperandRef, InlineAsmOperandRef,
 };
 use rustc_middle::bug;
 use rustc_middle::ty::Instance;
@@ -770,7 +770,7 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl
     }
 }
 
-impl<'gcc, 'tcx> AsmMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
+impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     fn codegen_global_asm(
         &self,
         template: &[InlineAsmTemplatePiece],
diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs
index 4940a7fa205..c0443faf24a 100644
--- a/compiler/rustc_codegen_gcc/src/base.rs
+++ b/compiler/rustc_codegen_gcc/src/base.rs
@@ -6,7 +6,7 @@ use std::time::Instant;
 use gccjit::{CType, 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::traits::DebugInfoCodegenMethods;
 use rustc_codegen_ssa::{ModuleCodegen, ModuleKind};
 use rustc_middle::dep_graph;
 use rustc_middle::mir::mono::Linkage;
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index 31d778823e0..9282d8699eb 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -14,8 +14,8 @@ use rustc_codegen_ssa::common::{
 use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
 use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::traits::{
-    BackendTypes, BaseTypeMethods, BuilderMethods, ConstMethods, HasCodegen, LayoutTypeMethods,
-    OverflowOp, StaticBuilderMethods,
+    BackendTypes, BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods,
+    LayoutTypeCodegenMethods, OverflowOp, StaticBuilderMethods,
 };
 use rustc_codegen_ssa::MemFlags;
 use rustc_data_structures::fx::FxHashSet;
@@ -23,7 +23,6 @@ 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::{Instance, ParamEnv, Ty, TyCtxt};
 use rustc_span::def_id::DefId;
@@ -460,10 +459,6 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> {
     }
 }
 
-impl<'gcc, 'tcx> HasCodegen<'tcx> for Builder<'_, 'gcc, 'tcx> {
-    type CodegenCx = CodegenCx<'gcc, 'tcx>;
-}
-
 impl<'tcx> HasTyCtxt<'tcx> for Builder<'_, '_, 'tcx> {
     fn tcx(&self) -> TyCtxt<'tcx> {
         self.cx.tcx()
@@ -477,8 +472,6 @@ impl HasDataLayout for Builder<'_, '_, '_> {
 }
 
 impl<'tcx> LayoutOfHelpers<'tcx> for Builder<'_, '_, 'tcx> {
-    type LayoutOfResult = TyAndLayout<'tcx>;
-
     #[inline]
     fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
         self.cx.handle_layout_err(err, span, ty)
@@ -486,8 +479,6 @@ impl<'tcx> LayoutOfHelpers<'tcx> for Builder<'_, '_, 'tcx> {
 }
 
 impl<'tcx> FnAbiOfHelpers<'tcx> for Builder<'_, '_, 'tcx> {
-    type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>;
-
     #[inline]
     fn handle_fn_abi_err(
         &self,
@@ -531,6 +522,8 @@ fn set_rvalue_location<'a, 'gcc, 'tcx>(
 }
 
 impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
+    type CodegenCx = CodegenCx<'gcc, 'tcx>;
+
     fn build(cx: &'a CodegenCx<'gcc, 'tcx>, block: Block<'gcc>) -> Builder<'a, 'gcc, 'tcx> {
         Builder::with_cx(cx, block)
     }
diff --git a/compiler/rustc_codegen_gcc/src/common.rs b/compiler/rustc_codegen_gcc/src/common.rs
index dca6b6494f9..b7ed34858b5 100644
--- a/compiler/rustc_codegen_gcc/src/common.rs
+++ b/compiler/rustc_codegen_gcc/src/common.rs
@@ -1,5 +1,7 @@
 use gccjit::{LValue, RValue, ToRValue, Type};
-use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods, MiscMethods, StaticMethods};
+use rustc_codegen_ssa::traits::{
+    BaseTypeCodegenMethods, ConstCodegenMethods, MiscCodegenMethods, StaticCodegenMethods,
+};
 use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
 use rustc_middle::mir::Mutability;
 use rustc_middle::ty::layout::LayoutOf;
@@ -55,7 +57,7 @@ pub fn type_is_pointer(typ: Type<'_>) -> bool {
     typ.get_pointee().is_some()
 }
 
-impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
+impl<'gcc, 'tcx> ConstCodegenMethods<'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 { self.const_int(typ, 0) }
     }
@@ -78,22 +80,14 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         self.const_undef(typ)
     }
 
-    fn const_int(&self, typ: Type<'gcc>, int: i64) -> RValue<'gcc> {
-        self.gcc_int(typ, int)
-    }
-
-    fn const_uint(&self, typ: Type<'gcc>, int: u64) -> RValue<'gcc> {
-        self.gcc_uint(typ, int)
-    }
-
-    fn const_uint_big(&self, typ: Type<'gcc>, num: u128) -> RValue<'gcc> {
-        self.gcc_uint_big(typ, num)
-    }
-
     fn const_bool(&self, val: bool) -> RValue<'gcc> {
         self.const_uint(self.type_i1(), val as u64)
     }
 
+    fn const_i8(&self, i: i8) -> RValue<'gcc> {
+        self.const_int(self.type_i8(), i as i64)
+    }
+
     fn const_i16(&self, i: i16) -> RValue<'gcc> {
         self.const_int(self.type_i16(), i as i64)
     }
@@ -102,8 +96,12 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         self.const_int(self.type_i32(), i as i64)
     }
 
-    fn const_i8(&self, i: i8) -> RValue<'gcc> {
-        self.const_int(self.type_i8(), i as i64)
+    fn const_int(&self, typ: Type<'gcc>, int: i64) -> RValue<'gcc> {
+        self.gcc_int(typ, int)
+    }
+
+    fn const_u8(&self, i: u8) -> RValue<'gcc> {
+        self.const_uint(self.type_u8(), i as u64)
     }
 
     fn const_u32(&self, i: u32) -> RValue<'gcc> {
@@ -128,8 +126,12 @@ impl<'gcc, 'tcx> ConstMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         self.const_uint(self.usize_type, i)
     }
 
-    fn const_u8(&self, i: u8) -> RValue<'gcc> {
-        self.const_uint(self.type_u8(), i as u64)
+    fn const_uint(&self, typ: Type<'gcc>, int: u64) -> RValue<'gcc> {
+        self.gcc_uint(typ, int)
+    }
+
+    fn const_uint_big(&self, typ: Type<'gcc>, num: u128) -> RValue<'gcc> {
+        self.gcc_uint_big(typ, num)
     }
 
     fn const_real(&self, typ: Type<'gcc>, val: f64) -> RValue<'gcc> {
diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs
index e5673cddc4a..68b9df946d0 100644
--- a/compiler/rustc_codegen_gcc/src/consts.rs
+++ b/compiler/rustc_codegen_gcc/src/consts.rs
@@ -1,7 +1,9 @@
 #[cfg(feature = "master")]
 use gccjit::{FnAttribute, VarAttribute, Visibility};
 use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue, Type};
-use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods, StaticMethods};
+use rustc_codegen_ssa::traits::{
+    BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods,
+};
 use rustc_hir::def::DefKind;
 use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs};
 use rustc_middle::mir::interpret::{
@@ -37,7 +39,7 @@ fn set_global_alignment<'gcc, 'tcx>(
     gv.set_alignment(align.bytes() as i32);
 }
 
-impl<'gcc, 'tcx> StaticMethods for CodegenCx<'gcc, 'tcx> {
+impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> {
     fn static_addr_of(&self, cv: RValue<'gcc>, align: Align, kind: Option<&str>) -> RValue<'gcc> {
         // TODO(antoyo): implement a proper rvalue comparison in libgccjit instead of doing the
         // following:
diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs
index e330102fbd8..8e1a5b61285 100644
--- a/compiler/rustc_codegen_gcc/src/context.rs
+++ b/compiler/rustc_codegen_gcc/src/context.rs
@@ -5,20 +5,19 @@ use gccjit::{
 };
 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_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, MiscCodegenMethods};
 use rustc_data_structures::base_n::{ToBaseN, ALPHANUMERIC_ONLY};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 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,
+    LayoutOfHelpers,
 };
 use rustc_middle::ty::{self, Instance, ParamEnv, PolyExistentialTraitRef, Ty, TyCtxt};
 use rustc_session::Session;
 use rustc_span::source_map::respan;
 use rustc_span::{Span, DUMMY_SP};
-use rustc_target::abi::call::FnAbi;
 use rustc_target::abi::{HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx};
 use rustc_target::spec::{HasTargetSpec, HasWasmCAbiOpt, Target, TlsModel, WasmCAbi};
 
@@ -426,7 +425,7 @@ impl<'gcc, 'tcx> BackendTypes for CodegenCx<'gcc, 'tcx> {
     type DIVariable = (); // TODO(antoyo)
 }
 
-impl<'gcc, 'tcx> MiscMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
+impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     fn vtables(
         &self,
     ) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<PolyExistentialTraitRef<'tcx>>), RValue<'gcc>>> {
@@ -572,8 +571,6 @@ impl<'gcc, 'tcx> HasWasmCAbiOpt for CodegenCx<'gcc, 'tcx> {
 }
 
 impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> {
-    type LayoutOfResult = TyAndLayout<'tcx>;
-
     #[inline]
     fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
         if let LayoutError::SizeOverflow(_) | LayoutError::ReferencesError(_) = err {
@@ -585,8 +582,6 @@ impl<'gcc, 'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> {
 }
 
 impl<'gcc, 'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> {
-    type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>;
-
     #[inline]
     fn handle_fn_abi_err(
         &self,
diff --git a/compiler/rustc_codegen_gcc/src/debuginfo.rs b/compiler/rustc_codegen_gcc/src/debuginfo.rs
index f2ae9f9c8a6..1d859656b3e 100644
--- a/compiler/rustc_codegen_gcc/src/debuginfo.rs
+++ b/compiler/rustc_codegen_gcc/src/debuginfo.rs
@@ -2,7 +2,7 @@ use std::ops::Range;
 
 use gccjit::{Location, RValue};
 use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind};
-use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoMethods};
+use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoCodegenMethods};
 use rustc_data_structures::sync::Lrc;
 use rustc_index::bit_set::BitSet;
 use rustc_index::{Idx, IndexVec};
@@ -206,7 +206,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
     }
 }
 
-impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
+impl<'gcc, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     fn create_vtable_debuginfo(
         &self,
         _ty: Ty<'tcx>,
diff --git a/compiler/rustc_codegen_gcc/src/declare.rs b/compiler/rustc_codegen_gcc/src/declare.rs
index a2b158ee0a7..46818045f0b 100644
--- a/compiler/rustc_codegen_gcc/src/declare.rs
+++ b/compiler/rustc_codegen_gcc/src/declare.rs
@@ -1,7 +1,7 @@
 #[cfg(feature = "master")]
 use gccjit::{FnAttribute, ToRValue};
 use gccjit::{Function, FunctionType, GlobalKind, LValue, RValue, Type};
-use rustc_codegen_ssa::traits::BaseTypeMethods;
+use rustc_codegen_ssa::traits::BaseTypeCodegenMethods;
 use rustc_middle::ty::Ty;
 use rustc_span::Symbol;
 use rustc_target::abi::call::FnAbi;
diff --git a/compiler/rustc_codegen_gcc/src/int.rs b/compiler/rustc_codegen_gcc/src/int.rs
index 92d5c1cbbb8..29f4db6738b 100644
--- a/compiler/rustc_codegen_gcc/src/int.rs
+++ b/compiler/rustc_codegen_gcc/src/int.rs
@@ -4,7 +4,7 @@
 
 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_codegen_ssa::traits::{BackendTypes, BaseTypeCodegenMethods, BuilderMethods, OverflowOp};
 use rustc_middle::ty::{ParamEnv, Ty};
 use rustc_target::abi::call::{ArgAbi, ArgAttributes, Conv, FnAbi, PassMode};
 use rustc_target::abi::Endian;
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
index 9352a67e362..4fd033255fe 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
@@ -13,10 +13,10 @@ use rustc_codegen_ssa::errors::InvalidMonomorphization;
 use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
 use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue};
 use rustc_codegen_ssa::traits::{
-    ArgAbiMethods, BuilderMethods, ConstMethods, IntrinsicCallMethods,
+    ArgAbiBuilderMethods, BuilderMethods, ConstCodegenMethods, IntrinsicCallBuilderMethods,
 };
 #[cfg(feature = "master")]
-use rustc_codegen_ssa::traits::{BaseTypeMethods, MiscMethods};
+use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, MiscCodegenMethods};
 use rustc_codegen_ssa::MemFlags;
 use rustc_middle::bug;
 use rustc_middle::ty::layout::LayoutOf;
@@ -94,7 +94,7 @@ fn get_simple_intrinsic<'gcc, 'tcx>(
     Some(cx.context.get_builtin_function(gcc_name))
 }
 
-impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
+impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
     fn codegen_intrinsic_call(
         &mut self,
         instance: Instance<'tcx>,
@@ -448,7 +448,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
     }
 }
 
-impl<'a, 'gcc, 'tcx> ArgAbiMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
+impl<'a, 'gcc, 'tcx> ArgAbiBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
     fn store_fn_arg(
         &mut self,
         arg_abi: &ArgAbi<'tcx, Ty<'tcx>>,
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
index 2eabc1430db..28f6a0821fb 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
@@ -10,7 +10,7 @@ use rustc_codegen_ssa::errors::ExpectedPointerMutability;
 use rustc_codegen_ssa::errors::InvalidMonomorphization;
 use rustc_codegen_ssa::mir::operand::OperandRef;
 use rustc_codegen_ssa::mir::place::PlaceRef;
-use rustc_codegen_ssa::traits::{BaseTypeMethods, BuilderMethods};
+use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods};
 #[cfg(feature = "master")]
 use rustc_hir as hir;
 use rustc_middle::mir::BinOp;
diff --git a/compiler/rustc_codegen_gcc/src/mono_item.rs b/compiler/rustc_codegen_gcc/src/mono_item.rs
index e6b22d51871..8a8b748750c 100644
--- a/compiler/rustc_codegen_gcc/src/mono_item.rs
+++ b/compiler/rustc_codegen_gcc/src/mono_item.rs
@@ -1,6 +1,6 @@
 #[cfg(feature = "master")]
 use gccjit::{FnAttribute, VarAttribute};
-use rustc_codegen_ssa::traits::PreDefineMethods;
+use rustc_codegen_ssa::traits::PreDefineCodegenMethods;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_middle::bug;
@@ -13,7 +13,7 @@ use crate::context::CodegenCx;
 use crate::type_of::LayoutGccExt;
 use crate::{attributes, base};
 
-impl<'gcc, 'tcx> PreDefineMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
+impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     #[cfg_attr(not(feature = "master"), allow(unused_variables))]
     fn predefine_static(
         &self,
diff --git a/compiler/rustc_codegen_gcc/src/type_.rs b/compiler/rustc_codegen_gcc/src/type_.rs
index e20234c5ce7..4ea5544721d 100644
--- a/compiler/rustc_codegen_gcc/src/type_.rs
+++ b/compiler/rustc_codegen_gcc/src/type_.rs
@@ -5,7 +5,9 @@ use std::convert::TryInto;
 use gccjit::CType;
 use gccjit::{RValue, Struct, Type};
 use rustc_codegen_ssa::common::TypeKind;
-use rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, TypeMembershipMethods};
+use rustc_codegen_ssa::traits::{
+    BaseTypeCodegenMethods, DerivedTypeCodegenMethods, TypeMembershipCodegenMethods,
+};
 use rustc_middle::ty::layout::TyAndLayout;
 use rustc_middle::{bug, ty};
 use rustc_target::abi::{AddressSpace, Align, Integer, Size};
@@ -121,7 +123,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> {
     }
 }
 
-impl<'gcc, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
+impl<'gcc, 'tcx> BaseTypeCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     fn type_i8(&self) -> Type<'gcc> {
         self.i8_type
     }
@@ -381,4 +383,4 @@ pub fn struct_fields<'gcc, 'tcx>(
     (result, packed)
 }
 
-impl<'gcc, 'tcx> TypeMembershipMethods<'tcx> for CodegenCx<'gcc, 'tcx> {}
+impl<'gcc, 'tcx> TypeMembershipCodegenMethods<'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 b7b1be5369c..cb45bbde2c2 100644
--- a/compiler/rustc_codegen_gcc/src/type_of.rs
+++ b/compiler/rustc_codegen_gcc/src/type_of.rs
@@ -1,7 +1,9 @@
 use std::fmt::Write;
 
 use gccjit::{Struct, Type};
-use rustc_codegen_ssa::traits::{BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods};
+use rustc_codegen_ssa::traits::{
+    BaseTypeCodegenMethods, DerivedTypeCodegenMethods, LayoutTypeCodegenMethods,
+};
 use rustc_middle::bug;
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::print::with_no_trimmed_paths;
@@ -330,7 +332,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> {
     }
 }
 
-impl<'gcc, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
+impl<'gcc, 'tcx> LayoutTypeCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
     fn backend_type(&self, layout: TyAndLayout<'tcx>) -> Type<'gcc> {
         layout.gcc_type(self)
     }
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index dea574a53cd..0fa8c9d3f19 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -285,7 +285,7 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> {
     }
 }
 
-impl<'ll, 'tcx> ArgAbiMethods<'tcx> for Builder<'_, 'll, 'tcx> {
+impl<'ll, 'tcx> ArgAbiBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
     fn store_fn_arg(
         &mut self,
         arg_abi: &ArgAbi<'tcx, Ty<'tcx>>,
@@ -422,6 +422,9 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
         if let Conv::RiscvInterrupt { kind } = self.conv {
             func_attrs.push(llvm::CreateAttrStringValue(cx.llcx, "interrupt", kind.as_str()));
         }
+        if let Conv::CCmseNonSecureEntry = self.conv {
+            func_attrs.push(llvm::CreateAttrString(cx.llcx, "cmse_nonsecure_entry"))
+        }
         attributes::apply_to_llfn(llfn, llvm::AttributePlace::Function, &{ func_attrs });
 
         let mut i = 0;
@@ -465,9 +468,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> {
                     cx.type_array(cx.type_i8(), self.ret.layout.size.bytes()),
                 );
                 attributes::apply_to_llfn(llfn, llvm::AttributePlace::Argument(i), &[sret]);
-                if cx.sess().opts.optimize != config::OptLevel::No
-                    && llvm_util::get_version() >= (18, 0, 0)
-                {
+                if cx.sess().opts.optimize != config::OptLevel::No {
                     attributes::apply_to_llfn(
                         llfn,
                         llvm::AttributePlace::Argument(i),
@@ -661,9 +662,11 @@ impl<'tcx> AbiBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
 impl From<Conv> for llvm::CallConv {
     fn from(conv: Conv) -> Self {
         match conv {
-            Conv::C | Conv::Rust | Conv::CCmseNonSecureCall | Conv::RiscvInterrupt { .. } => {
-                llvm::CCallConv
-            }
+            Conv::C
+            | Conv::Rust
+            | Conv::CCmseNonSecureCall
+            | Conv::CCmseNonSecureEntry
+            | Conv::RiscvInterrupt { .. } => llvm::CCallConv,
             Conv::Cold => llvm::ColdCallConv,
             Conv::PreserveMost => llvm::PreserveMost,
             Conv::PreserveAll => llvm::PreserveAll,
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index 1d91c3fb17d..430ba735243 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -356,7 +356,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
     }
 }
 
-impl<'tcx> AsmMethods<'tcx> for CodegenCx<'_, 'tcx> {
+impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
     fn codegen_global_asm(
         &self,
         template: &[InlineAsmTemplatePiece],
@@ -520,24 +520,16 @@ pub(crate) fn inline_asm_call<'ll>(
 
 /// If the register is an xmm/ymm/zmm register then return its index.
 fn xmm_reg_index(reg: InlineAsmReg) -> Option<u32> {
+    use X86InlineAsmReg::*;
     match reg {
-        InlineAsmReg::X86(reg)
-            if reg as u32 >= X86InlineAsmReg::xmm0 as u32
-                && reg as u32 <= X86InlineAsmReg::xmm15 as u32 =>
-        {
-            Some(reg as u32 - X86InlineAsmReg::xmm0 as u32)
+        InlineAsmReg::X86(reg) if reg as u32 >= xmm0 as u32 && reg as u32 <= xmm15 as u32 => {
+            Some(reg as u32 - xmm0 as u32)
         }
-        InlineAsmReg::X86(reg)
-            if reg as u32 >= X86InlineAsmReg::ymm0 as u32
-                && reg as u32 <= X86InlineAsmReg::ymm15 as u32 =>
-        {
-            Some(reg as u32 - X86InlineAsmReg::ymm0 as u32)
+        InlineAsmReg::X86(reg) if reg as u32 >= ymm0 as u32 && reg as u32 <= ymm15 as u32 => {
+            Some(reg as u32 - ymm0 as u32)
         }
-        InlineAsmReg::X86(reg)
-            if reg as u32 >= X86InlineAsmReg::zmm0 as u32
-                && reg as u32 <= X86InlineAsmReg::zmm31 as u32 =>
-        {
-            Some(reg as u32 - X86InlineAsmReg::zmm0 as u32)
+        InlineAsmReg::X86(reg) if reg as u32 >= zmm0 as u32 && reg as u32 <= zmm31 as u32 => {
+            Some(reg as u32 - zmm0 as u32)
         }
         _ => None,
     }
@@ -545,50 +537,56 @@ fn xmm_reg_index(reg: InlineAsmReg) -> Option<u32> {
 
 /// If the register is an AArch64 integer register then return its index.
 fn a64_reg_index(reg: InlineAsmReg) -> Option<u32> {
-    match reg {
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x0) => Some(0),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x1) => Some(1),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x2) => Some(2),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x3) => Some(3),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x4) => Some(4),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x5) => Some(5),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x6) => Some(6),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x7) => Some(7),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x8) => Some(8),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x9) => Some(9),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x10) => Some(10),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x11) => Some(11),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x12) => Some(12),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x13) => Some(13),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x14) => Some(14),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x15) => Some(15),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x16) => Some(16),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x17) => Some(17),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x18) => Some(18),
-        // x19 is reserved
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x20) => Some(20),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x21) => Some(21),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x22) => Some(22),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x23) => Some(23),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x24) => Some(24),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x25) => Some(25),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x26) => Some(26),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x27) => Some(27),
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x28) => Some(28),
-        // x29 is reserved
-        InlineAsmReg::AArch64(AArch64InlineAsmReg::x30) => Some(30),
-        _ => None,
-    }
+    use AArch64InlineAsmReg::*;
+    // Unlike `a64_vreg_index`, we can't subtract `x0` to get the u32 because
+    // `x19` and `x29` are missing and the integer constants for the
+    // `x0`..`x30` enum variants don't all match the register number. E.g. the
+    // integer constant for `x18` is 18, but the constant for `x20` is 19.
+    Some(match reg {
+        InlineAsmReg::AArch64(r) => match r {
+            x0 => 0,
+            x1 => 1,
+            x2 => 2,
+            x3 => 3,
+            x4 => 4,
+            x5 => 5,
+            x6 => 6,
+            x7 => 7,
+            x8 => 8,
+            x9 => 9,
+            x10 => 10,
+            x11 => 11,
+            x12 => 12,
+            x13 => 13,
+            x14 => 14,
+            x15 => 15,
+            x16 => 16,
+            x17 => 17,
+            x18 => 18,
+            // x19 is reserved
+            x20 => 20,
+            x21 => 21,
+            x22 => 22,
+            x23 => 23,
+            x24 => 24,
+            x25 => 25,
+            x26 => 26,
+            x27 => 27,
+            x28 => 28,
+            // x29 is reserved
+            x30 => 30,
+            _ => return None,
+        },
+        _ => return None,
+    })
 }
 
 /// If the register is an AArch64 vector register then return its index.
 fn a64_vreg_index(reg: InlineAsmReg) -> Option<u32> {
+    use AArch64InlineAsmReg::*;
     match reg {
-        InlineAsmReg::AArch64(reg)
-            if reg as u32 >= AArch64InlineAsmReg::v0 as u32
-                && reg as u32 <= AArch64InlineAsmReg::v31 as u32 =>
-        {
-            Some(reg as u32 - AArch64InlineAsmReg::v0 as u32)
+        InlineAsmReg::AArch64(reg) if reg as u32 >= v0 as u32 && reg as u32 <= v31 as u32 => {
+            Some(reg as u32 - v0 as u32)
         }
         _ => None,
     }
@@ -596,6 +594,7 @@ fn a64_vreg_index(reg: InlineAsmReg) -> Option<u32> {
 
 /// Converts a register class to an LLVM constraint code.
 fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> String {
+    use InlineAsmRegClass::*;
     match reg {
         // For vector registers LLVM wants the register name to match the type size.
         InlineAsmRegOrRegClass::Reg(reg) => {
@@ -652,75 +651,66 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) ->
         // The constraints can be retrieved from
         // https://llvm.org/docs/LangRef.html#supported-constraint-code-list
         InlineAsmRegOrRegClass::RegClass(reg) => match reg {
-            InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => "r",
-            InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => "w",
-            InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => "x",
-            InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
-                unreachable!("clobber-only")
-            }
-            InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => "r",
-            InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
-            | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16)
-            | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8) => "t",
-            InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16)
-            | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low8)
-            | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => "x",
-            InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg)
-            | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => "w",
-            InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => "r",
-            InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => "r",
-            InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => "f",
-            InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => "r",
-            InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => "f",
-            InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => "h",
-            InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => "r",
-            InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => "l",
-            InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => "r",
-            InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b",
-            InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
-            InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::cr)
-            | InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::xer) => {
+            AArch64(AArch64InlineAsmRegClass::reg) => "r",
+            AArch64(AArch64InlineAsmRegClass::vreg) => "w",
+            AArch64(AArch64InlineAsmRegClass::vreg_low16) => "x",
+            AArch64(AArch64InlineAsmRegClass::preg) => unreachable!("clobber-only"),
+            Arm(ArmInlineAsmRegClass::reg) => "r",
+            Arm(ArmInlineAsmRegClass::sreg)
+            | Arm(ArmInlineAsmRegClass::dreg_low16)
+            | Arm(ArmInlineAsmRegClass::qreg_low8) => "t",
+            Arm(ArmInlineAsmRegClass::sreg_low16)
+            | Arm(ArmInlineAsmRegClass::dreg_low8)
+            | Arm(ArmInlineAsmRegClass::qreg_low4) => "x",
+            Arm(ArmInlineAsmRegClass::dreg) | Arm(ArmInlineAsmRegClass::qreg) => "w",
+            Hexagon(HexagonInlineAsmRegClass::reg) => "r",
+            LoongArch(LoongArchInlineAsmRegClass::reg) => "r",
+            LoongArch(LoongArchInlineAsmRegClass::freg) => "f",
+            Mips(MipsInlineAsmRegClass::reg) => "r",
+            Mips(MipsInlineAsmRegClass::freg) => "f",
+            Nvptx(NvptxInlineAsmRegClass::reg16) => "h",
+            Nvptx(NvptxInlineAsmRegClass::reg32) => "r",
+            Nvptx(NvptxInlineAsmRegClass::reg64) => "l",
+            PowerPC(PowerPCInlineAsmRegClass::reg) => "r",
+            PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => "b",
+            PowerPC(PowerPCInlineAsmRegClass::freg) => "f",
+            PowerPC(PowerPCInlineAsmRegClass::cr) | PowerPC(PowerPCInlineAsmRegClass::xer) => {
                 unreachable!("clobber-only")
             }
-            InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r",
-            InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f",
-            InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
-                unreachable!("clobber-only")
-            }
-            InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) => "r",
-            InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => "Q",
-            InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => "q",
-            InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg)
-            | InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg) => "x",
-            InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => "v",
-            InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => "^Yk",
-            InlineAsmRegClass::X86(
+            RiscV(RiscVInlineAsmRegClass::reg) => "r",
+            RiscV(RiscVInlineAsmRegClass::freg) => "f",
+            RiscV(RiscVInlineAsmRegClass::vreg) => unreachable!("clobber-only"),
+            X86(X86InlineAsmRegClass::reg) => "r",
+            X86(X86InlineAsmRegClass::reg_abcd) => "Q",
+            X86(X86InlineAsmRegClass::reg_byte) => "q",
+            X86(X86InlineAsmRegClass::xmm_reg) | X86(X86InlineAsmRegClass::ymm_reg) => "x",
+            X86(X86InlineAsmRegClass::zmm_reg) => "v",
+            X86(X86InlineAsmRegClass::kreg) => "^Yk",
+            X86(
                 X86InlineAsmRegClass::x87_reg
                 | X86InlineAsmRegClass::mmx_reg
                 | X86InlineAsmRegClass::kreg0
                 | X86InlineAsmRegClass::tmm_reg,
             ) => unreachable!("clobber-only"),
-            InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => "r",
-            InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => "r",
-            InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => "w",
-            InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg) => "r",
-            InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_upper) => "d",
-            InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) => "r",
-            InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) => "w",
-            InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => "e",
-            InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg) => "r",
-            InlineAsmRegClass::S390x(S390xInlineAsmRegClass::reg_addr) => "a",
-            InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => "f",
-            InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => "r",
-            InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => "r",
-            InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => "a",
-            InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => "d",
-            InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::reg) => "r",
-            InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::freg) => "f",
-            InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
-                bug!("LLVM backend does not support SPIR-V")
-            }
-            InlineAsmRegClass::Err => unreachable!(),
+            Wasm(WasmInlineAsmRegClass::local) => "r",
+            Bpf(BpfInlineAsmRegClass::reg) => "r",
+            Bpf(BpfInlineAsmRegClass::wreg) => "w",
+            Avr(AvrInlineAsmRegClass::reg) => "r",
+            Avr(AvrInlineAsmRegClass::reg_upper) => "d",
+            Avr(AvrInlineAsmRegClass::reg_pair) => "r",
+            Avr(AvrInlineAsmRegClass::reg_iw) => "w",
+            Avr(AvrInlineAsmRegClass::reg_ptr) => "e",
+            S390x(S390xInlineAsmRegClass::reg) => "r",
+            S390x(S390xInlineAsmRegClass::reg_addr) => "a",
+            S390x(S390xInlineAsmRegClass::freg) => "f",
+            Msp430(Msp430InlineAsmRegClass::reg) => "r",
+            M68k(M68kInlineAsmRegClass::reg) => "r",
+            M68k(M68kInlineAsmRegClass::reg_addr) => "a",
+            M68k(M68kInlineAsmRegClass::reg_data) => "d",
+            CSKY(CSKYInlineAsmRegClass::reg) => "r",
+            CSKY(CSKYInlineAsmRegClass::freg) => "f",
+            SpirV(SpirVInlineAsmRegClass::reg) => bug!("LLVM backend does not support SPIR-V"),
+            Err => unreachable!(),
         }
         .to_string(),
     }
@@ -732,44 +722,41 @@ fn modifier_to_llvm(
     reg: InlineAsmRegClass,
     modifier: Option<char>,
 ) -> Option<char> {
+    use InlineAsmRegClass::*;
     // The modifiers can be retrieved from
     // https://llvm.org/docs/LangRef.html#asm-template-argument-modifiers
     match reg {
-        InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => modifier,
-        InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg)
-        | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => {
-            if modifier == Some('v') { None } else { modifier }
-        }
-        InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
-            unreachable!("clobber-only")
+        AArch64(AArch64InlineAsmRegClass::reg) => modifier,
+        AArch64(AArch64InlineAsmRegClass::vreg) | AArch64(AArch64InlineAsmRegClass::vreg_low16) => {
+            if modifier == Some('v') {
+                None
+            } else {
+                modifier
+            }
         }
-        InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => None,
-        InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
-        | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => None,
-        InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg)
-        | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16)
-        | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low8) => Some('P'),
-        InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg)
-        | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8)
-        | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => {
+        AArch64(AArch64InlineAsmRegClass::preg) => unreachable!("clobber-only"),
+        Arm(ArmInlineAsmRegClass::reg) => None,
+        Arm(ArmInlineAsmRegClass::sreg) | Arm(ArmInlineAsmRegClass::sreg_low16) => None,
+        Arm(ArmInlineAsmRegClass::dreg)
+        | Arm(ArmInlineAsmRegClass::dreg_low16)
+        | Arm(ArmInlineAsmRegClass::dreg_low8) => Some('P'),
+        Arm(ArmInlineAsmRegClass::qreg)
+        | Arm(ArmInlineAsmRegClass::qreg_low8)
+        | Arm(ArmInlineAsmRegClass::qreg_low4) => {
             if modifier.is_none() {
                 Some('q')
             } else {
                 modifier
             }
         }
-        InlineAsmRegClass::Hexagon(_) => None,
-        InlineAsmRegClass::LoongArch(_) => None,
-        InlineAsmRegClass::Mips(_) => None,
-        InlineAsmRegClass::Nvptx(_) => None,
-        InlineAsmRegClass::PowerPC(_) => None,
-        InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg)
-        | InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => None,
-        InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::vreg) => {
-            unreachable!("clobber-only")
-        }
-        InlineAsmRegClass::X86(X86InlineAsmRegClass::reg)
-        | InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => match modifier {
+        Hexagon(_) => None,
+        LoongArch(_) => None,
+        Mips(_) => None,
+        Nvptx(_) => None,
+        PowerPC(_) => None,
+        RiscV(RiscVInlineAsmRegClass::reg) | RiscV(RiscVInlineAsmRegClass::freg) => None,
+        RiscV(RiscVInlineAsmRegClass::vreg) => unreachable!("clobber-only"),
+        X86(X86InlineAsmRegClass::reg) | X86(X86InlineAsmRegClass::reg_abcd) => match modifier {
             None if arch == InlineAsmArch::X86_64 => Some('q'),
             None => Some('k'),
             Some('l') => Some('b'),
@@ -779,10 +766,10 @@ fn modifier_to_llvm(
             Some('r') => Some('q'),
             _ => unreachable!(),
         },
-        InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => None,
-        InlineAsmRegClass::X86(reg @ X86InlineAsmRegClass::xmm_reg)
-        | InlineAsmRegClass::X86(reg @ X86InlineAsmRegClass::ymm_reg)
-        | InlineAsmRegClass::X86(reg @ X86InlineAsmRegClass::zmm_reg) => match (reg, modifier) {
+        X86(X86InlineAsmRegClass::reg_byte) => None,
+        X86(reg @ X86InlineAsmRegClass::xmm_reg)
+        | X86(reg @ X86InlineAsmRegClass::ymm_reg)
+        | X86(reg @ X86InlineAsmRegClass::zmm_reg) => match (reg, modifier) {
             (X86InlineAsmRegClass::xmm_reg, None) => Some('x'),
             (X86InlineAsmRegClass::ymm_reg, None) => Some('t'),
             (X86InlineAsmRegClass::zmm_reg, None) => Some('g'),
@@ -791,116 +778,97 @@ fn modifier_to_llvm(
             (_, Some('z')) => Some('g'),
             _ => unreachable!(),
         },
-        InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => None,
-        InlineAsmRegClass::X86(
+        X86(X86InlineAsmRegClass::kreg) => None,
+        X86(
             X86InlineAsmRegClass::x87_reg
             | X86InlineAsmRegClass::mmx_reg
             | X86InlineAsmRegClass::kreg0
             | X86InlineAsmRegClass::tmm_reg,
-        ) => {
-            unreachable!("clobber-only")
-        }
-        InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => None,
-        InlineAsmRegClass::Bpf(_) => None,
-        InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair)
-        | InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw)
-        | InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => match modifier {
+        ) => unreachable!("clobber-only"),
+        Wasm(WasmInlineAsmRegClass::local) => None,
+        Bpf(_) => None,
+        Avr(AvrInlineAsmRegClass::reg_pair)
+        | Avr(AvrInlineAsmRegClass::reg_iw)
+        | Avr(AvrInlineAsmRegClass::reg_ptr) => match modifier {
             Some('h') => Some('B'),
             Some('l') => Some('A'),
             _ => None,
         },
-        InlineAsmRegClass::Avr(_) => None,
-        InlineAsmRegClass::S390x(_) => None,
-        InlineAsmRegClass::Msp430(_) => None,
-        InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
-            bug!("LLVM backend does not support SPIR-V")
-        }
-        InlineAsmRegClass::M68k(_) => None,
-        InlineAsmRegClass::CSKY(_) => None,
-        InlineAsmRegClass::Err => unreachable!(),
+        Avr(_) => None,
+        S390x(_) => None,
+        Msp430(_) => None,
+        SpirV(SpirVInlineAsmRegClass::reg) => bug!("LLVM backend does not support SPIR-V"),
+        M68k(_) => None,
+        CSKY(_) => None,
+        Err => unreachable!(),
     }
 }
 
 /// Type to use for outputs that are discarded. It doesn't really matter what
 /// the type is, as long as it is valid for the constraint code.
 fn dummy_output_type<'ll>(cx: &CodegenCx<'ll, '_>, reg: InlineAsmRegClass) -> &'ll Type {
+    use InlineAsmRegClass::*;
     match reg {
-        InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => cx.type_i32(),
-        InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg)
-        | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => {
+        AArch64(AArch64InlineAsmRegClass::reg) => cx.type_i32(),
+        AArch64(AArch64InlineAsmRegClass::vreg) | AArch64(AArch64InlineAsmRegClass::vreg_low16) => {
             cx.type_vector(cx.type_i64(), 2)
         }
-        InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => {
+        AArch64(AArch64InlineAsmRegClass::preg) => unreachable!("clobber-only"),
+        Arm(ArmInlineAsmRegClass::reg) => cx.type_i32(),
+        Arm(ArmInlineAsmRegClass::sreg) | Arm(ArmInlineAsmRegClass::sreg_low16) => cx.type_f32(),
+        Arm(ArmInlineAsmRegClass::dreg)
+        | Arm(ArmInlineAsmRegClass::dreg_low16)
+        | Arm(ArmInlineAsmRegClass::dreg_low8) => cx.type_f64(),
+        Arm(ArmInlineAsmRegClass::qreg)
+        | Arm(ArmInlineAsmRegClass::qreg_low8)
+        | Arm(ArmInlineAsmRegClass::qreg_low4) => cx.type_vector(cx.type_i64(), 2),
+        Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(),
+        LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(),
+        LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(),
+        Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(),
+        Mips(MipsInlineAsmRegClass::freg) => cx.type_f32(),
+        Nvptx(NvptxInlineAsmRegClass::reg16) => cx.type_i16(),
+        Nvptx(NvptxInlineAsmRegClass::reg32) => cx.type_i32(),
+        Nvptx(NvptxInlineAsmRegClass::reg64) => cx.type_i64(),
+        PowerPC(PowerPCInlineAsmRegClass::reg) => cx.type_i32(),
+        PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => cx.type_i32(),
+        PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(),
+        PowerPC(PowerPCInlineAsmRegClass::cr) | PowerPC(PowerPCInlineAsmRegClass::xer) => {
             unreachable!("clobber-only")
         }
-        InlineAsmRegClass::Arm(ArmInlineAsmRegClass::reg) => cx.type_i32(),
-        InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg)
-        | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg_low16) => cx.type_f32(),
-        InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg)
-        | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low16)
-        | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg_low8) => cx.type_f64(),
-        InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg)
-        | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low8)
-        | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => {
-            cx.type_vector(cx.type_i64(), 2)
-        }
-        InlineAsmRegClass::Hexagon(HexagonInlineAsmRegClass::reg) => cx.type_i32(),
-        InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::reg) => cx.type_i32(),
-        InlineAsmRegClass::LoongArch(LoongArchInlineAsmRegClass::freg) => cx.type_f32(),
-        InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(),
-        InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => cx.type_f32(),
-        InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => cx.type_i16(),
-        InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => cx.type_i32(),
-        InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => cx.type_i64(),
-        InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg) => cx.type_i32(),
-        InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::reg_nonzero) => cx.type_i32(),
-        InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::freg) => cx.type_f64(),
-        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) => {
-            unreachable!("clobber-only")
-        }
-        InlineAsmRegClass::X86(X86InlineAsmRegClass::reg)
-        | InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd) => cx.type_i32(),
-        InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_byte) => cx.type_i8(),
-        InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg)
-        | InlineAsmRegClass::X86(X86InlineAsmRegClass::ymm_reg)
-        | InlineAsmRegClass::X86(X86InlineAsmRegClass::zmm_reg) => cx.type_f32(),
-        InlineAsmRegClass::X86(X86InlineAsmRegClass::kreg) => cx.type_i16(),
-        InlineAsmRegClass::X86(
+        RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(),
+        RiscV(RiscVInlineAsmRegClass::freg) => cx.type_f32(),
+        RiscV(RiscVInlineAsmRegClass::vreg) => unreachable!("clobber-only"),
+        X86(X86InlineAsmRegClass::reg) | X86(X86InlineAsmRegClass::reg_abcd) => cx.type_i32(),
+        X86(X86InlineAsmRegClass::reg_byte) => cx.type_i8(),
+        X86(X86InlineAsmRegClass::xmm_reg)
+        | X86(X86InlineAsmRegClass::ymm_reg)
+        | X86(X86InlineAsmRegClass::zmm_reg) => cx.type_f32(),
+        X86(X86InlineAsmRegClass::kreg) => cx.type_i16(),
+        X86(
             X86InlineAsmRegClass::x87_reg
             | X86InlineAsmRegClass::mmx_reg
             | X86InlineAsmRegClass::kreg0
             | X86InlineAsmRegClass::tmm_reg,
-        ) => {
-            unreachable!("clobber-only")
-        }
-        InlineAsmRegClass::Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(),
-        InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::reg) => cx.type_i64(),
-        InlineAsmRegClass::Bpf(BpfInlineAsmRegClass::wreg) => cx.type_i32(),
-        InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg) => cx.type_i8(),
-        InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_upper) => cx.type_i8(),
-        InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_pair) => cx.type_i16(),
-        InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_iw) => cx.type_i16(),
-        InlineAsmRegClass::Avr(AvrInlineAsmRegClass::reg_ptr) => cx.type_i16(),
-        InlineAsmRegClass::S390x(
-            S390xInlineAsmRegClass::reg | S390xInlineAsmRegClass::reg_addr,
-        ) => cx.type_i32(),
-        InlineAsmRegClass::S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(),
-        InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => cx.type_i16(),
-        InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(),
-        InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(),
-        InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg_data) => cx.type_i32(),
-        InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::reg) => cx.type_i32(),
-        InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::freg) => cx.type_f32(),
-        InlineAsmRegClass::SpirV(SpirVInlineAsmRegClass::reg) => {
-            bug!("LLVM backend does not support SPIR-V")
-        }
-        InlineAsmRegClass::Err => unreachable!(),
+        ) => unreachable!("clobber-only"),
+        Wasm(WasmInlineAsmRegClass::local) => cx.type_i32(),
+        Bpf(BpfInlineAsmRegClass::reg) => cx.type_i64(),
+        Bpf(BpfInlineAsmRegClass::wreg) => cx.type_i32(),
+        Avr(AvrInlineAsmRegClass::reg) => cx.type_i8(),
+        Avr(AvrInlineAsmRegClass::reg_upper) => cx.type_i8(),
+        Avr(AvrInlineAsmRegClass::reg_pair) => cx.type_i16(),
+        Avr(AvrInlineAsmRegClass::reg_iw) => cx.type_i16(),
+        Avr(AvrInlineAsmRegClass::reg_ptr) => cx.type_i16(),
+        S390x(S390xInlineAsmRegClass::reg | S390xInlineAsmRegClass::reg_addr) => cx.type_i32(),
+        S390x(S390xInlineAsmRegClass::freg) => cx.type_f64(),
+        Msp430(Msp430InlineAsmRegClass::reg) => cx.type_i16(),
+        M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(),
+        M68k(M68kInlineAsmRegClass::reg_addr) => cx.type_i32(),
+        M68k(M68kInlineAsmRegClass::reg_data) => cx.type_i32(),
+        CSKY(CSKYInlineAsmRegClass::reg) => cx.type_i32(),
+        CSKY(CSKYInlineAsmRegClass::freg) => cx.type_f32(),
+        SpirV(SpirVInlineAsmRegClass::reg) => bug!("LLVM backend does not support SPIR-V"),
+        Err => unreachable!(),
     }
 }
 
@@ -940,9 +908,10 @@ fn llvm_fixup_input<'ll, 'tcx>(
     layout: &TyAndLayout<'tcx>,
     instance: Instance<'_>,
 ) -> &'ll Value {
+    use InlineAsmRegClass::*;
     let dl = &bx.tcx.data_layout;
     match (reg, layout.abi) {
-        (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => {
+        (AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => {
             if let Primitive::Int(Integer::I8, _) = s.primitive() {
                 let vec_ty = bx.cx.type_vector(bx.cx.type_i8(), 8);
                 bx.insert_element(bx.const_undef(vec_ty), value, bx.const_i32(0))
@@ -950,7 +919,7 @@ fn llvm_fixup_input<'ll, 'tcx>(
                 value
             }
         }
-        (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Scalar(s))
+        (AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Scalar(s))
             if s.primitive() != Primitive::Float(Float::F128) =>
         {
             let elem_ty = llvm_asm_scalar_type(bx.cx, s);
@@ -963,26 +932,25 @@ fn llvm_fixup_input<'ll, 'tcx>(
             }
             bx.insert_element(bx.const_undef(vec_ty), value, bx.const_i32(0))
         }
-        (
-            InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16),
-            Abi::Vector { element, count },
-        ) if layout.size.bytes() == 8 => {
+        (AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Vector { element, count })
+            if layout.size.bytes() == 8 =>
+        {
             let elem_ty = llvm_asm_scalar_type(bx.cx, element);
             let vec_ty = bx.cx.type_vector(elem_ty, count);
             let indices: Vec<_> = (0..count * 2).map(|x| bx.const_i32(x as i32)).collect();
             bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices))
         }
-        (InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
+        (X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
             if s.primitive() == Primitive::Float(Float::F64) =>
         {
             bx.bitcast(value, bx.cx.type_i64())
         }
         (
-            InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg | X86InlineAsmRegClass::zmm_reg),
+            X86(X86InlineAsmRegClass::xmm_reg | X86InlineAsmRegClass::zmm_reg),
             Abi::Vector { .. },
         ) if layout.size.bytes() == 64 => bx.bitcast(value, bx.cx.type_vector(bx.cx.type_f64(), 8)),
         (
-            InlineAsmRegClass::X86(
+            X86(
                 X86InlineAsmRegClass::xmm_reg
                 | X86InlineAsmRegClass::ymm_reg
                 | X86InlineAsmRegClass::zmm_reg,
@@ -994,7 +962,7 @@ fn llvm_fixup_input<'ll, 'tcx>(
             bx.bitcast(value, bx.type_vector(bx.type_i32(), 4))
         }
         (
-            InlineAsmRegClass::X86(
+            X86(
                 X86InlineAsmRegClass::xmm_reg
                 | X86InlineAsmRegClass::ymm_reg
                 | X86InlineAsmRegClass::zmm_reg,
@@ -1009,7 +977,7 @@ fn llvm_fixup_input<'ll, 'tcx>(
             bx.bitcast(value, bx.type_vector(bx.type_i16(), 8))
         }
         (
-            InlineAsmRegClass::X86(
+            X86(
                 X86InlineAsmRegClass::xmm_reg
                 | X86InlineAsmRegClass::ymm_reg
                 | X86InlineAsmRegClass::zmm_reg,
@@ -1018,10 +986,7 @@ fn llvm_fixup_input<'ll, 'tcx>(
         ) if element.primitive() == Primitive::Float(Float::F16) => {
             bx.bitcast(value, bx.type_vector(bx.type_i16(), count))
         }
-        (
-            InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16),
-            Abi::Scalar(s),
-        ) => {
+        (Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16), Abi::Scalar(s)) => {
             if let Primitive::Int(Integer::I32, _) = s.primitive() {
                 bx.bitcast(value, bx.cx.type_f32())
             } else {
@@ -1029,7 +994,7 @@ fn llvm_fixup_input<'ll, 'tcx>(
             }
         }
         (
-            InlineAsmRegClass::Arm(
+            Arm(
                 ArmInlineAsmRegClass::dreg
                 | ArmInlineAsmRegClass::dreg_low8
                 | ArmInlineAsmRegClass::dreg_low16,
@@ -1043,7 +1008,7 @@ fn llvm_fixup_input<'ll, 'tcx>(
             }
         }
         (
-            InlineAsmRegClass::Arm(
+            Arm(
                 ArmInlineAsmRegClass::dreg
                 | ArmInlineAsmRegClass::dreg_low8
                 | ArmInlineAsmRegClass::dreg_low16
@@ -1055,7 +1020,7 @@ fn llvm_fixup_input<'ll, 'tcx>(
         ) if element.primitive() == Primitive::Float(Float::F16) => {
             bx.bitcast(value, bx.type_vector(bx.type_i16(), count))
         }
-        (InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => {
+        (Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => {
             match s.primitive() {
                 // MIPS only supports register-length arithmetics.
                 Primitive::Int(Integer::I8 | Integer::I16, _) => bx.zext(value, bx.cx.type_i32()),
@@ -1064,7 +1029,7 @@ fn llvm_fixup_input<'ll, 'tcx>(
                 _ => value,
             }
         }
-        (InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg), Abi::Scalar(s))
+        (RiscV(RiscVInlineAsmRegClass::freg), Abi::Scalar(s))
             if s.primitive() == Primitive::Float(Float::F16)
                 && !any_target_feature_enabled(bx, instance, &[sym::zfhmin, sym::zfh]) =>
         {
@@ -1086,15 +1051,16 @@ fn llvm_fixup_output<'ll, 'tcx>(
     layout: &TyAndLayout<'tcx>,
     instance: Instance<'_>,
 ) -> &'ll Value {
+    use InlineAsmRegClass::*;
     match (reg, layout.abi) {
-        (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => {
+        (AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => {
             if let Primitive::Int(Integer::I8, _) = s.primitive() {
                 bx.extract_element(value, bx.const_i32(0))
             } else {
                 value
             }
         }
-        (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Scalar(s))
+        (AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Scalar(s))
             if s.primitive() != Primitive::Float(Float::F128) =>
         {
             value = bx.extract_element(value, bx.const_i32(0));
@@ -1103,26 +1069,25 @@ fn llvm_fixup_output<'ll, 'tcx>(
             }
             value
         }
-        (
-            InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16),
-            Abi::Vector { element, count },
-        ) if layout.size.bytes() == 8 => {
+        (AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Vector { element, count })
+            if layout.size.bytes() == 8 =>
+        {
             let elem_ty = llvm_asm_scalar_type(bx.cx, element);
             let vec_ty = bx.cx.type_vector(elem_ty, count * 2);
             let indices: Vec<_> = (0..count).map(|x| bx.const_i32(x as i32)).collect();
             bx.shuffle_vector(value, bx.const_undef(vec_ty), bx.const_vector(&indices))
         }
-        (InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
+        (X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
             if s.primitive() == Primitive::Float(Float::F64) =>
         {
             bx.bitcast(value, bx.cx.type_f64())
         }
         (
-            InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg | X86InlineAsmRegClass::zmm_reg),
+            X86(X86InlineAsmRegClass::xmm_reg | X86InlineAsmRegClass::zmm_reg),
             Abi::Vector { .. },
         ) if layout.size.bytes() == 64 => bx.bitcast(value, layout.llvm_type(bx.cx)),
         (
-            InlineAsmRegClass::X86(
+            X86(
                 X86InlineAsmRegClass::xmm_reg
                 | X86InlineAsmRegClass::ymm_reg
                 | X86InlineAsmRegClass::zmm_reg,
@@ -1134,7 +1099,7 @@ fn llvm_fixup_output<'ll, 'tcx>(
             bx.bitcast(value, bx.type_f128())
         }
         (
-            InlineAsmRegClass::X86(
+            X86(
                 X86InlineAsmRegClass::xmm_reg
                 | X86InlineAsmRegClass::ymm_reg
                 | X86InlineAsmRegClass::zmm_reg,
@@ -1145,7 +1110,7 @@ fn llvm_fixup_output<'ll, 'tcx>(
             bx.extract_element(value, bx.const_usize(0))
         }
         (
-            InlineAsmRegClass::X86(
+            X86(
                 X86InlineAsmRegClass::xmm_reg
                 | X86InlineAsmRegClass::ymm_reg
                 | X86InlineAsmRegClass::zmm_reg,
@@ -1154,10 +1119,7 @@ fn llvm_fixup_output<'ll, 'tcx>(
         ) if element.primitive() == Primitive::Float(Float::F16) => {
             bx.bitcast(value, bx.type_vector(bx.type_f16(), count))
         }
-        (
-            InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16),
-            Abi::Scalar(s),
-        ) => {
+        (Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16), Abi::Scalar(s)) => {
             if let Primitive::Int(Integer::I32, _) = s.primitive() {
                 bx.bitcast(value, bx.cx.type_i32())
             } else {
@@ -1165,7 +1127,7 @@ fn llvm_fixup_output<'ll, 'tcx>(
             }
         }
         (
-            InlineAsmRegClass::Arm(
+            Arm(
                 ArmInlineAsmRegClass::dreg
                 | ArmInlineAsmRegClass::dreg_low8
                 | ArmInlineAsmRegClass::dreg_low16,
@@ -1179,7 +1141,7 @@ fn llvm_fixup_output<'ll, 'tcx>(
             }
         }
         (
-            InlineAsmRegClass::Arm(
+            Arm(
                 ArmInlineAsmRegClass::dreg
                 | ArmInlineAsmRegClass::dreg_low8
                 | ArmInlineAsmRegClass::dreg_low16
@@ -1191,7 +1153,7 @@ fn llvm_fixup_output<'ll, 'tcx>(
         ) if element.primitive() == Primitive::Float(Float::F16) => {
             bx.bitcast(value, bx.type_vector(bx.type_f16(), count))
         }
-        (InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => {
+        (Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => {
             match s.primitive() {
                 // MIPS only supports register-length arithmetics.
                 Primitive::Int(Integer::I8, _) => bx.trunc(value, bx.cx.type_i8()),
@@ -1201,7 +1163,7 @@ fn llvm_fixup_output<'ll, 'tcx>(
                 _ => value,
             }
         }
-        (InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg), Abi::Scalar(s))
+        (RiscV(RiscVInlineAsmRegClass::freg), Abi::Scalar(s))
             if s.primitive() == Primitive::Float(Float::F16)
                 && !any_target_feature_enabled(bx, instance, &[sym::zfhmin, sym::zfh]) =>
         {
@@ -1220,39 +1182,39 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
     layout: &TyAndLayout<'tcx>,
     instance: Instance<'_>,
 ) -> &'ll Type {
+    use InlineAsmRegClass::*;
     match (reg, layout.abi) {
-        (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => {
+        (AArch64(AArch64InlineAsmRegClass::vreg), Abi::Scalar(s)) => {
             if let Primitive::Int(Integer::I8, _) = s.primitive() {
                 cx.type_vector(cx.type_i8(), 8)
             } else {
                 layout.llvm_type(cx)
             }
         }
-        (InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Scalar(s))
+        (AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Scalar(s))
             if s.primitive() != Primitive::Float(Float::F128) =>
         {
             let elem_ty = llvm_asm_scalar_type(cx, s);
             let count = 16 / layout.size.bytes();
             cx.type_vector(elem_ty, count)
         }
-        (
-            InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16),
-            Abi::Vector { element, count },
-        ) if layout.size.bytes() == 8 => {
+        (AArch64(AArch64InlineAsmRegClass::vreg_low16), Abi::Vector { element, count })
+            if layout.size.bytes() == 8 =>
+        {
             let elem_ty = llvm_asm_scalar_type(cx, element);
             cx.type_vector(elem_ty, count * 2)
         }
-        (InlineAsmRegClass::X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
+        (X86(X86InlineAsmRegClass::reg_abcd), Abi::Scalar(s))
             if s.primitive() == Primitive::Float(Float::F64) =>
         {
             cx.type_i64()
         }
         (
-            InlineAsmRegClass::X86(X86InlineAsmRegClass::xmm_reg | X86InlineAsmRegClass::zmm_reg),
+            X86(X86InlineAsmRegClass::xmm_reg | X86InlineAsmRegClass::zmm_reg),
             Abi::Vector { .. },
         ) if layout.size.bytes() == 64 => cx.type_vector(cx.type_f64(), 8),
         (
-            InlineAsmRegClass::X86(
+            X86(
                 X86InlineAsmRegClass::xmm_reg
                 | X86InlineAsmRegClass::ymm_reg
                 | X86InlineAsmRegClass::zmm_reg,
@@ -1264,7 +1226,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
             cx.type_vector(cx.type_i32(), 4)
         }
         (
-            InlineAsmRegClass::X86(
+            X86(
                 X86InlineAsmRegClass::xmm_reg
                 | X86InlineAsmRegClass::ymm_reg
                 | X86InlineAsmRegClass::zmm_reg,
@@ -1272,7 +1234,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
             Abi::Scalar(s),
         ) if s.primitive() == Primitive::Float(Float::F16) => cx.type_vector(cx.type_i16(), 8),
         (
-            InlineAsmRegClass::X86(
+            X86(
                 X86InlineAsmRegClass::xmm_reg
                 | X86InlineAsmRegClass::ymm_reg
                 | X86InlineAsmRegClass::zmm_reg,
@@ -1281,10 +1243,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
         ) if element.primitive() == Primitive::Float(Float::F16) => {
             cx.type_vector(cx.type_i16(), count)
         }
-        (
-            InlineAsmRegClass::Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16),
-            Abi::Scalar(s),
-        ) => {
+        (Arm(ArmInlineAsmRegClass::sreg | ArmInlineAsmRegClass::sreg_low16), Abi::Scalar(s)) => {
             if let Primitive::Int(Integer::I32, _) = s.primitive() {
                 cx.type_f32()
             } else {
@@ -1292,7 +1251,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
             }
         }
         (
-            InlineAsmRegClass::Arm(
+            Arm(
                 ArmInlineAsmRegClass::dreg
                 | ArmInlineAsmRegClass::dreg_low8
                 | ArmInlineAsmRegClass::dreg_low16,
@@ -1306,7 +1265,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
             }
         }
         (
-            InlineAsmRegClass::Arm(
+            Arm(
                 ArmInlineAsmRegClass::dreg
                 | ArmInlineAsmRegClass::dreg_low8
                 | ArmInlineAsmRegClass::dreg_low16
@@ -1318,7 +1277,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
         ) if element.primitive() == Primitive::Float(Float::F16) => {
             cx.type_vector(cx.type_i16(), count)
         }
-        (InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => {
+        (Mips(MipsInlineAsmRegClass::reg), Abi::Scalar(s)) => {
             match s.primitive() {
                 // MIPS only supports register-length arithmetics.
                 Primitive::Int(Integer::I8 | Integer::I16, _) => cx.type_i32(),
@@ -1327,7 +1286,7 @@ fn llvm_fixup_output_type<'ll, 'tcx>(
                 _ => layout.llvm_type(cx),
             }
         }
-        (InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg), Abi::Scalar(s))
+        (RiscV(RiscVInlineAsmRegClass::freg), Abi::Scalar(s))
             if s.primitive() == Primitive::Float(Float::F16)
                 && !any_target_feature_enabled(cx, instance, &[sym::zfhmin, sym::zfh]) =>
         {
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index 9d4497d73a8..489259da856 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -403,8 +403,9 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
     if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED) {
         to_add.push(AttributeKind::Naked.create_attr(cx.llcx));
         // HACK(jubilee): "indirect branch tracking" works by attaching prologues to functions.
-        // And it is a module-level attribute, so the alternative is pulling naked functions into new LLVM modules.
-        // Otherwise LLVM's "naked" functions come with endbr prefixes per https://github.com/rust-lang/rust/issues/98768
+        // And it is a module-level attribute, so the alternative is pulling naked functions into
+        // new LLVM modules. Otherwise LLVM's "naked" functions come with endbr prefixes per
+        // https://github.com/rust-lang/rust/issues/98768
         to_add.push(AttributeKind::NoCfCheck.create_attr(cx.llcx));
         if llvm_util::get_version() < (19, 0, 0) {
             // Prior to LLVM 19, branch-target-enforcement was disabled by setting the attribute to
@@ -454,7 +455,8 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
             flags |= AllocKindFlags::Zeroed;
         }
         to_add.push(llvm::CreateAllocKindAttr(cx.llcx, flags));
-        // apply to return place instead of function (unlike all other attributes applied in this function)
+        // apply to return place instead of function (unlike all other attributes applied in this
+        // function)
         let no_alias = AttributeKind::NoAlias.create_attr(cx.llcx);
         attributes::apply_to_llfn(llfn, AttributePlace::ReturnValue, &[no_alias]);
     }
@@ -481,9 +483,6 @@ pub(crate) fn llfn_attrs_from_instance<'ll, 'tcx>(
         let allocated_pointer = AttributeKind::AllocatedPointer.create_attr(cx.llcx);
         attributes::apply_to_llfn(llfn, AttributePlace::Argument(0), &[allocated_pointer]);
     }
-    if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY) {
-        to_add.push(llvm::CreateAttrString(cx.llcx, "cmse_nonsecure_entry"));
-    }
     if let Some(align) = codegen_fn_attrs.alignment {
         llvm::set_alignment(llfn, align);
     }
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index 2ebe0be53aa..66479ad7f34 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -156,15 +156,15 @@ fn get_bitcode_slice_from_object_data<'a>(
     obj: &'a [u8],
     cgcx: &CodegenContext<LlvmCodegenBackend>,
 ) -> Result<&'a [u8], LtoBitcodeFromRlib> {
-    // We're about to assume the data here is an object file with sections, but if it's raw LLVM IR that
-    // won't work. Fortunately, if that's what we have we can just return the object directly, so we sniff
-    // the relevant magic strings here and return.
+    // We're about to assume the data here is an object file with sections, but if it's raw LLVM IR
+    // that won't work. Fortunately, if that's what we have we can just return the object directly,
+    // so we sniff the relevant magic strings here and return.
     if obj.starts_with(b"\xDE\xC0\x17\x0B") || obj.starts_with(b"BC\xC0\xDE") {
         return Ok(obj);
     }
-    // We drop the "__LLVM," prefix here because on Apple platforms there's a notion of "segment name"
-    // which in the public API for sections gets treated as part of the section name, but internally
-    // in MachOObjectFile.cpp gets treated separately.
+    // We drop the "__LLVM," prefix here because on Apple platforms there's a notion of "segment
+    // name" which in the public API for sections gets treated as part of the section name, but
+    // internally in MachOObjectFile.cpp gets treated separately.
     let section_name = bitcode_section_name(cgcx).trim_start_matches("__LLVM,");
     let mut len = 0;
     let data = unsafe {
diff --git a/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs
index 681ac75c877..76529e0c83b 100644
--- a/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs
+++ b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs
@@ -30,7 +30,7 @@ impl OwnedTargetMachine {
         data_sections: bool,
         unique_section_names: bool,
         trap_unreachable: bool,
-        singletree: bool,
+        singlethread: bool,
         verbose_asm: bool,
         emit_stack_size_section: bool,
         relax_elf_relocations: bool,
@@ -62,7 +62,7 @@ impl OwnedTargetMachine {
                 data_sections,
                 unique_section_names,
                 trap_unreachable,
-                singletree,
+                singlethread,
                 verbose_asm,
                 emit_stack_size_section,
                 relax_elf_relocations,
@@ -86,15 +86,17 @@ impl Deref for OwnedTargetMachine {
     type Target = llvm::TargetMachine;
 
     fn deref(&self) -> &Self::Target {
-        // SAFETY: constructing ensures we have a valid pointer created by llvm::LLVMRustCreateTargetMachine
+        // SAFETY: constructing ensures we have a valid pointer created by
+        // llvm::LLVMRustCreateTargetMachine.
         unsafe { self.tm_unique.as_ref() }
     }
 }
 
 impl Drop for OwnedTargetMachine {
     fn drop(&mut self) {
-        // SAFETY: constructing ensures we have a valid pointer created by llvm::LLVMRustCreateTargetMachine
-        // OwnedTargetMachine is not copyable so there is no double free or use after free
+        // SAFETY: constructing ensures we have a valid pointer created by
+        // llvm::LLVMRustCreateTargetMachine OwnedTargetMachine is not copyable so there is no
+        // double free or use after free.
         unsafe {
             llvm::LLVMRustDisposeTargetMachine(self.tm_unique.as_mut());
         }
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index b1b692cc027..d2c4ea8171b 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -38,7 +38,7 @@ use crate::errors::{
     CopyBitcode, FromLlvmDiag, FromLlvmOptimizationDiag, LlvmError, UnknownCompression,
     WithLlvmError, WriteBytecode,
 };
-use crate::llvm::diagnostic::OptimizationDiagnosticKind;
+use crate::llvm::diagnostic::OptimizationDiagnosticKind::*;
 use crate::llvm::{self, DiagnosticInfo, PassManager};
 use crate::type_::Type;
 use crate::{base, common, llvm_util, LlvmCodegenBackend, ModuleLlvm};
@@ -157,7 +157,8 @@ fn to_pass_builder_opt_level(cfg: config::OptLevel) -> llvm::PassBuilderOptLevel
 fn to_llvm_relocation_model(relocation_model: RelocModel) -> llvm::RelocModel {
     match relocation_model {
         RelocModel::Static => llvm::RelocModel::Static,
-        // LLVM doesn't have a PIE relocation model, it represents PIE as PIC with an extra attribute.
+        // LLVM doesn't have a PIE relocation model, it represents PIE as PIC with an extra
+        // attribute.
         RelocModel::Pic | RelocModel::Pie => llvm::RelocModel::PIC,
         RelocModel::DynamicNoPic => llvm::RelocModel::DynamicNoPic,
         RelocModel::Ropi => llvm::RelocModel::ROPI,
@@ -188,8 +189,8 @@ pub(crate) fn target_machine_factory(
     let use_softfp = if sess.target.arch == "arm" && sess.target.abi == "eabihf" {
         sess.opts.cg.soft_float
     } else {
-        // `validate_commandline_args_with_session_available` has already warned about this being ignored.
-        // Let's make sure LLVM doesn't suddenly start using this flag on more targets.
+        // `validate_commandline_args_with_session_available` has already warned about this being
+        // ignored. Let's make sure LLVM doesn't suddenly start using this flag on more targets.
         false
     };
 
@@ -446,13 +447,12 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void
                 column: opt.column,
                 pass_name: &opt.pass_name,
                 kind: match opt.kind {
-                    OptimizationDiagnosticKind::OptimizationRemark => "success",
-                    OptimizationDiagnosticKind::OptimizationMissed
-                    | OptimizationDiagnosticKind::OptimizationFailure => "missed",
-                    OptimizationDiagnosticKind::OptimizationAnalysis
-                    | OptimizationDiagnosticKind::OptimizationAnalysisFPCommute
-                    | OptimizationDiagnosticKind::OptimizationAnalysisAliasing => "analysis",
-                    OptimizationDiagnosticKind::OptimizationRemarkOther => "other",
+                    OptimizationRemark => "success",
+                    OptimizationMissed | OptimizationFailure => "missed",
+                    OptimizationAnalysis
+                    | OptimizationAnalysisFPCommute
+                    | OptimizationAnalysisAliasing => "analysis",
+                    OptimizationRemarkOther => "other",
                 },
                 message: &opt.message,
             });
@@ -945,11 +945,12 @@ fn create_section_with_flags_asm(section_name: &str, section_flags: &str, data:
 }
 
 fn target_is_apple(cgcx: &CodegenContext<LlvmCodegenBackend>) -> bool {
-    cgcx.opts.target_triple.triple().contains("-ios")
-        || cgcx.opts.target_triple.triple().contains("-darwin")
-        || cgcx.opts.target_triple.triple().contains("-tvos")
-        || cgcx.opts.target_triple.triple().contains("-watchos")
-        || cgcx.opts.target_triple.triple().contains("-visionos")
+    let triple = cgcx.opts.target_triple.triple();
+    triple.contains("-ios")
+        || triple.contains("-darwin")
+        || triple.contains("-tvos")
+        || triple.contains("-watchos")
+        || triple.contains("-visionos")
 }
 
 fn target_is_aix(cgcx: &CodegenContext<LlvmCodegenBackend>) -> bool {
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 40783825cae..6ffe90997f5 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -26,13 +26,13 @@ use smallvec::SmallVec;
 use tracing::{debug, instrument};
 
 use crate::abi::FnAbiLlvmExt;
+use crate::attributes;
 use crate::common::Funclet;
 use crate::context::CodegenCx;
 use crate::llvm::{self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, True};
 use crate::type_::Type;
 use crate::type_of::LayoutLlvmExt;
 use crate::value::Value;
-use crate::{attributes, llvm_util};
 
 // All Builders must have an llfn associated with them
 #[must_use]
@@ -93,8 +93,6 @@ impl HasTargetSpec for Builder<'_, '_, '_> {
 }
 
 impl<'tcx> LayoutOfHelpers<'tcx> for Builder<'_, '_, 'tcx> {
-    type LayoutOfResult = TyAndLayout<'tcx>;
-
     #[inline]
     fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
         self.cx.handle_layout_err(err, span, ty)
@@ -102,8 +100,6 @@ impl<'tcx> LayoutOfHelpers<'tcx> for Builder<'_, '_, 'tcx> {
 }
 
 impl<'tcx> FnAbiOfHelpers<'tcx> for Builder<'_, '_, 'tcx> {
-    type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>;
-
     #[inline]
     fn handle_fn_abi_err(
         &self,
@@ -124,11 +120,7 @@ impl<'ll, 'tcx> Deref for Builder<'_, 'll, 'tcx> {
     }
 }
 
-impl<'ll, 'tcx> HasCodegen<'tcx> for Builder<'_, 'll, 'tcx> {
-    type CodegenCx = CodegenCx<'ll, 'tcx>;
-}
-
-macro_rules! builder_methods_for_value_instructions {
+macro_rules! math_builder_methods {
     ($($name:ident($($arg:ident),*) => $llvm_capi:ident),+ $(,)?) => {
         $(fn $name(&mut self, $($arg: &'ll Value),*) -> &'ll Value {
             unsafe {
@@ -138,7 +130,21 @@ macro_rules! builder_methods_for_value_instructions {
     }
 }
 
+macro_rules! set_math_builder_methods {
+    ($($name:ident($($arg:ident),*) => ($llvm_capi:ident, $llvm_set_math:ident)),+ $(,)?) => {
+        $(fn $name(&mut self, $($arg: &'ll Value),*) -> &'ll Value {
+            unsafe {
+                let instr = llvm::$llvm_capi(self.llbuilder, $($arg,)* UNNAMED);
+                llvm::$llvm_set_math(instr);
+                instr
+            }
+        })+
+    }
+}
+
 impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
+    type CodegenCx = CodegenCx<'ll, 'tcx>;
+
     fn build(cx: &'a CodegenCx<'ll, 'tcx>, llbb: &'ll BasicBlock) -> Self {
         let bx = Builder::with_cx(cx);
         unsafe {
@@ -273,7 +279,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         }
     }
 
-    builder_methods_for_value_instructions! {
+    math_builder_methods! {
         add(a, b) => LLVMBuildAdd,
         fadd(a, b) => LLVMBuildFAdd,
         sub(a, b) => LLVMBuildSub,
@@ -305,84 +311,17 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         unchecked_umul(x, y) => LLVMBuildNUWMul,
     }
 
-    fn fadd_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, UNNAMED);
-            llvm::LLVMRustSetFastMath(instr);
-            instr
-        }
-    }
-
-    fn fsub_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, UNNAMED);
-            llvm::LLVMRustSetFastMath(instr);
-            instr
-        }
-    }
-
-    fn fmul_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            let instr = llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, UNNAMED);
-            llvm::LLVMRustSetFastMath(instr);
-            instr
-        }
-    }
-
-    fn fdiv_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            let instr = llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, UNNAMED);
-            llvm::LLVMRustSetFastMath(instr);
-            instr
-        }
-    }
-
-    fn frem_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            let instr = llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, UNNAMED);
-            llvm::LLVMRustSetFastMath(instr);
-            instr
-        }
-    }
-
-    fn fadd_algebraic(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, UNNAMED);
-            llvm::LLVMRustSetAlgebraicMath(instr);
-            instr
-        }
-    }
-
-    fn fsub_algebraic(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, UNNAMED);
-            llvm::LLVMRustSetAlgebraicMath(instr);
-            instr
-        }
-    }
-
-    fn fmul_algebraic(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            let instr = llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, UNNAMED);
-            llvm::LLVMRustSetAlgebraicMath(instr);
-            instr
-        }
-    }
-
-    fn fdiv_algebraic(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            let instr = llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, UNNAMED);
-            llvm::LLVMRustSetAlgebraicMath(instr);
-            instr
-        }
-    }
-
-    fn frem_algebraic(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
-        unsafe {
-            let instr = llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, UNNAMED);
-            llvm::LLVMRustSetAlgebraicMath(instr);
-            instr
-        }
+    set_math_builder_methods! {
+        fadd_fast(x, y) => (LLVMBuildFAdd, LLVMRustSetFastMath),
+        fsub_fast(x, y) => (LLVMBuildFSub, LLVMRustSetFastMath),
+        fmul_fast(x, y) => (LLVMBuildFMul, LLVMRustSetFastMath),
+        fdiv_fast(x, y) => (LLVMBuildFDiv, LLVMRustSetFastMath),
+        frem_fast(x, y) => (LLVMBuildFRem, LLVMRustSetFastMath),
+        fadd_algebraic(x, y) => (LLVMBuildFAdd, LLVMRustSetAlgebraicMath),
+        fsub_algebraic(x, y) => (LLVMBuildFSub, LLVMRustSetAlgebraicMath),
+        fmul_algebraic(x, y) => (LLVMBuildFMul, LLVMRustSetAlgebraicMath),
+        fdiv_algebraic(x, y) => (LLVMBuildFDiv, LLVMRustSetAlgebraicMath),
+        frem_algebraic(x, y) => (LLVMBuildFRem, LLVMRustSetAlgebraicMath),
     }
 
     fn checked_binop(
@@ -465,6 +404,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
             val
         }
     }
+
     fn to_immediate_scalar(&mut self, val: Self::Value, scalar: abi::Scalar) -> Self::Value {
         if scalar.is_bool() {
             return self.trunc(val, self.cx().type_i1());
@@ -733,11 +673,11 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
                 // for performance. LLVM doesn't seem to care about this, and will happily treat
                 // `!nontemporal` stores as-if they were normal stores (for reordering optimizations
                 // etc) even on x86, despite later lowering them to MOVNT which do *not* behave like
-                // regular stores but require special fences.
-                // So we keep a list of architectures where `!nontemporal` is known to be truly just
-                // a hint, and use regular stores everywhere else.
-                // (In the future, we could alternatively ensure that an sfence gets emitted after a sequence of movnt
-                // before any kind of synchronizing operation. But it's not clear how to do that with LLVM.)
+                // regular stores but require special fences. So we keep a list of architectures
+                // where `!nontemporal` is known to be truly just a hint, and use regular stores
+                // everywhere else. (In the future, we could alternatively ensure that an sfence
+                // gets emitted after a sequence of movnt before any kind of synchronizing
+                // operation. But it's not clear how to do that with LLVM.)
                 // For more context, see <https://github.com/rust-lang/rust/issues/114582> and
                 // <https://github.com/llvm/llvm-project/issues/64521>.
                 const WELL_BEHAVED_NONTEMPORAL_ARCHS: &[&str] =
@@ -1166,6 +1106,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
             (val, success)
         }
     }
+
     fn atomic_rmw(
         &mut self,
         op: rustc_codegen_ssa::common::AtomicRmwBinOp,
@@ -1317,15 +1258,9 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
     }
 
     fn apply_attrs_to_cleanup_callsite(&mut self, llret: &'ll Value) {
-        if llvm_util::get_version() < (17, 0, 2) {
-            // Work around https://github.com/llvm/llvm-project/issues/66984.
-            let noinline = llvm::AttributeKind::NoInline.create_attr(self.llcx);
-            attributes::apply_to_callsite(llret, llvm::AttributePlace::Function, &[noinline]);
-        } else {
-            // Cleanup is always the cold path.
-            let cold_inline = llvm::AttributeKind::Cold.create_attr(self.llcx);
-            attributes::apply_to_callsite(llret, llvm::AttributePlace::Function, &[cold_inline]);
-        }
+        // Cleanup is always the cold path.
+        let cold_inline = llvm::AttributeKind::Cold.create_attr(self.llcx);
+        attributes::apply_to_callsite(llret, llvm::AttributePlace::Function, &[cold_inline]);
     }
 }
 
@@ -1767,8 +1702,6 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
     ) {
         debug!("mcdc_parameters() with args ({:?}, {:?}, {:?})", fn_name, hash, bitmap_bytes);
 
-        assert!(llvm_util::get_version() >= (18, 0, 0), "MCDC intrinsics require LLVM 18 or later");
-
         let llfn = unsafe { llvm::LLVMRustGetInstrProfMCDCParametersIntrinsic(self.cx().llmod) };
         let llty = self.cx.type_func(
             &[self.cx.type_ptr(), self.cx.type_i64(), self.cx.type_i32()],
@@ -1802,7 +1735,6 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
             "mcdc_tvbitmap_update() with args ({:?}, {:?}, {:?}, {:?}, {:?})",
             fn_name, hash, bitmap_bytes, bitmap_index, mcdc_temp
         );
-        assert!(llvm_util::get_version() >= (18, 0, 0), "MCDC intrinsics require LLVM 18 or later");
 
         let llfn =
             unsafe { llvm::LLVMRustGetInstrProfMCDCTVBitmapUpdateIntrinsic(self.cx().llmod) };
@@ -1844,7 +1776,6 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> {
             "mcdc_condbitmap_update() with args ({:?}, {:?}, {:?}, {:?}, {:?})",
             fn_name, hash, cond_loc, mcdc_temp, bool_value
         );
-        assert!(llvm_util::get_version() >= (18, 0, 0), "MCDC intrinsics require LLVM 18 or later");
         let llfn = unsafe { llvm::LLVMRustGetInstrProfMCDCCondBitmapIntrinsic(self.cx().llmod) };
         let llty = self.cx.type_func(
             &[
diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs
index 949fd1bc124..206a7069792 100644
--- a/compiler/rustc_codegen_llvm/src/callee.rs
+++ b/compiler/rustc_codegen_llvm/src/callee.rs
@@ -15,11 +15,6 @@ use crate::value::Value;
 
 /// Codegens a reference to a fn/method item, monomorphizing and
 /// inlining as it goes.
-///
-/// # Parameters
-///
-/// - `cx`: the crate context
-/// - `instance`: the instance to be instantiated
 pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'tcx>) -> &'ll Value {
     let tcx = cx.tcx();
 
@@ -106,62 +101,42 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t
             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.
-
+            let is_hidden = if is_generic {
+                // This is a monomorphization of a generic function.
+                if !cx.tcx.sess.opts.share_generics() {
+                    // When not sharing generics, all instances are in the same
+                    // crate and have hidden visibility.
+                    true
+                } else {
                     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)
+                        // This is a monomorphization of a generic function
+                        // defined in the current crate. It is hidden if:
+                        // - the definition is unreachable for downstream
+                        //   crates, or
+                        // - the current crate does not re-export generics
+                        //   (because the crate is a C library or executable)
+                        cx.tcx.is_unreachable_local_definition(instance_def_id)
                             || !cx.tcx.local_crate_exports_generics()
-                        {
-                            llvm::LLVMRustSetVisibility(llfn, llvm::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 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() {
-                                llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
-                            }
-                        }
+                        // defined in an upstream crate. It is hidden if:
+                        // - it is instantiated in this crate, and
+                        // - the current crate does not re-export generics
+                        instance.upstream_monomorphization(tcx).is_none()
+                            && !cx.tcx.local_crate_exports_generics()
                     }
-                } else {
-                    // When not sharing generics, all instances are in the same
-                    // crate and have hidden visibility
-                    llvm::LLVMRustSetVisibility(llfn, llvm::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) {
-                            llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
-                        }
-                    } else {
-                        // This is a function from an upstream crate that has
-                        // been instantiated here. These are always hidden.
-                        llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
-                    }
-                }
+                // This is a non-generic function. It is hidden if:
+                // - it is instantiated in the local crate, and
+                //   - it is defined an upstream crate (non-local), or
+                //   - it is not reachable
+                cx.tcx.is_codegened_item(instance_def_id)
+                    && (!instance_def_id.is_local()
+                        || !cx.tcx.is_reachable_non_generic(instance_def_id))
+            };
+            if is_hidden {
+                llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden);
             }
 
             // MinGW: For backward compatibility we rely on the linker to decide whether it
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index ef6560ecbe5..508c2d1a820 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -113,7 +113,7 @@ impl<'ll> CodegenCx<'ll, '_> {
     }
 }
 
-impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
+impl<'ll, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
     fn const_null(&self, t: &'ll Type) -> &'ll Value {
         unsafe { llvm::LLVMConstNull(t) }
     }
@@ -126,25 +126,14 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         unsafe { llvm::LLVMGetPoison(t) }
     }
 
-    fn const_int(&self, t: &'ll Type, i: i64) -> &'ll Value {
-        unsafe { llvm::LLVMConstInt(t, i as u64, True) }
-    }
-
-    fn const_uint(&self, t: &'ll Type, i: u64) -> &'ll Value {
-        unsafe { llvm::LLVMConstInt(t, i, False) }
-    }
-
-    fn const_uint_big(&self, t: &'ll Type, u: u128) -> &'ll Value {
-        unsafe {
-            let words = [u as u64, (u >> 64) as u64];
-            llvm::LLVMConstIntOfArbitraryPrecision(t, 2, words.as_ptr())
-        }
-    }
-
     fn const_bool(&self, val: bool) -> &'ll Value {
         self.const_uint(self.type_i1(), val as u64)
     }
 
+    fn const_i8(&self, i: i8) -> &'ll Value {
+        self.const_int(self.type_i8(), i as i64)
+    }
+
     fn const_i16(&self, i: i16) -> &'ll Value {
         self.const_int(self.type_i16(), i as i64)
     }
@@ -153,8 +142,12 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         self.const_int(self.type_i32(), i as i64)
     }
 
-    fn const_i8(&self, i: i8) -> &'ll Value {
-        self.const_int(self.type_i8(), i as i64)
+    fn const_int(&self, t: &'ll Type, i: i64) -> &'ll Value {
+        unsafe { llvm::LLVMConstInt(t, i as u64, True) }
+    }
+
+    fn const_u8(&self, i: u8) -> &'ll Value {
+        self.const_uint(self.type_i8(), i as u64)
     }
 
     fn const_u32(&self, i: u32) -> &'ll Value {
@@ -179,8 +172,15 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         self.const_uint(self.isize_ty, i)
     }
 
-    fn const_u8(&self, i: u8) -> &'ll Value {
-        self.const_uint(self.type_i8(), i as u64)
+    fn const_uint(&self, t: &'ll Type, i: u64) -> &'ll Value {
+        unsafe { llvm::LLVMConstInt(t, i, False) }
+    }
+
+    fn const_uint_big(&self, t: &'ll Type, u: u128) -> &'ll Value {
+        unsafe {
+            let words = [u as u64, (u >> 64) as u64];
+            llvm::LLVMConstIntOfArbitraryPrecision(t, 2, words.as_ptr())
+        }
     }
 
     fn const_real(&self, t: &'ll Type, val: f64) -> &'ll Value {
diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs
index d60122fccee..33d3b5d4474 100644
--- a/compiler/rustc_codegen_llvm/src/consts.rs
+++ b/compiler/rustc_codegen_llvm/src/consts.rs
@@ -73,8 +73,8 @@ pub(crate) fn const_alloc_to_llvm<'ll>(
 
         // Generating partially-uninit consts is limited to small numbers of chunks,
         // to avoid the cost of generating large complex const expressions.
-        // For example, `[(u32, u8); 1024 * 1024]` contains uninit padding in each element,
-        // and would result in `{ [5 x i8] zeroinitializer, [3 x i8] undef, ...repeat 1M times... }`.
+        // For example, `[(u32, u8); 1024 * 1024]` contains uninit padding in each element, and
+        // would result in `{ [5 x i8] zeroinitializer, [3 x i8] undef, ...repeat 1M times... }`.
         let max = cx.sess().opts.unstable_opts.uninit_const_chunk_threshold;
         let allow_uninit_chunks = chunks.clone().take(max.saturating_add(1)).count() <= max;
 
@@ -249,8 +249,8 @@ impl<'ll> CodegenCx<'ll, '_> {
         trace!(?instance);
 
         let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() };
-        // Nested statics do not have a type, so pick a dummy type and let `codegen_static` figure out
-        // the llvm type from the actual evaluated initializer.
+        // Nested statics do not have a type, so pick a dummy type and let `codegen_static` figure
+        // out the llvm type from the actual evaluated initializer.
         let llty = if nested {
             self.type_i8()
         } else {
@@ -262,7 +262,7 @@ impl<'ll> CodegenCx<'ll, '_> {
     }
 
     #[instrument(level = "debug", skip(self, llty))]
-    pub(crate) fn get_static_inner(&self, def_id: DefId, llty: &'ll Type) -> &'ll Value {
+    fn get_static_inner(&self, def_id: DefId, llty: &'ll Type) -> &'ll Value {
         let instance = Instance::mono(self.tcx, def_id);
         if let Some(&g) = self.instances.borrow().get(&instance) {
             trace!("used cached value");
@@ -320,15 +320,16 @@ impl<'ll> CodegenCx<'ll, '_> {
         }
 
         if !def_id.is_local() {
-            let needs_dll_storage_attr = self.use_dll_storage_attrs && !self.tcx.is_foreign_item(def_id) &&
+            let needs_dll_storage_attr = self.use_dll_storage_attrs
+                && !self.tcx.is_foreign_item(def_id)
                 // Local definitions can never be imported, so we must not apply
                 // the DLLImport annotation.
-                !dso_local &&
+                && !dso_local
                 // ThinLTO can't handle this workaround in all cases, so we don't
                 // emit the attrs. Instead we make them unnecessary by disallowing
                 // dynamic linking when linker plugin based LTO is enabled.
-                !self.tcx.sess.opts.cg.linker_plugin_lto.enabled() &&
-                self.tcx.sess.lto() != Lto::Thin;
+                && !self.tcx.sess.opts.cg.linker_plugin_lto.enabled()
+                && self.tcx.sess.lto() != Lto::Thin;
 
             // If this assertion triggers, there's something wrong with commandline
             // argument validation.
@@ -442,58 +443,6 @@ impl<'ll> CodegenCx<'ll, '_> {
 
             if attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) {
                 llvm::set_thread_local_mode(g, self.tls_model);
-
-                // Do not allow LLVM to change the alignment of a TLS on macOS.
-                //
-                // By default a global's alignment can be freely increased.
-                // This allows LLVM to generate more performant instructions
-                // e.g., using load-aligned into a SIMD register.
-                //
-                // However, on macOS 10.10 or below, the dynamic linker does not
-                // respect any alignment given on the TLS (radar 24221680).
-                // This will violate the alignment assumption, and causing segfault at runtime.
-                //
-                // This bug is very easy to trigger. In `println!` and `panic!`,
-                // the `LOCAL_STDOUT`/`LOCAL_STDERR` handles are stored in a TLS,
-                // which the values would be `mem::replace`d on initialization.
-                // The implementation of `mem::replace` will use SIMD
-                // whenever the size is 32 bytes or higher. LLVM notices SIMD is used
-                // and tries to align `LOCAL_STDOUT`/`LOCAL_STDERR` to a 32-byte boundary,
-                // which macOS's dyld disregarded and causing crashes
-                // (see issues #51794, #51758, #50867, #48866 and #44056).
-                //
-                // To workaround the bug, we trick LLVM into not increasing
-                // the global's alignment by explicitly assigning a section to it
-                // (equivalent to automatically generating a `#[link_section]` attribute).
-                // See the comment in the `GlobalValue::canIncreaseAlignment()` function
-                // of `lib/IR/Globals.cpp` for why this works.
-                //
-                // When the alignment is not increased, the optimized `mem::replace`
-                // will use load-unaligned instructions instead, and thus avoiding the crash.
-                //
-                // We could remove this hack whenever we decide to drop macOS 10.10 support.
-                if self.tcx.sess.target.is_like_osx {
-                    // The `inspect` method is okay here because we checked for provenance, and
-                    // because we are doing this access to inspect the final interpreter state
-                    // (not as part of the interpreter execution).
-                    //
-                    // FIXME: This check requires that the (arbitrary) value of undefined bytes
-                    // happens to be zero. Instead, we should only check the value of defined bytes
-                    // and set all undefined bytes to zero if this allocation is headed for the
-                    // BSS.
-                    let all_bytes_are_zero = alloc.provenance().ptrs().is_empty()
-                        && alloc
-                            .inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len())
-                            .iter()
-                            .all(|&byte| byte == 0);
-
-                    let sect_name = if all_bytes_are_zero {
-                        c"__DATA,__thread_bss"
-                    } else {
-                        c"__DATA,__thread_data"
-                    };
-                    llvm::LLVMSetSection(g, sect_name.as_ptr());
-                }
             }
 
             // Wasm statics with custom link sections get special treatment as they
@@ -551,8 +500,8 @@ impl<'ll> CodegenCx<'ll, '_> {
                 // `#[used(compiler)]` is explicitly requested. This is to avoid similar breakage
                 // on other targets, in particular MachO targets have *their* static constructor
                 // lists broken if `llvm.compiler.used` is emitted rather than `llvm.used`. However,
-                // that check happens when assigning the `CodegenFnAttrFlags` in `rustc_hir_analysis`,
-                // so we don't need to take care of it here.
+                // that check happens when assigning the `CodegenFnAttrFlags` in
+                // `rustc_hir_analysis`, so we don't need to take care of it here.
                 self.add_compiler_used_global(g);
             }
             if attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) {
@@ -565,7 +514,7 @@ impl<'ll> CodegenCx<'ll, '_> {
     }
 }
 
-impl<'ll> StaticMethods for CodegenCx<'ll, '_> {
+impl<'ll> StaticCodegenMethods for CodegenCx<'ll, '_> {
     fn static_addr_of(&self, cv: &'ll Value, align: Align, kind: Option<&str>) -> &'ll Value {
         if let Some(&gv) = self.const_globals.borrow().get(&cv) {
             unsafe {
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 73c2c15717f..1d5580fdd07 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -15,7 +15,6 @@ use rustc_middle::middle::codegen_fn_attrs::PatchableFunctionEntry;
 use rustc_middle::mir::mono::CodegenUnit;
 use rustc_middle::ty::layout::{
     FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasParamEnv, LayoutError, LayoutOfHelpers,
-    TyAndLayout,
 };
 use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
@@ -25,7 +24,6 @@ use rustc_session::config::{
 use rustc_session::Session;
 use rustc_span::source_map::Spanned;
 use rustc_span::{Span, DUMMY_SP};
-use rustc_target::abi::call::FnAbi;
 use rustc_target::abi::{HasDataLayout, TargetDataLayout, VariantIdx};
 use rustc_target::spec::{HasTargetSpec, RelocModel, SmallDataThresholdSupport, Target, TlsModel};
 use smallvec::SmallVec;
@@ -37,8 +35,8 @@ use crate::type_::Type;
 use crate::value::Value;
 use crate::{attributes, coverageinfo, debuginfo, llvm, llvm_util};
 
-/// There is one `CodegenCx` per compilation unit. Each one has its own LLVM
-/// `llvm::Context` so that several compilation units may be optimized in parallel.
+/// There is one `CodegenCx` per codegen unit. Each one has its own LLVM
+/// `llvm::Context` so that several codegen units may be processed in parallel.
 /// All other LLVM data structures in the `CodegenCx` are tied to that `llvm::Context`.
 pub(crate) struct CodegenCx<'ll, 'tcx> {
     pub tcx: TyCtxt<'tcx>,
@@ -122,14 +120,6 @@ pub(crate) unsafe fn create_module<'ll>(
 
     let mut target_data_layout = sess.target.data_layout.to_string();
     let llvm_version = llvm_util::get_version();
-    if llvm_version < (18, 0, 0) {
-        if sess.target.arch == "x86" || sess.target.arch == "x86_64" {
-            // LLVM 18 adjusts i128 to be 128-bit aligned on x86 variants.
-            // Earlier LLVMs leave this as default alignment, so remove it.
-            // See https://reviews.llvm.org/D86310
-            target_data_layout = target_data_layout.replace("-i128:128", "");
-        }
-    }
 
     if llvm_version < (19, 0, 0) {
         if sess.target.arch == "aarch64" || sess.target.arch.starts_with("arm64") {
@@ -241,7 +231,8 @@ pub(crate) unsafe fn create_module<'ll>(
         }
     }
 
-    // Enable LTO unit splitting if specified or if CFI is enabled. (See https://reviews.llvm.org/D53891.)
+    // Enable LTO unit splitting if specified or if CFI is enabled. (See
+    // https://reviews.llvm.org/D53891.)
     if sess.is_split_lto_unit_enabled() || sess.is_sanitizer_cfi_enabled() {
         let enable_split_lto_unit = c"EnableSplitLTOUnit".as_ptr();
         unsafe {
@@ -598,7 +589,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
     }
 }
 
-impl<'ll, 'tcx> MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
+impl<'ll, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
     fn vtables(
         &self,
     ) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), &'ll Value>>
@@ -1158,8 +1149,6 @@ impl<'tcx, 'll> HasParamEnv<'tcx> for CodegenCx<'ll, 'tcx> {
 }
 
 impl<'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'_, 'tcx> {
-    type LayoutOfResult = TyAndLayout<'tcx>;
-
     #[inline]
     fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
         if let LayoutError::SizeOverflow(_) | LayoutError::ReferencesError(_) = err {
@@ -1171,8 +1160,6 @@ impl<'tcx> LayoutOfHelpers<'tcx> for CodegenCx<'_, 'tcx> {
 }
 
 impl<'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'_, 'tcx> {
-    type FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>;
-
     #[inline]
     fn handle_fn_abi_err(
         &self,
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs
index d7a4f105f3c..77821ca89bc 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs
@@ -121,7 +121,8 @@ mod mcdc {
         num_conditions: u16,
     }
 
-    // ConditionId in llvm is `unsigned int` at 18 while `int16_t` at [19](https://github.com/llvm/llvm-project/pull/81257)
+    // ConditionId in llvm is `unsigned int` at 18 while `int16_t` at
+    // [19](https://github.com/llvm/llvm-project/pull/81257).
     type LLVMConditionId = i16;
 
     /// Must match the layout of `LLVMRustMCDCBranchParameters`.
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
index b5acfabfde2..a9f65ee8a93 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs
@@ -1,5 +1,5 @@
 use itertools::Itertools as _;
-use rustc_codegen_ssa::traits::{BaseTypeMethods, ConstMethods};
+use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, ConstCodegenMethods};
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_index::IndexVec;
diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
index 69babc7c9cf..c9d2a1c9b88 100644
--- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs
@@ -2,8 +2,8 @@ use std::cell::RefCell;
 
 use libc::c_uint;
 use rustc_codegen_ssa::traits::{
-    BaseTypeMethods, BuilderMethods, ConstMethods, CoverageInfoBuilderMethods, MiscMethods,
-    StaticMethods,
+    BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods, CoverageInfoBuilderMethods,
+    MiscCodegenMethods, StaticCodegenMethods,
 };
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_llvm::RustString;
@@ -48,11 +48,10 @@ impl<'ll, 'tcx> CrateCoverageContext<'ll, 'tcx> {
         self.function_coverage_map.replace(FxIndexMap::default())
     }
 
-    /// LLVM use a temp value to record evaluated mcdc test vector of each decision, which is called condition bitmap.
-    /// In order to handle nested decisions, several condition bitmaps can be
-    /// allocated for a function body.
-    /// These values are named `mcdc.addr.{i}` and are a 32-bit integers.
-    /// They respectively hold the condition bitmaps for decisions with a depth of `i`.
+    /// LLVM use a temp value to record evaluated mcdc test vector of each decision, which is
+    /// called condition bitmap. In order to handle nested decisions, several condition bitmaps can
+    /// be allocated for a function body. These values are named `mcdc.addr.{i}` and are a 32-bit
+    /// integers. They respectively hold the condition bitmaps for decisions with a depth of `i`.
     fn try_get_mcdc_condition_bitmap(
         &self,
         instance: &Instance<'tcx>,
@@ -157,8 +156,8 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> {
             ),
             CoverageKind::CounterIncrement { id } => {
                 func_coverage.mark_counter_id_seen(id);
-                // We need to explicitly drop the `RefMut` before calling into `instrprof_increment`,
-                // as that needs an exclusive borrow.
+                // We need to explicitly drop the `RefMut` before calling into
+                // `instrprof_increment`, as that needs an exclusive borrow.
                 drop(coverage_map);
 
                 // The number of counters passed to `llvm.instrprof.increment` might
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
index dc228e94811..f93d3e40b20 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
@@ -44,7 +44,8 @@ pub(crate) fn get_or_insert_gdb_debug_scripts_section_global<'ll>(
         // Add the pretty printers for the standard library first.
         section_contents.extend_from_slice(b"\x01gdb_load_rust_pretty_printers.py\0");
 
-        // Next, add the pretty printers that were specified via the `#[debugger_visualizer]` attribute.
+        // Next, add the pretty printers that were specified via the `#[debugger_visualizer]`
+        // attribute.
         let visualizers = collect_debugger_visualizers_transitive(
             cx.tcx,
             DebuggerVisualizerType::GdbPrettyPrinter,
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index d231b103964..57e396415cc 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -125,7 +125,9 @@ fn build_fixed_size_array_di_node<'ll, 'tcx>(
 
     let (size, align) = cx.size_and_align_of(array_type);
 
-    let upper_bound = len.eval_target_usize(cx.tcx, ty::ParamEnv::reveal_all()) as c_longlong;
+    let upper_bound = len
+        .try_to_target_usize(cx.tcx)
+        .expect("expected monomorphic const in codegen") as c_longlong;
 
     let subrange =
         unsafe { Some(llvm::LLVMRustDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)) };
@@ -216,8 +218,9 @@ fn build_pointer_or_reference_di_node<'ll, 'tcx>(
                     //        need to make sure that we don't break existing debuginfo consumers
                     //        by doing that (at least not without a warning period).
                     let layout_type = if ptr_type.is_box() {
-                        // The assertion at the start of this function ensures we have a ZST allocator.
-                        // We'll make debuginfo "skip" all ZST allocators, not just the default allocator.
+                        // The assertion at the start of this function ensures we have a ZST
+                        // allocator. We'll make debuginfo "skip" all ZST allocators, not just the
+                        // default allocator.
                         Ty::new_mut_ptr(cx.tcx, pointee_type)
                     } else {
                         ptr_type
@@ -280,8 +283,7 @@ fn build_subroutine_type_di_node<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
     unique_type_id: UniqueTypeId<'tcx>,
 ) -> DINodeCreationResult<'ll> {
-    // It's possible to create a self-referential
-    // type in Rust by using 'impl trait':
+    // It's possible to create a self-referential type in Rust by using 'impl trait':
     //
     // fn foo() -> impl Copy { foo }
     //
@@ -573,14 +575,14 @@ pub(crate) fn file_metadata<'ll>(cx: &CodegenCx<'ll, '_>, source_file: &SourceFi
                     {
                         // If the compiler's working directory (which also is the DW_AT_comp_dir of
                         // the compilation unit) is a prefix of the path we are about to emit, then
-                        // only emit the part relative to the working directory.
-                        // Because of path remapping we sometimes see strange things here: `abs_path`
-                        // might actually look like a relative path
-                        // (e.g. `<crate-name-and-version>/src/lib.rs`), so if we emit it without
-                        // taking the working directory into account, downstream tooling will
-                        // interpret it as `<working-directory>/<crate-name-and-version>/src/lib.rs`,
-                        // which makes no sense. Usually in such cases the working directory will also
-                        // be remapped to `<crate-name-and-version>` or some other prefix of the path
+                        // only emit the part relative to the working directory. Because of path
+                        // remapping we sometimes see strange things here: `abs_path` might
+                        // actually look like a relative path (e.g.
+                        // `<crate-name-and-version>/src/lib.rs`), so if we emit it without taking
+                        // the working directory into account, downstream tooling will interpret it
+                        // as `<working-directory>/<crate-name-and-version>/src/lib.rs`, which
+                        // makes no sense. Usually in such cases the working directory will also be
+                        // remapped to `<crate-name-and-version>` or some other prefix of the path
                         // we are remapping, so we end up with
                         // `<crate-name-and-version>/<crate-name-and-version>/src/lib.rs`.
                         // By moving the working directory portion into the `directory` part of the
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
index 181022087f3..8a132f89aa3 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/cpp_like.rs
@@ -3,7 +3,7 @@ use std::borrow::Cow;
 use libc::c_uint;
 use rustc_codegen_ssa::debuginfo::type_names::compute_debuginfo_type_name;
 use rustc_codegen_ssa::debuginfo::{tag_base_type, wants_c_like_enum_debuginfo};
-use rustc_codegen_ssa::traits::ConstMethods;
+use rustc_codegen_ssa::traits::ConstCodegenMethods;
 use rustc_index::IndexVec;
 use rustc_middle::bug;
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
index 238fbad4dfd..0b3140cc91f 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/native.rs
@@ -3,7 +3,7 @@ use std::borrow::Cow;
 use libc::c_uint;
 use rustc_codegen_ssa::debuginfo::type_names::compute_debuginfo_type_name;
 use rustc_codegen_ssa::debuginfo::{tag_base_type, wants_c_like_enum_debuginfo};
-use rustc_codegen_ssa::traits::ConstMethods;
+use rustc_codegen_ssa::traits::ConstCodegenMethods;
 use rustc_middle::bug;
 use rustc_middle::ty::layout::{LayoutOf, TyAndLayout};
 use rustc_middle::ty::{self};
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index 842212ac05d..920c9e06be4 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -286,7 +286,7 @@ impl CodegenCx<'_, '_> {
     }
 }
 
-impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
+impl<'ll, 'tcx> DebugInfoCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
     fn create_function_debug_context(
         &self,
         instance: Instance<'tcx>,
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
index 83d7a82dadc..9674b1eb848 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
@@ -13,8 +13,7 @@ pub(crate) fn mangled_name_of_instance<'a, 'tcx>(
     cx: &CodegenCx<'a, 'tcx>,
     instance: Instance<'tcx>,
 ) -> ty::SymbolName<'tcx> {
-    let tcx = cx.tcx;
-    tcx.symbol_name(instance)
+    cx.tcx.symbol_name(instance)
 }
 
 pub(crate) fn item_namespace<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'ll DIScope {
diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs
index 4e4500b6373..b0b29ca1280 100644
--- a/compiler/rustc_codegen_llvm/src/declare.rs
+++ b/compiler/rustc_codegen_llvm/src/declare.rs
@@ -12,7 +12,7 @@
 //! * When in doubt, define.
 
 use itertools::Itertools;
-use rustc_codegen_ssa::traits::TypeMembershipMethods;
+use rustc_codegen_ssa::traits::TypeMembershipCodegenMethods;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_middle::ty::{Instance, Ty};
 use rustc_sanitizers::{cfi, kcfi};
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index 15c519dfcb4..307fb9c35b7 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -148,7 +148,7 @@ fn get_simple_intrinsic<'ll>(
     Some(cx.get_intrinsic(llvm_name))
 }
 
-impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
+impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
     fn codegen_intrinsic_call(
         &mut self,
         instance: ty::Instance<'tcx>,
@@ -404,7 +404,8 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
                             let llvm_name =
                                 &format!("llvm.fsh{}.i{}", if is_left { 'l' } else { 'r' }, width);
 
-                            // llvm expects shift to be the same type as the values, but rust always uses `u32`
+                            // llvm expects shift to be the same type as the values, but rust
+                            // always uses `u32`.
                             let raw_shift = self.intcast(raw_shift, self.val_ty(val), false);
 
                             self.call_intrinsic(llvm_name, &[val, val, raw_shift])
@@ -573,8 +574,8 @@ impl<'ll, 'tcx> IntrinsicCallMethods<'tcx> for Builder<'_, 'll, 'tcx> {
                     span,
                 ) {
                     Ok(llval) => llval,
-                    // If there was an error, just skip this invocation... we'll abort compilation anyway,
-                    // but we can keep codegen'ing to find more errors.
+                    // If there was an error, just skip this invocation... we'll abort compilation
+                    // anyway, but we can keep codegen'ing to find more errors.
                     Err(()) => return Ok(()),
                 }
             }
@@ -1847,7 +1848,8 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
         require!(
             matches!(
                 *pointer_ty.kind(),
-                ty::RawPtr(p_ty, p_mutbl) if p_ty == values_elem && p_ty.kind() == values_elem.kind() && p_mutbl.is_mut()
+                ty::RawPtr(p_ty, p_mutbl)
+                    if p_ty == values_elem && p_ty.kind() == values_elem.kind() && p_mutbl.is_mut()
             ),
             InvalidMonomorphization::ExpectedElementType {
                 span,
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index e84ab0aa538..a588f11b623 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -220,17 +220,18 @@ pub enum IntPredicate {
 
 impl IntPredicate {
     pub fn from_generic(intpre: rustc_codegen_ssa::common::IntPredicate) -> Self {
+        use rustc_codegen_ssa::common::IntPredicate as Common;
         match intpre {
-            rustc_codegen_ssa::common::IntPredicate::IntEQ => IntPredicate::IntEQ,
-            rustc_codegen_ssa::common::IntPredicate::IntNE => IntPredicate::IntNE,
-            rustc_codegen_ssa::common::IntPredicate::IntUGT => IntPredicate::IntUGT,
-            rustc_codegen_ssa::common::IntPredicate::IntUGE => IntPredicate::IntUGE,
-            rustc_codegen_ssa::common::IntPredicate::IntULT => IntPredicate::IntULT,
-            rustc_codegen_ssa::common::IntPredicate::IntULE => IntPredicate::IntULE,
-            rustc_codegen_ssa::common::IntPredicate::IntSGT => IntPredicate::IntSGT,
-            rustc_codegen_ssa::common::IntPredicate::IntSGE => IntPredicate::IntSGE,
-            rustc_codegen_ssa::common::IntPredicate::IntSLT => IntPredicate::IntSLT,
-            rustc_codegen_ssa::common::IntPredicate::IntSLE => IntPredicate::IntSLE,
+            Common::IntEQ => Self::IntEQ,
+            Common::IntNE => Self::IntNE,
+            Common::IntUGT => Self::IntUGT,
+            Common::IntUGE => Self::IntUGE,
+            Common::IntULT => Self::IntULT,
+            Common::IntULE => Self::IntULE,
+            Common::IntSGT => Self::IntSGT,
+            Common::IntSGE => Self::IntSGE,
+            Common::IntSLT => Self::IntSLT,
+            Common::IntSLE => Self::IntSLE,
         }
     }
 }
@@ -259,27 +260,24 @@ pub enum RealPredicate {
 
 impl RealPredicate {
     pub fn from_generic(realp: rustc_codegen_ssa::common::RealPredicate) -> Self {
+        use rustc_codegen_ssa::common::RealPredicate as Common;
         match realp {
-            rustc_codegen_ssa::common::RealPredicate::RealPredicateFalse => {
-                RealPredicate::RealPredicateFalse
-            }
-            rustc_codegen_ssa::common::RealPredicate::RealOEQ => RealPredicate::RealOEQ,
-            rustc_codegen_ssa::common::RealPredicate::RealOGT => RealPredicate::RealOGT,
-            rustc_codegen_ssa::common::RealPredicate::RealOGE => RealPredicate::RealOGE,
-            rustc_codegen_ssa::common::RealPredicate::RealOLT => RealPredicate::RealOLT,
-            rustc_codegen_ssa::common::RealPredicate::RealOLE => RealPredicate::RealOLE,
-            rustc_codegen_ssa::common::RealPredicate::RealONE => RealPredicate::RealONE,
-            rustc_codegen_ssa::common::RealPredicate::RealORD => RealPredicate::RealORD,
-            rustc_codegen_ssa::common::RealPredicate::RealUNO => RealPredicate::RealUNO,
-            rustc_codegen_ssa::common::RealPredicate::RealUEQ => RealPredicate::RealUEQ,
-            rustc_codegen_ssa::common::RealPredicate::RealUGT => RealPredicate::RealUGT,
-            rustc_codegen_ssa::common::RealPredicate::RealUGE => RealPredicate::RealUGE,
-            rustc_codegen_ssa::common::RealPredicate::RealULT => RealPredicate::RealULT,
-            rustc_codegen_ssa::common::RealPredicate::RealULE => RealPredicate::RealULE,
-            rustc_codegen_ssa::common::RealPredicate::RealUNE => RealPredicate::RealUNE,
-            rustc_codegen_ssa::common::RealPredicate::RealPredicateTrue => {
-                RealPredicate::RealPredicateTrue
-            }
+            Common::RealPredicateFalse => Self::RealPredicateFalse,
+            Common::RealOEQ => Self::RealOEQ,
+            Common::RealOGT => Self::RealOGT,
+            Common::RealOGE => Self::RealOGE,
+            Common::RealOLT => Self::RealOLT,
+            Common::RealOLE => Self::RealOLE,
+            Common::RealONE => Self::RealONE,
+            Common::RealORD => Self::RealORD,
+            Common::RealUNO => Self::RealUNO,
+            Common::RealUEQ => Self::RealUEQ,
+            Common::RealUGT => Self::RealUGT,
+            Common::RealUGE => Self::RealUGE,
+            Common::RealULT => Self::RealULT,
+            Common::RealULE => Self::RealULE,
+            Common::RealUNE => Self::RealUNE,
+            Common::RealPredicateTrue => Self::RealPredicateTrue,
         }
     }
 }
@@ -311,26 +309,27 @@ pub enum TypeKind {
 
 impl TypeKind {
     pub fn to_generic(self) -> rustc_codegen_ssa::common::TypeKind {
+        use rustc_codegen_ssa::common::TypeKind as Common;
         match self {
-            TypeKind::Void => rustc_codegen_ssa::common::TypeKind::Void,
-            TypeKind::Half => rustc_codegen_ssa::common::TypeKind::Half,
-            TypeKind::Float => rustc_codegen_ssa::common::TypeKind::Float,
-            TypeKind::Double => rustc_codegen_ssa::common::TypeKind::Double,
-            TypeKind::X86_FP80 => rustc_codegen_ssa::common::TypeKind::X86_FP80,
-            TypeKind::FP128 => rustc_codegen_ssa::common::TypeKind::FP128,
-            TypeKind::PPC_FP128 => rustc_codegen_ssa::common::TypeKind::PPC_FP128,
-            TypeKind::Label => rustc_codegen_ssa::common::TypeKind::Label,
-            TypeKind::Integer => rustc_codegen_ssa::common::TypeKind::Integer,
-            TypeKind::Function => rustc_codegen_ssa::common::TypeKind::Function,
-            TypeKind::Struct => rustc_codegen_ssa::common::TypeKind::Struct,
-            TypeKind::Array => rustc_codegen_ssa::common::TypeKind::Array,
-            TypeKind::Pointer => rustc_codegen_ssa::common::TypeKind::Pointer,
-            TypeKind::Vector => rustc_codegen_ssa::common::TypeKind::Vector,
-            TypeKind::Metadata => rustc_codegen_ssa::common::TypeKind::Metadata,
-            TypeKind::Token => rustc_codegen_ssa::common::TypeKind::Token,
-            TypeKind::ScalableVector => rustc_codegen_ssa::common::TypeKind::ScalableVector,
-            TypeKind::BFloat => rustc_codegen_ssa::common::TypeKind::BFloat,
-            TypeKind::X86_AMX => rustc_codegen_ssa::common::TypeKind::X86_AMX,
+            Self::Void => Common::Void,
+            Self::Half => Common::Half,
+            Self::Float => Common::Float,
+            Self::Double => Common::Double,
+            Self::X86_FP80 => Common::X86_FP80,
+            Self::FP128 => Common::FP128,
+            Self::PPC_FP128 => Common::PPC_FP128,
+            Self::Label => Common::Label,
+            Self::Integer => Common::Integer,
+            Self::Function => Common::Function,
+            Self::Struct => Common::Struct,
+            Self::Array => Common::Array,
+            Self::Pointer => Common::Pointer,
+            Self::Vector => Common::Vector,
+            Self::Metadata => Common::Metadata,
+            Self::Token => Common::Token,
+            Self::ScalableVector => Common::ScalableVector,
+            Self::BFloat => Common::BFloat,
+            Self::X86_AMX => Common::X86_AMX,
         }
     }
 }
@@ -354,18 +353,19 @@ pub enum AtomicRmwBinOp {
 
 impl AtomicRmwBinOp {
     pub fn from_generic(op: rustc_codegen_ssa::common::AtomicRmwBinOp) -> Self {
+        use rustc_codegen_ssa::common::AtomicRmwBinOp as Common;
         match op {
-            rustc_codegen_ssa::common::AtomicRmwBinOp::AtomicXchg => AtomicRmwBinOp::AtomicXchg,
-            rustc_codegen_ssa::common::AtomicRmwBinOp::AtomicAdd => AtomicRmwBinOp::AtomicAdd,
-            rustc_codegen_ssa::common::AtomicRmwBinOp::AtomicSub => AtomicRmwBinOp::AtomicSub,
-            rustc_codegen_ssa::common::AtomicRmwBinOp::AtomicAnd => AtomicRmwBinOp::AtomicAnd,
-            rustc_codegen_ssa::common::AtomicRmwBinOp::AtomicNand => AtomicRmwBinOp::AtomicNand,
-            rustc_codegen_ssa::common::AtomicRmwBinOp::AtomicOr => AtomicRmwBinOp::AtomicOr,
-            rustc_codegen_ssa::common::AtomicRmwBinOp::AtomicXor => AtomicRmwBinOp::AtomicXor,
-            rustc_codegen_ssa::common::AtomicRmwBinOp::AtomicMax => AtomicRmwBinOp::AtomicMax,
-            rustc_codegen_ssa::common::AtomicRmwBinOp::AtomicMin => AtomicRmwBinOp::AtomicMin,
-            rustc_codegen_ssa::common::AtomicRmwBinOp::AtomicUMax => AtomicRmwBinOp::AtomicUMax,
-            rustc_codegen_ssa::common::AtomicRmwBinOp::AtomicUMin => AtomicRmwBinOp::AtomicUMin,
+            Common::AtomicXchg => Self::AtomicXchg,
+            Common::AtomicAdd => Self::AtomicAdd,
+            Common::AtomicSub => Self::AtomicSub,
+            Common::AtomicAnd => Self::AtomicAnd,
+            Common::AtomicNand => Self::AtomicNand,
+            Common::AtomicOr => Self::AtomicOr,
+            Common::AtomicXor => Self::AtomicXor,
+            Common::AtomicMax => Self::AtomicMax,
+            Common::AtomicMin => Self::AtomicMin,
+            Common::AtomicUMax => Self::AtomicUMax,
+            Common::AtomicUMin => Self::AtomicUMin,
         }
     }
 }
@@ -387,17 +387,14 @@ pub enum AtomicOrdering {
 
 impl AtomicOrdering {
     pub fn from_generic(ao: rustc_codegen_ssa::common::AtomicOrdering) -> Self {
+        use rustc_codegen_ssa::common::AtomicOrdering as Common;
         match ao {
-            rustc_codegen_ssa::common::AtomicOrdering::Unordered => AtomicOrdering::Unordered,
-            rustc_codegen_ssa::common::AtomicOrdering::Relaxed => AtomicOrdering::Monotonic,
-            rustc_codegen_ssa::common::AtomicOrdering::Acquire => AtomicOrdering::Acquire,
-            rustc_codegen_ssa::common::AtomicOrdering::Release => AtomicOrdering::Release,
-            rustc_codegen_ssa::common::AtomicOrdering::AcquireRelease => {
-                AtomicOrdering::AcquireRelease
-            }
-            rustc_codegen_ssa::common::AtomicOrdering::SequentiallyConsistent => {
-                AtomicOrdering::SequentiallyConsistent
-            }
+            Common::Unordered => Self::Unordered,
+            Common::Relaxed => Self::Monotonic,
+            Common::Acquire => Self::Acquire,
+            Common::Release => Self::Release,
+            Common::AcquireRelease => Self::AcquireRelease,
+            Common::SequentiallyConsistent => Self::SequentiallyConsistent,
         }
     }
 }
@@ -563,13 +560,11 @@ pub enum ArchiveKind {
     K_AIXBIG,
 }
 
-// LLVMRustThinLTOData
 unsafe extern "C" {
+    // LLVMRustThinLTOData
     pub type ThinLTOData;
-}
 
-// LLVMRustThinLTOBuffer
-unsafe extern "C" {
+    // LLVMRustThinLTOBuffer
     pub type ThinLTOBuffer;
 }
 
@@ -633,26 +628,12 @@ struct InvariantOpaque<'a> {
 // Opaque pointer types
 unsafe extern "C" {
     pub type Module;
-}
-unsafe extern "C" {
     pub type Context;
-}
-unsafe extern "C" {
     pub type Type;
-}
-unsafe extern "C" {
     pub type Value;
-}
-unsafe extern "C" {
     pub type ConstantInt;
-}
-unsafe extern "C" {
     pub type Attribute;
-}
-unsafe extern "C" {
     pub type Metadata;
-}
-unsafe extern "C" {
     pub type BasicBlock;
 }
 #[repr(C)]
@@ -661,11 +642,7 @@ pub struct Builder<'a>(InvariantOpaque<'a>);
 pub struct PassManager<'a>(InvariantOpaque<'a>);
 unsafe extern "C" {
     pub type Pass;
-}
-unsafe extern "C" {
     pub type TargetMachine;
-}
-unsafe extern "C" {
     pub type Archive;
 }
 #[repr(C)]
@@ -674,11 +651,7 @@ pub struct ArchiveIterator<'a>(InvariantOpaque<'a>);
 pub struct ArchiveChild<'a>(InvariantOpaque<'a>);
 unsafe extern "C" {
     pub type Twine;
-}
-unsafe extern "C" {
     pub type DiagnosticInfo;
-}
-unsafe extern "C" {
     pub type SMDiagnostic;
 }
 #[repr(C)]
@@ -2177,7 +2150,8 @@ unsafe extern "C" {
 
     pub fn LLVMRustGetHostCPUName(len: *mut usize) -> *const c_char;
 
-    // This function makes copies of pointed to data, so the data's lifetime may end after this function returns
+    // This function makes copies of pointed to data, so the data's lifetime may end after this
+    // function returns.
     pub fn LLVMRustCreateTargetMachine(
         Triple: *const c_char,
         CPU: *const c_char,
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 29afe6f6bfc..fd8db4ad1d5 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -217,10 +217,10 @@ impl<'a> IntoIterator for LLVMFeature<'a> {
 // where `{ARCH}` is the architecture name. Look for instances of `SubtargetFeature`.
 //
 // Check the current rustc fork of LLVM in the repo at https://github.com/rust-lang/llvm-project/.
-// The commit in use can be found via the `llvm-project` submodule in https://github.com/rust-lang/rust/tree/master/src
-// Though note that Rust can also be build with an external precompiled version of LLVM
-// which might lead to failures if the oldest tested / supported LLVM version
-// doesn't yet support the relevant intrinsics
+// The commit in use can be found via the `llvm-project` submodule in
+// https://github.com/rust-lang/rust/tree/master/src Though note that Rust can also be build with
+// an external precompiled version of LLVM which might lead to failures if the oldest tested /
+// supported LLVM version doesn't yet support the relevant intrinsics.
 pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFeature<'a>> {
     let arch = if sess.target.arch == "x86_64" {
         "x86"
@@ -258,28 +258,14 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
         ("aarch64", "fhm") => Some(LLVMFeature::new("fp16fml")),
         ("aarch64", "fp16") => Some(LLVMFeature::new("fullfp16")),
         // Filter out features that are not supported by the current LLVM version
-        ("aarch64", "faminmax") if get_version().0 < 18 => None,
-        ("aarch64", "fp8") if get_version().0 < 18 => None,
-        ("aarch64", "fp8dot2") if get_version().0 < 18 => None,
-        ("aarch64", "fp8dot4") if get_version().0 < 18 => None,
-        ("aarch64", "fp8fma") if get_version().0 < 18 => None,
         ("aarch64", "fpmr") if get_version().0 != 18 => None,
-        ("aarch64", "lut") if get_version().0 < 18 => None,
-        ("aarch64", "sme-f8f16") if get_version().0 < 18 => None,
-        ("aarch64", "sme-f8f32") if get_version().0 < 18 => None,
-        ("aarch64", "sme-fa64") if get_version().0 < 18 => None,
-        ("aarch64", "sme-lutv2") if get_version().0 < 18 => None,
-        ("aarch64", "ssve-fp8dot2") if get_version().0 < 18 => None,
-        ("aarch64", "ssve-fp8dot4") if get_version().0 < 18 => None,
-        ("aarch64", "ssve-fp8fma") if get_version().0 < 18 => None,
-        ("aarch64", "v9.5a") if get_version().0 < 18 => None,
-        // In LLVM 18, `unaligned-scalar-mem` was merged with `unaligned-vector-mem` into a single feature called
-        // `fast-unaligned-access`. In LLVM 19, it was split back out.
+        // In LLVM 18, `unaligned-scalar-mem` was merged with `unaligned-vector-mem` into a single
+        // feature called `fast-unaligned-access`. In LLVM 19, it was split back out.
         ("riscv32" | "riscv64", "unaligned-scalar-mem") if get_version().0 == 18 => {
             Some(LLVMFeature::new("fast-unaligned-access"))
         }
-        // For LLVM 18, enable the evex512 target feature if a avx512 target feature is enabled.
-        ("x86", s) if get_version().0 >= 18 && s.starts_with("avx512") => {
+        // Enable the evex512 target feature if an avx512 target feature is enabled.
+        ("x86", s) if s.starts_with("avx512") => {
             Some(LLVMFeature::with_dependency(s, TargetFeatureFoldStrength::EnableOnly("evex512")))
         }
         (_, s) => Some(LLVMFeature::new(s)),
@@ -420,7 +406,8 @@ fn print_target_features(out: &mut String, sess: &Session, tm: &llvm::TargetMach
         .supported_target_features()
         .iter()
         .filter_map(|(feature, _gate, _implied)| {
-            // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these strings.
+            // LLVM asserts that these are sorted. LLVM and Rust both use byte comparison for these
+            // strings.
             let llvm_feature = to_llvm_features(sess, *feature)?.llvm_feature_name;
             let desc =
                 match llvm_target_features.binary_search_by_key(&llvm_feature, |(f, _d)| f).ok() {
@@ -587,7 +574,6 @@ pub(crate) fn global_llvm_features(
     // -Ctarget-features
     if !only_base_features {
         let supported_features = sess.target.supported_target_features();
-        let (llvm_major, _, _) = get_version();
         let mut featsmap = FxHashMap::default();
 
         // insert implied features
@@ -664,12 +650,6 @@ pub(crate) fn global_llvm_features(
                     return None;
                 }
 
-                // if the target-feature is "backchain" and LLVM version is greater than 18
-                // then we also need to add "+backchain" to the target-features attribute.
-                // otherwise, we will only add the naked `backchain` attribute to the attribute-group.
-                if feature == "backchain" && llvm_major < 18 {
-                    return None;
-                }
                 // ... otherwise though we run through `to_llvm_features` when
                 // passing requests down to LLVM. This means that all in-language
                 // features also work on the command line instead of having two
diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs
index f1ef359594b..02e1995620b 100644
--- a/compiler/rustc_codegen_llvm/src/mono_item.rs
+++ b/compiler/rustc_codegen_llvm/src/mono_item.rs
@@ -14,7 +14,7 @@ use crate::errors::SymbolAlreadyDefined;
 use crate::type_of::LayoutLlvmExt;
 use crate::{base, llvm};
 
-impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> {
+impl<'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
     fn predefine_static(
         &self,
         def_id: DefId,
@@ -24,8 +24,8 @@ impl<'tcx> PreDefineMethods<'tcx> for CodegenCx<'_, 'tcx> {
     ) {
         let instance = Instance::mono(self.tcx, def_id);
         let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() };
-        // Nested statics do not have a type, so pick a dummy type and let `codegen_static` figure out
-        // the llvm type from the actual evaluated initializer.
+        // Nested statics do not have a type, so pick a dummy type and let `codegen_static` figure
+        // out the llvm type from the actual evaluated initializer.
         let ty = if nested {
             self.tcx.types.unit
         } else {
diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs
index ec1e2cb8094..2c2b9030b7c 100644
--- a/compiler/rustc_codegen_llvm/src/type_.rs
+++ b/compiler/rustc_codegen_llvm/src/type_.rs
@@ -141,7 +141,7 @@ impl<'ll> CodegenCx<'ll, '_> {
     }
 }
 
-impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
+impl<'ll, 'tcx> BaseTypeCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
     fn type_i8(&self) -> &'ll Type {
         unsafe { llvm::LLVMInt8TypeInContext(self.llcx) }
     }
@@ -245,7 +245,7 @@ impl Type {
     }
 }
 
-impl<'ll, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
+impl<'ll, 'tcx> LayoutTypeCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
     fn backend_type(&self, layout: TyAndLayout<'tcx>) -> &'ll Type {
         layout.llvm_type(self)
     }
@@ -280,7 +280,7 @@ impl<'ll, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
     }
 }
 
-impl<'ll, 'tcx> TypeMembershipMethods<'tcx> for CodegenCx<'ll, 'tcx> {
+impl<'ll, 'tcx> TypeMembershipCodegenMethods<'tcx> for CodegenCx<'ll, 'tcx> {
     fn add_type_metadata(&self, function: &'ll Value, typeid: String) {
         let typeid_metadata = self.typeid_metadata(typeid).unwrap();
         let v = [self.const_usize(0), typeid_metadata];
diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs
index 94e77c5bd70..781cee81180 100644
--- a/compiler/rustc_codegen_llvm/src/va_arg.rs
+++ b/compiler/rustc_codegen_llvm/src/va_arg.rs
@@ -1,6 +1,6 @@
 use rustc_codegen_ssa::common::IntPredicate;
 use rustc_codegen_ssa::mir::operand::OperandRef;
-use rustc_codegen_ssa::traits::{BaseTypeMethods, BuilderMethods, ConstMethods};
+use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods};
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
 use rustc_middle::ty::Ty;
 use rustc_target::abi::{Align, Endian, HasDataLayout, Size};
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index f6b45eb4466..3d1007a4673 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -115,9 +115,9 @@ fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     let (source, target) =
         cx.tcx().struct_lockstep_tails_for_codegen(source, target, bx.param_env());
     match (source.kind(), target.kind()) {
-        (&ty::Array(_, len), &ty::Slice(_)) => {
-            cx.const_usize(len.eval_target_usize(cx.tcx(), ty::ParamEnv::reveal_all()))
-        }
+        (&ty::Array(_, len), &ty::Slice(_)) => cx.const_usize(
+            len.try_to_target_usize(cx.tcx()).expect("expected monomorphic const in codegen"),
+        ),
         (&ty::Dynamic(data_a, _, src_dyn_kind), &ty::Dynamic(data_b, _, target_dyn_kind))
             if src_dyn_kind == target_dyn_kind =>
         {
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 137e481f08c..9bd8a84f5a3 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -195,24 +195,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                     }
                 }
             }
-            sym::cmse_nonsecure_entry => {
-                if let Some(fn_sig) = fn_sig()
-                    && !matches!(fn_sig.skip_binder().abi(), abi::Abi::C { .. })
-                {
-                    struct_span_code_err!(
-                        tcx.dcx(),
-                        attr.span,
-                        E0776,
-                        "`#[cmse_nonsecure_entry]` requires C ABI"
-                    )
-                    .emit();
-                }
-                if !tcx.sess.target.llvm_target.contains("thumbv8m") {
-                    struct_span_code_err!(tcx.dcx(), attr.span, E0775, "`#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension")
-                    .emit();
-                }
-                codegen_fn_attrs.flags |= CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY
-            }
             sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL,
             sym::track_caller => {
                 let is_closure = tcx.is_closure_like(did.to_def_id());
diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
index 55a71db9bae..369ab387bea 100644
--- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
+++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs
@@ -188,7 +188,8 @@ fn push_debuginfo_type_name<'tcx>(
                     _ => write!(
                         output,
                         ",{}>",
-                        len.eval_target_usize(tcx, ty::ParamEnv::reveal_all())
+                        len.try_to_target_usize(tcx)
+                            .expect("expected monomorphic const in codegen")
                     )
                     .unwrap(),
                 }
@@ -200,7 +201,8 @@ fn push_debuginfo_type_name<'tcx>(
                     _ => write!(
                         output,
                         "; {}]",
-                        len.eval_target_usize(tcx, ty::ParamEnv::reveal_all())
+                        len.try_to_target_usize(tcx)
+                            .expect("expected monomorphic const in codegen")
                     )
                     .unwrap(),
                 }
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index f6570532b97..26d4d0acac5 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -11,6 +11,7 @@
 #![feature(negative_impls)]
 #![feature(rustdoc_internals)]
 #![feature(strict_provenance)]
+#![feature(trait_alias)]
 #![feature(try_blocks)]
 #![warn(unreachable_pub)]
 // tidy-alphabetical-end
diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
index f13c46e8bef..25712095e76 100644
--- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
@@ -15,6 +15,7 @@ use crate::traits::*;
 
 pub(crate) fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     fx: &FunctionCx<'a, 'tcx, Bx>,
+    traversal_order: &[mir::BasicBlock],
 ) -> BitSet<mir::Local> {
     let mir = fx.mir;
     let dominators = mir.basic_blocks.dominators();
@@ -24,13 +25,7 @@ pub(crate) fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
         .map(|decl| {
             let ty = fx.monomorphize(decl.ty);
             let layout = fx.cx.spanned_layout_of(ty, decl.source_info.span);
-            if layout.is_zst() {
-                LocalKind::ZST
-            } else if fx.cx.is_backend_immediate(layout) || fx.cx.is_backend_scalar_pair(layout) {
-                LocalKind::Unused
-            } else {
-                LocalKind::Memory
-            }
+            if layout.is_zst() { LocalKind::ZST } else { LocalKind::Unused }
         })
         .collect();
 
@@ -44,7 +39,8 @@ pub(crate) fn non_ssa_locals<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     // If there exists a local definition that dominates all uses of that local,
     // the definition should be visited first. Traverse blocks in an order that
     // is a topological sort of dominance partial order.
-    for (bb, data) in traversal::reverse_postorder(mir) {
+    for bb in traversal_order.iter().copied() {
+        let data = &mir.basic_blocks[bb];
         analyzer.visit_basic_block_data(bb, data);
     }
 
@@ -77,11 +73,22 @@ struct LocalAnalyzer<'a, 'b, 'tcx, Bx: BuilderMethods<'b, 'tcx>> {
 
 impl<'a, 'b, 'tcx, Bx: BuilderMethods<'b, 'tcx>> LocalAnalyzer<'a, 'b, 'tcx, Bx> {
     fn define(&mut self, local: mir::Local, location: DefLocation) {
+        let fx = self.fx;
         let kind = &mut self.locals[local];
+        let decl = &fx.mir.local_decls[local];
         match *kind {
             LocalKind::ZST => {}
             LocalKind::Memory => {}
-            LocalKind::Unused => *kind = LocalKind::SSA(location),
+            LocalKind::Unused => {
+                let ty = fx.monomorphize(decl.ty);
+                let layout = fx.cx.spanned_layout_of(ty, decl.source_info.span);
+                *kind =
+                    if fx.cx.is_backend_immediate(layout) || fx.cx.is_backend_scalar_pair(layout) {
+                        LocalKind::SSA(location)
+                    } else {
+                        LocalKind::Memory
+                    };
+            }
             LocalKind::SSA(_) => *kind = LocalKind::Memory,
         }
     }
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index 61e9b9bd774..68fb5cb2206 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -218,7 +218,8 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
 
     fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut start_bx);
 
-    let memory_locals = analyze::non_ssa_locals(&fx);
+    let traversal_order = traversal::mono_reachable_reverse_postorder(mir, cx.tcx(), instance);
+    let memory_locals = analyze::non_ssa_locals(&fx, &traversal_order);
 
     // Allocate variable and temp allocas
     let local_values = {
@@ -277,17 +278,20 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
     // So drop the builder of `start_llbb` to avoid having two at the same time.
     drop(start_bx);
 
-    let reachable_blocks = traversal::mono_reachable_as_bitset(mir, cx.tcx(), instance);
+    let mut unreached_blocks = BitSet::new_filled(mir.basic_blocks.len());
+    // Codegen the body of each reachable block using our reverse postorder list.
+    for bb in traversal_order {
+        fx.codegen_block(bb);
+        unreached_blocks.remove(bb);
+    }
 
-    // Codegen the body of each block using reverse postorder
-    for (bb, _) in traversal::reverse_postorder(mir) {
-        if reachable_blocks.contains(bb) {
-            fx.codegen_block(bb);
-        } else {
-            // We want to skip this block, because it's not reachable. But we still create
-            // the block so terminators in other blocks can reference it.
-            fx.codegen_block_as_unreachable(bb);
-        }
+    // FIXME: These empty unreachable blocks are *mostly* a waste. They are occasionally
+    // targets for a SwitchInt terminator, but the reimplementation of the mono-reachable
+    // simplification in SwitchInt lowering sometimes misses cases that
+    // mono_reachable_reverse_postorder manages to figure out.
+    // The solution is to do something like post-mono GVN. But for now we have this hack.
+    for bb in unreached_blocks.iter() {
+        fx.codegen_block_as_unreachable(bb);
     }
 }
 
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index 8afd5e867b5..ee32b4f23c9 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -27,32 +27,32 @@ pub enum OperandValue<V> {
     /// which indicates that it refers to an unsized rvalue.
     ///
     /// An `OperandValue` *must* be this variant for any type for which
-    /// [`LayoutTypeMethods::is_backend_ref`] returns `true`.
+    /// [`LayoutTypeCodegenMethods::is_backend_ref`] returns `true`.
     /// (That basically amounts to "isn't one of the other variants".)
     ///
     /// This holds a [`PlaceValue`] (like a [`PlaceRef`] does) with a pointer
     /// to the location holding the value. The type behind that pointer is the
-    /// one returned by [`LayoutTypeMethods::backend_type`].
+    /// one returned by [`LayoutTypeCodegenMethods::backend_type`].
     Ref(PlaceValue<V>),
     /// A single LLVM immediate value.
     ///
     /// An `OperandValue` *must* be this variant for any type for which
-    /// [`LayoutTypeMethods::is_backend_immediate`] returns `true`.
+    /// [`LayoutTypeCodegenMethods::is_backend_immediate`] returns `true`.
     /// The backend value in this variant must be the *immediate* backend type,
-    /// as returned by [`LayoutTypeMethods::immediate_backend_type`].
+    /// as returned by [`LayoutTypeCodegenMethods::immediate_backend_type`].
     Immediate(V),
     /// A pair of immediate LLVM values. Used by fat pointers too.
     ///
     /// An `OperandValue` *must* be this variant for any type for which
-    /// [`LayoutTypeMethods::is_backend_scalar_pair`] returns `true`.
+    /// [`LayoutTypeCodegenMethods::is_backend_scalar_pair`] returns `true`.
     /// The backend values in this variant must be the *immediate* backend types,
-    /// as returned by [`LayoutTypeMethods::scalar_pair_element_backend_type`]
+    /// as returned by [`LayoutTypeCodegenMethods::scalar_pair_element_backend_type`]
     /// with `immediate: true`.
     Pair(V, V),
     /// A value taking no bytes, and which therefore needs no LLVM value at all.
     ///
     /// If you ever need a `V` to pass to something, get a fresh poison value
-    /// from [`ConstMethods::const_poison`].
+    /// from [`ConstCodegenMethods::const_poison`].
     ///
     /// An `OperandValue` *must* be this variant for any type for which
     /// `is_zst` on its `Layout` returns `true`. Note however that
@@ -110,7 +110,7 @@ impl<V: CodegenObject> OperandValue<V> {
         PlaceValue { llval, llextra, align }
     }
 
-    pub(crate) fn is_expected_variant_for_type<'tcx, Cx: LayoutTypeMethods<'tcx>>(
+    pub(crate) fn is_expected_variant_for_type<'tcx, Cx: LayoutTypeCodegenMethods<'tcx>>(
         &self,
         cx: &Cx,
         ty: TyAndLayout<'tcx>,
@@ -280,7 +280,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
     ///
     /// If you don't need the type, see [`OperandValue::pointer_parts`]
     /// or [`OperandValue::deref`].
-    pub fn deref<Cx: LayoutTypeMethods<'tcx>>(self, cx: &Cx) -> PlaceRef<'tcx, V> {
+    pub fn deref<Cx: CodegenMethods<'tcx>>(self, cx: &Cx) -> PlaceRef<'tcx, V> {
         if self.layout.ty.is_box() {
             // Derefer should have removed all Box derefs
             bug!("dereferencing {:?} in codegen", self.layout.ty);
diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs
index 0fad4d169ed..eba150c6eac 100644
--- a/compiler/rustc_codegen_ssa/src/mir/place.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/place.rs
@@ -133,7 +133,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> {
         Self::alloca(bx, ptr_layout)
     }
 
-    pub fn len<Cx: ConstMethods<'tcx, Value = V>>(&self, cx: &Cx) -> V {
+    pub fn len<Cx: ConstCodegenMethods<'tcx, Value = V>>(&self, cx: &Cx) -> V {
         if let FieldsShape::Array { count, .. } = self.layout.fields {
             if self.layout.is_unsized() {
                 assert_eq!(count, 0);
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 37474d85b11..6bf75293fce 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -114,7 +114,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
                 let count = self
                     .monomorphize(count)
-                    .eval_target_usize(bx.cx().tcx(), ty::ParamEnv::reveal_all());
+                    .try_to_target_usize(bx.tcx())
+                    .expect("expected monomorphic const in codegen");
 
                 bx.write_operand_repeatedly(cg_elem, count, dest);
             }
@@ -803,7 +804,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         if let Some(index) = place.as_local() {
             if let LocalRef::Operand(op) = self.locals[index] {
                 if let ty::Array(_, n) = op.layout.ty.kind() {
-                    let n = n.eval_target_usize(bx.cx().tcx(), ty::ParamEnv::reveal_all());
+                    let n = n
+                        .try_to_target_usize(bx.tcx())
+                        .expect("expected monomorphic const in codegen");
                     return bx.cx().const_usize(n);
                 }
             }
diff --git a/compiler/rustc_codegen_ssa/src/traits/asm.rs b/compiler/rustc_codegen_ssa/src/traits/asm.rs
index 162141a106b..f4853da1156 100644
--- a/compiler/rustc_codegen_ssa/src/traits/asm.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/asm.rs
@@ -60,7 +60,7 @@ pub trait AsmBuilderMethods<'tcx>: BackendTypes {
     );
 }
 
-pub trait AsmMethods<'tcx> {
+pub trait AsmCodegenMethods<'tcx> {
     fn codegen_global_asm(
         &self,
         template: &[InlineAsmTemplatePiece],
diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs
index 4fc44e9c0fc..e45af1cd153 100644
--- a/compiler/rustc_codegen_ssa/src/traits/backend.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs
@@ -8,13 +8,11 @@ use rustc_errors::ErrorGuaranteed;
 use rustc_metadata::creader::MetadataLoaderDyn;
 use rustc_metadata::EncodedMetadata;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
-use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, LayoutOf, TyAndLayout};
-use rustc_middle::ty::{Ty, TyCtxt};
+use rustc_middle::ty::TyCtxt;
 use rustc_middle::util::Providers;
 use rustc_session::config::{self, OutputFilenames, PrintRequest};
 use rustc_session::Session;
 use rustc_span::symbol::Symbol;
-use rustc_target::abi::call::FnAbi;
 
 use super::write::WriteBackendMethods;
 use super::CodegenObject;
@@ -36,23 +34,6 @@ pub trait BackendTypes {
     type DIVariable: Copy;
 }
 
-pub trait Backend<'tcx>:
-    Sized
-    + BackendTypes
-    + HasTyCtxt<'tcx>
-    + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>>
-    + FnAbiOf<'tcx, FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>>
-{
-}
-
-impl<'tcx, T> Backend<'tcx> for T where
-    Self: BackendTypes
-        + HasTyCtxt<'tcx>
-        + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>>
-        + FnAbiOf<'tcx, FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>>
-{
-}
-
 pub trait CodegenBackend {
     /// Locale resources for diagnostic messages - a string the content of the Fluent resource.
     /// Called before `init` so that all other functions are able to emit translatable diagnostics.
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index 6cf84a012f0..5af0457bebd 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -1,23 +1,23 @@
 use std::assert_matches::assert_matches;
+use std::ops::Deref;
 
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
-use rustc_middle::ty::layout::{HasParamEnv, TyAndLayout};
+use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
 use rustc_middle::ty::{Instance, Ty};
 use rustc_session::config::OptLevel;
 use rustc_span::Span;
 use rustc_target::abi::call::FnAbi;
 use rustc_target::abi::{Abi, Align, Scalar, Size, WrappingRange};
-use rustc_target::spec::HasTargetSpec;
 
 use super::abi::AbiBuilderMethods;
 use super::asm::AsmBuilderMethods;
-use super::consts::ConstMethods;
+use super::consts::ConstCodegenMethods;
 use super::coverageinfo::CoverageInfoBuilderMethods;
 use super::debuginfo::DebugInfoBuilderMethods;
-use super::intrinsic::IntrinsicCallMethods;
-use super::misc::MiscMethods;
-use super::type_::{ArgAbiMethods, BaseTypeMethods, LayoutTypeMethods};
-use super::{HasCodegen, StaticBuilderMethods};
+use super::intrinsic::IntrinsicCallBuilderMethods;
+use super::misc::MiscCodegenMethods;
+use super::type_::{ArgAbiBuilderMethods, BaseTypeCodegenMethods, LayoutTypeCodegenMethods};
+use super::{CodegenMethods, StaticBuilderMethods};
 use crate::common::{
     AtomicOrdering, AtomicRmwBinOp, IntPredicate, RealPredicate, SynchronizationScope, TypeKind,
 };
@@ -33,17 +33,33 @@ pub enum OverflowOp {
 }
 
 pub trait BuilderMethods<'a, 'tcx>:
-    HasCodegen<'tcx>
+    Sized
+    + LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>>
+    + FnAbiOf<'tcx, FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>>
+    + Deref<Target = Self::CodegenCx>
     + CoverageInfoBuilderMethods<'tcx>
     + DebugInfoBuilderMethods
-    + ArgAbiMethods<'tcx>
+    + ArgAbiBuilderMethods<'tcx>
     + AbiBuilderMethods<'tcx>
-    + IntrinsicCallMethods<'tcx>
+    + IntrinsicCallBuilderMethods<'tcx>
     + AsmBuilderMethods<'tcx>
     + StaticBuilderMethods
-    + HasParamEnv<'tcx>
-    + HasTargetSpec
 {
+    // `BackendTypes` is a supertrait of both `CodegenMethods` and
+    // `BuilderMethods`. This bound ensures all impls agree on the associated
+    // types within.
+    type CodegenCx: CodegenMethods<
+            'tcx,
+            Value = Self::Value,
+            Function = Self::Function,
+            BasicBlock = Self::BasicBlock,
+            Type = Self::Type,
+            Funclet = Self::Funclet,
+            DIScope = Self::DIScope,
+            DILocation = Self::DILocation,
+            DIVariable = Self::DIVariable,
+        >;
+
     fn build(cx: &'a Self::CodegenCx, llbb: Self::BasicBlock) -> Self;
 
     fn cx(&self) -> &Self::CodegenCx;
diff --git a/compiler/rustc_codegen_ssa/src/traits/consts.rs b/compiler/rustc_codegen_ssa/src/traits/consts.rs
index c15f1fa8e56..9af463a691a 100644
--- a/compiler/rustc_codegen_ssa/src/traits/consts.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/consts.rs
@@ -3,7 +3,7 @@ use rustc_target::abi;
 
 use super::BackendTypes;
 
-pub trait ConstMethods<'tcx>: BackendTypes {
+pub trait ConstCodegenMethods<'tcx>: BackendTypes {
     // Constant constructors
     fn const_null(&self, t: Self::Type) -> Self::Value;
     /// Generate an uninitialized value (matching uninitialized memory in MIR).
@@ -14,18 +14,20 @@ pub trait ConstMethods<'tcx>: BackendTypes {
     /// (including code that e.g. copies uninit memory with `MaybeUninit`) can never encounter a
     /// poison value.
     fn const_poison(&self, t: Self::Type) -> Self::Value;
-    fn const_int(&self, t: Self::Type, i: i64) -> Self::Value;
-    fn const_uint(&self, t: Self::Type, i: u64) -> Self::Value;
-    fn const_uint_big(&self, t: Self::Type, u: u128) -> Self::Value;
+
     fn const_bool(&self, val: bool) -> Self::Value;
+
+    fn const_i8(&self, i: i8) -> Self::Value;
     fn const_i16(&self, i: i16) -> Self::Value;
     fn const_i32(&self, i: i32) -> Self::Value;
-    fn const_i8(&self, i: i8) -> Self::Value;
+    fn const_int(&self, t: Self::Type, i: i64) -> Self::Value;
+    fn const_u8(&self, i: u8) -> Self::Value;
     fn const_u32(&self, i: u32) -> Self::Value;
     fn const_u64(&self, i: u64) -> Self::Value;
     fn const_u128(&self, i: u128) -> Self::Value;
     fn const_usize(&self, i: u64) -> Self::Value;
-    fn const_u8(&self, i: u8) -> Self::Value;
+    fn const_uint(&self, t: Self::Type, i: u64) -> Self::Value;
+    fn const_uint_big(&self, t: Self::Type, u: u128) -> Self::Value;
     fn const_real(&self, t: Self::Type, val: f64) -> Self::Value;
 
     fn const_str(&self, s: &str) -> (Self::Value, Self::Value);
diff --git a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs
index 0b1645c66ed..0b513dac503 100644
--- a/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/coverageinfo.rs
@@ -1,9 +1,7 @@
 use rustc_middle::mir::coverage::CoverageKind;
 use rustc_middle::ty::Instance;
 
-use super::BackendTypes;
-
-pub trait CoverageInfoBuilderMethods<'tcx>: BackendTypes {
+pub trait CoverageInfoBuilderMethods<'tcx> {
     /// Performs any start-of-function codegen needed for coverage instrumentation.
     ///
     /// Can be a no-op in backends that don't support coverage instrumentation.
diff --git a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs
index 5fbe97214fb..7526c221b05 100644
--- a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs
@@ -9,7 +9,7 @@ use rustc_target::abi::Size;
 use super::BackendTypes;
 use crate::mir::debuginfo::{FunctionDebugContext, VariableKind};
 
-pub trait DebugInfoMethods<'tcx>: BackendTypes {
+pub trait DebugInfoCodegenMethods<'tcx>: BackendTypes {
     fn create_vtable_debuginfo(
         &self,
         ty: Ty<'tcx>,
diff --git a/compiler/rustc_codegen_ssa/src/traits/declare.rs b/compiler/rustc_codegen_ssa/src/traits/declare.rs
index 792d2b04ed6..c1edeac31b0 100644
--- a/compiler/rustc_codegen_ssa/src/traits/declare.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/declare.rs
@@ -2,9 +2,7 @@ use rustc_hir::def_id::DefId;
 use rustc_middle::mir::mono::{Linkage, Visibility};
 use rustc_middle::ty::Instance;
 
-use super::BackendTypes;
-
-pub trait PreDefineMethods<'tcx>: BackendTypes {
+pub trait PreDefineCodegenMethods<'tcx> {
     fn predefine_static(
         &self,
         def_id: DefId,
diff --git a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
index 172004a9cc7..e721cfb7134 100644
--- a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
@@ -5,7 +5,7 @@ use rustc_target::abi::call::FnAbi;
 use super::BackendTypes;
 use crate::mir::operand::OperandRef;
 
-pub trait IntrinsicCallMethods<'tcx>: BackendTypes {
+pub trait IntrinsicCallBuilderMethods<'tcx>: BackendTypes {
     /// Remember to add all intrinsics here, in `compiler/rustc_hir_analysis/src/check/mod.rs`,
     /// and in `library/core/src/intrinsics.rs`; if you need access to any LLVM intrinsics,
     /// add them to `compiler/rustc_codegen_llvm/src/context.rs`.
diff --git a/compiler/rustc_codegen_ssa/src/traits/misc.rs b/compiler/rustc_codegen_ssa/src/traits/misc.rs
index bf1b7eabe23..5b33fd7ab10 100644
--- a/compiler/rustc_codegen_ssa/src/traits/misc.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/misc.rs
@@ -7,7 +7,7 @@ use rustc_session::Session;
 
 use super::BackendTypes;
 
-pub trait MiscMethods<'tcx>: BackendTypes {
+pub trait MiscCodegenMethods<'tcx>: BackendTypes {
     fn vtables(
         &self,
     ) -> &RefCell<FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), Self::Value>>;
diff --git a/compiler/rustc_codegen_ssa/src/traits/mod.rs b/compiler/rustc_codegen_ssa/src/traits/mod.rs
index 9ac923bef88..2196bc996d9 100644
--- a/compiler/rustc_codegen_ssa/src/traits/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/mod.rs
@@ -8,9 +8,6 @@
 //! actual codegen, while the builder stores the information about the function during codegen and
 //! is used to produce the instructions of the backend IR.
 //!
-//! Finally, a third `Backend` structure has to implement methods related to how codegen information
-//! is passed to the backend, especially for asynchronous compilation.
-//!
 //! The traits contain associated types that are backend-specific, such as the backend's value or
 //! basic blocks.
 
@@ -30,71 +27,36 @@ mod write;
 
 use std::fmt;
 
-use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt};
-use rustc_target::spec::HasTargetSpec;
+use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
+use rustc_middle::ty::Ty;
+use rustc_target::abi::call::FnAbi;
 
 pub use self::abi::AbiBuilderMethods;
-pub use self::asm::{AsmBuilderMethods, AsmMethods, GlobalAsmOperandRef, InlineAsmOperandRef};
-pub use self::backend::{Backend, BackendTypes, CodegenBackend, ExtraBackendMethods};
+pub use self::asm::{
+    AsmBuilderMethods, AsmCodegenMethods, GlobalAsmOperandRef, InlineAsmOperandRef,
+};
+pub use self::backend::{BackendTypes, CodegenBackend, ExtraBackendMethods};
 pub use self::builder::{BuilderMethods, OverflowOp};
-pub use self::consts::ConstMethods;
+pub use self::consts::ConstCodegenMethods;
 pub use self::coverageinfo::CoverageInfoBuilderMethods;
-pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoMethods};
-pub use self::declare::PreDefineMethods;
-pub use self::intrinsic::IntrinsicCallMethods;
-pub use self::misc::MiscMethods;
-pub use self::statics::{StaticBuilderMethods, StaticMethods};
+pub use self::debuginfo::{DebugInfoBuilderMethods, DebugInfoCodegenMethods};
+pub use self::declare::PreDefineCodegenMethods;
+pub use self::intrinsic::IntrinsicCallBuilderMethods;
+pub use self::misc::MiscCodegenMethods;
+pub use self::statics::{StaticBuilderMethods, StaticCodegenMethods};
 pub use self::type_::{
-    ArgAbiMethods, BaseTypeMethods, DerivedTypeMethods, LayoutTypeMethods, TypeMembershipMethods,
-    TypeMethods,
+    ArgAbiBuilderMethods, BaseTypeCodegenMethods, DerivedTypeCodegenMethods,
+    LayoutTypeCodegenMethods, TypeCodegenMethods, TypeMembershipCodegenMethods,
 };
 pub use self::write::{ModuleBufferMethods, ThinBufferMethods, WriteBackendMethods};
 
-pub trait CodegenObject: Copy + PartialEq + fmt::Debug {}
-impl<T: Copy + PartialEq + fmt::Debug> CodegenObject for T {}
-
-pub trait CodegenMethods<'tcx>:
-    Backend<'tcx>
-    + TypeMethods<'tcx>
-    + MiscMethods<'tcx>
-    + ConstMethods<'tcx>
-    + StaticMethods
-    + DebugInfoMethods<'tcx>
-    + AsmMethods<'tcx>
-    + PreDefineMethods<'tcx>
-    + HasParamEnv<'tcx>
-    + HasTyCtxt<'tcx>
-    + HasTargetSpec
-{
-}
-
-impl<'tcx, T> CodegenMethods<'tcx> for T where
-    Self: Backend<'tcx>
-        + TypeMethods<'tcx>
-        + MiscMethods<'tcx>
-        + ConstMethods<'tcx>
-        + StaticMethods
-        + DebugInfoMethods<'tcx>
-        + AsmMethods<'tcx>
-        + PreDefineMethods<'tcx>
-        + HasParamEnv<'tcx>
-        + HasTyCtxt<'tcx>
-        + HasTargetSpec
-{
-}
+pub trait CodegenObject = Copy + PartialEq + fmt::Debug;
 
-pub trait HasCodegen<'tcx>:
-    Backend<'tcx> + std::ops::Deref<Target = <Self as HasCodegen<'tcx>>::CodegenCx>
-{
-    type CodegenCx: CodegenMethods<'tcx>
-        + BackendTypes<
-            Value = Self::Value,
-            Function = Self::Function,
-            BasicBlock = Self::BasicBlock,
-            Type = Self::Type,
-            Funclet = Self::Funclet,
-            DIScope = Self::DIScope,
-            DILocation = Self::DILocation,
-            DIVariable = Self::DIVariable,
-        >;
-}
+pub trait CodegenMethods<'tcx> = LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>>
+    + FnAbiOf<'tcx, FnAbiOfResult = &'tcx FnAbi<'tcx, Ty<'tcx>>>
+    + TypeCodegenMethods<'tcx>
+    + ConstCodegenMethods<'tcx>
+    + StaticCodegenMethods
+    + DebugInfoCodegenMethods<'tcx>
+    + AsmCodegenMethods<'tcx>
+    + PreDefineCodegenMethods<'tcx>;
diff --git a/compiler/rustc_codegen_ssa/src/traits/statics.rs b/compiler/rustc_codegen_ssa/src/traits/statics.rs
index b418199e616..c10733fb0ed 100644
--- a/compiler/rustc_codegen_ssa/src/traits/statics.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/statics.rs
@@ -3,7 +3,7 @@ use rustc_target::abi::Align;
 
 use super::BackendTypes;
 
-pub trait StaticMethods: BackendTypes {
+pub trait StaticCodegenMethods: BackendTypes {
     fn static_addr_of(&self, cv: Self::Value, align: Align, kind: Option<&str>) -> Self::Value;
     fn codegen_static(&self, def_id: DefId);
 
diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs
index 7c042c0c621..f6f309287fe 100644
--- a/compiler/rustc_codegen_ssa/src/traits/type_.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs
@@ -1,17 +1,15 @@
 use rustc_middle::bug;
-use rustc_middle::ty::layout::TyAndLayout;
+use rustc_middle::ty::layout::{HasTyCtxt, TyAndLayout};
 use rustc_middle::ty::{self, Ty};
 use rustc_target::abi::call::{ArgAbi, CastTarget, FnAbi, Reg};
 use rustc_target::abi::{AddressSpace, Float, Integer};
 
-use super::misc::MiscMethods;
-use super::{Backend, HasCodegen};
+use super::misc::MiscCodegenMethods;
+use super::BackendTypes;
 use crate::common::TypeKind;
 use crate::mir::place::PlaceRef;
 
-// This depends on `Backend` and not `BackendTypes`, because consumers will probably want to use
-// `LayoutOf` or `HasTyCtxt`. This way, they don't have to add a constraint on it themselves.
-pub trait BaseTypeMethods<'tcx>: Backend<'tcx> {
+pub trait BaseTypeCodegenMethods<'tcx>: BackendTypes {
     fn type_i8(&self) -> Self::Type;
     fn type_i16(&self) -> Self::Type;
     fn type_i32(&self) -> Self::Type;
@@ -42,7 +40,9 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> {
     fn val_ty(&self, v: Self::Value) -> Self::Type;
 }
 
-pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {
+pub trait DerivedTypeCodegenMethods<'tcx>:
+    BaseTypeCodegenMethods<'tcx> + MiscCodegenMethods<'tcx> + HasTyCtxt<'tcx>
+{
     fn type_int(&self) -> Self::Type {
         match &self.sess().target.c_int_width[..] {
             "16" => self.type_i16(),
@@ -100,9 +100,12 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {
     }
 }
 
-impl<'tcx, T> DerivedTypeMethods<'tcx> for T where Self: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {}
+impl<'tcx, T> DerivedTypeCodegenMethods<'tcx> for T where
+    Self: BaseTypeCodegenMethods<'tcx> + MiscCodegenMethods<'tcx> + HasTyCtxt<'tcx>
+{
+}
 
-pub trait LayoutTypeMethods<'tcx>: Backend<'tcx> {
+pub trait LayoutTypeCodegenMethods<'tcx>: BackendTypes {
     /// The backend type used for a rust type when it's in memory,
     /// such as when it's stack-allocated or when it's being loaded or stored.
     fn backend_type(&self, layout: TyAndLayout<'tcx>) -> Self::Type;
@@ -114,7 +117,7 @@ pub trait LayoutTypeMethods<'tcx>: Backend<'tcx> {
     ///
     /// For nearly all types this is the same as the [`Self::backend_type`], however
     /// `bool` (and other `0`-or-`1` values) are kept as `i1` in registers but as
-    /// [`BaseTypeMethods::type_i8`] in memory.
+    /// [`BaseTypeCodegenMethods::type_i8`] in memory.
     ///
     /// Converting values between the two different backend types is done using
     /// [`from_immediate`](super::BuilderMethods::from_immediate) and
@@ -146,7 +149,7 @@ pub trait LayoutTypeMethods<'tcx>: Backend<'tcx> {
 
 // For backends that support CFI using type membership (i.e., testing whether a given pointer is
 // associated with a type identifier).
-pub trait TypeMembershipMethods<'tcx>: Backend<'tcx> {
+pub trait TypeMembershipCodegenMethods<'tcx>: BackendTypes {
     fn add_type_metadata(&self, _function: Self::Function, _typeid: String) {}
     fn set_type_metadata(&self, _function: Self::Function, _typeid: String) {}
     fn typeid_metadata(&self, _typeid: String) -> Option<Self::Value> {
@@ -156,7 +159,7 @@ pub trait TypeMembershipMethods<'tcx>: Backend<'tcx> {
     fn set_kcfi_type_metadata(&self, _function: Self::Function, _typeid: u32) {}
 }
 
-pub trait ArgAbiMethods<'tcx>: HasCodegen<'tcx> {
+pub trait ArgAbiBuilderMethods<'tcx>: BackendTypes {
     fn store_fn_arg(
         &mut self,
         arg_abi: &ArgAbi<'tcx, Ty<'tcx>>,
@@ -172,12 +175,6 @@ pub trait ArgAbiMethods<'tcx>: HasCodegen<'tcx> {
     fn arg_memory_ty(&self, arg_abi: &ArgAbi<'tcx, Ty<'tcx>>) -> Self::Type;
 }
 
-pub trait TypeMethods<'tcx>:
-    DerivedTypeMethods<'tcx> + LayoutTypeMethods<'tcx> + TypeMembershipMethods<'tcx>
-{
-}
-
-impl<'tcx, T> TypeMethods<'tcx> for T where
-    Self: DerivedTypeMethods<'tcx> + LayoutTypeMethods<'tcx> + TypeMembershipMethods<'tcx>
-{
-}
+pub trait TypeCodegenMethods<'tcx> = DerivedTypeCodegenMethods<'tcx>
+    + LayoutTypeCodegenMethods<'tcx>
+    + TypeMembershipCodegenMethods<'tcx>;
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 6a691abae02..9daee12ca2e 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -641,7 +641,14 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
                 // current number of evaluated terminators is a power of 2. The latter gives us a cheap
                 // way to implement exponential backoff.
                 let span = ecx.cur_span();
-                ecx.tcx.dcx().emit_warn(LongRunningWarn { span, item_span: ecx.tcx.span });
+                // We store a unique number in `force_duplicate` to evade `-Z deduplicate-diagnostics`.
+                // `new_steps` is guaranteed to be unique because `ecx.machine.num_evaluated_steps` is
+                // always increasing.
+                ecx.tcx.dcx().emit_warn(LongRunningWarn {
+                    span,
+                    item_span: ecx.tcx.span,
+                    force_duplicate: new_steps,
+                });
             }
         }
 
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index b66b5c0a00a..06ae5b30be0 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -209,6 +209,8 @@ pub struct LongRunningWarn {
     pub span: Span,
     #[help]
     pub item_span: Span,
+    // Used for evading `-Z deduplicate-diagnostics`.
+    pub force_duplicate: usize,
 }
 
 #[derive(Subdiagnostic)]
diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs
index 0f2b22f035b..97f7242b336 100644
--- a/compiler/rustc_const_eval/src/interpret/call.rs
+++ b/compiler/rustc_const_eval/src/interpret/call.rs
@@ -234,6 +234,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         // so we implement a type-based check that reflects the guaranteed rules for ABI compatibility.
         if self.layout_compat(caller_abi.layout, callee_abi.layout)? {
             // Ensure that our checks imply actual ABI compatibility for this concrete call.
+            // (This can fail e.g. if `#[rustc_nonnull_optimization_guaranteed]` is used incorrectly.)
             assert!(caller_abi.eq_abi(callee_abi));
             Ok(true)
         } else {
diff --git a/compiler/rustc_driver_impl/src/signal_handler.rs b/compiler/rustc_driver_impl/src/signal_handler.rs
index e1f868c2522..411661824f0 100644
--- a/compiler/rustc_driver_impl/src/signal_handler.rs
+++ b/compiler/rustc_driver_impl/src/signal_handler.rs
@@ -35,6 +35,8 @@ macro raw_errln($tokens:tt) {
 }
 
 /// Signal handler installed for SIGSEGV
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#[allow(static_mut_refs)]
 extern "C" fn print_stack_trace(_: libc::c_int) {
     const MAX_FRAMES: usize = 256;
     // Reserve data segment so we don't have to malloc in a signal handler, which might fail
diff --git a/compiler/rustc_error_codes/src/error_codes/E0775.md b/compiler/rustc_error_codes/src/error_codes/E0775.md
index 9bafd52f75c..efbd51e89ea 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0775.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0775.md
@@ -1,13 +1,14 @@
+#### Note: this error code is no longer emitted by the compiler.
+
 `#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M
 extension.
 
 Erroneous code example:
 
-```compile_fail,E0775
+```ignore (no longer emitted)
 #![feature(cmse_nonsecure_entry)]
 
-#[cmse_nonsecure_entry]
-pub extern "C" fn entry_function() {}
+pub extern "C-cmse-nonsecure-entry" fn entry_function() {}
 ```
 
 To fix this error, compile your code for a Rust target that supports the
diff --git a/compiler/rustc_error_codes/src/error_codes/E0776.md b/compiler/rustc_error_codes/src/error_codes/E0776.md
index d65beebe07c..e46d498d1c2 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0776.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0776.md
@@ -1,8 +1,10 @@
+#### Note: this error code is no longer emitted by the compiler.
+
 `#[cmse_nonsecure_entry]` functions require a C ABI
 
 Erroneous code example:
 
-```compile_fail,E0776
+```ignore (no longer emitted)
 #![feature(cmse_nonsecure_entry)]
 
 #[no_mangle]
diff --git a/compiler/rustc_error_codes/src/error_codes/E0796.md b/compiler/rustc_error_codes/src/error_codes/E0796.md
index 7ac429e5215..ced163e98f7 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0796.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0796.md
@@ -1,14 +1,14 @@
+#### Note: this error code is no longer emitted by the compiler.
+
 You have created a reference to a mutable static.
 
 Erroneous code example:
 
-```compile_fail,edition2024,E0796
+```
 static mut X: i32 = 23;
-
 fn work() {
   let _val = unsafe { X };
 }
-
 let x_ref = unsafe { &mut X };
 work();
 // The next line has Undefined Behavior!
diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs
index d6f0206b0de..8631de65ec8 100644
--- a/compiler/rustc_error_codes/src/lib.rs
+++ b/compiler/rustc_error_codes/src/lib.rs
@@ -681,3 +681,5 @@ E0800: 0800,
 //  E0723, // unstable feature in `const` context
 //  E0738, // Removed; errored on `#[track_caller] fn`s in `extern "Rust" { ... }`.
 //  E0744, // merged into E0728
+//  E0776, // Removed; cmse_nonsecure_entry is now `C-cmse-nonsecure-entry`
+//  E0796, // unused error code. We use `static_mut_refs` lint instead.
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 094e3010471..59866012069 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -571,6 +571,8 @@ pub enum StashKey {
     /// Query cycle detected, stashing in favor of a better error.
     Cycle,
     UndeterminedMacroResolution,
+    /// Used by `Parser::maybe_recover_trailing_expr`
+    ExprInPat,
 }
 
 fn default_track_diagnostic<R>(diag: DiagInner, f: &mut dyn FnMut(DiagInner) -> R) -> R {
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 0d56a005f15..84ae351ed72 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -41,7 +41,9 @@ use crate::errors::{
 };
 use crate::fluent_generated;
 use crate::mbe::diagnostics::annotate_err_with_kind;
-use crate::module::{mod_dir_path, parse_external_mod, DirOwnership, ParsedExternalMod};
+use crate::module::{
+    mod_dir_path, mod_file_path_from_attr, parse_external_mod, DirOwnership, ParsedExternalMod,
+};
 use crate::placeholders::{placeholder, PlaceholderExpander};
 
 macro_rules! ast_fragments {
@@ -1202,8 +1204,14 @@ impl InvocationCollectorNode for P<ast::Item> {
                     ecx.current_expansion.dir_ownership,
                     *inline,
                 );
+                // If the module was parsed from an external file, recover its path.
+                // This lets `parse_external_mod` catch cycles if it's self-referential.
+                let file_path = match inline {
+                    Inline::Yes => None,
+                    Inline::No => mod_file_path_from_attr(ecx.sess, &attrs, &dir_path),
+                };
                 node.attrs = attrs;
-                (None, dir_path, dir_ownership)
+                (file_path, dir_path, dir_ownership)
             }
             ModKind::Unloaded => {
                 // We have an outline `mod foo;` so we need to parse the file.
diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs
index 13348376851..27a9a330f3c 100644
--- a/compiler/rustc_expand/src/module.rs
+++ b/compiler/rustc_expand/src/module.rs
@@ -171,7 +171,7 @@ fn mod_file_path<'a>(
 
 /// Derive a submodule path from the first found `#[path = "path_string"]`.
 /// The provided `dir_path` is joined with the `path_string`.
-fn mod_file_path_from_attr(
+pub(crate) fn mod_file_path_from_attr(
     sess: &Session,
     attrs: &[Attribute],
     dir_path: &Path,
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 3b7e0d82d0f..efb582fde1b 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -551,10 +551,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         EncodeCrossCrate::No, experimental!(register_tool),
     ),
 
-    gated!(
-        cmse_nonsecure_entry, Normal, template!(Word), WarnFollowing,
-        EncodeCrossCrate::No, experimental!(cmse_nonsecure_entry)
-    ),
     // RFC 2632
     gated!(
         const_trait, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No, const_trait_impl,
@@ -863,8 +859,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     rustc_attr!(
         rustc_nonnull_optimization_guaranteed, Normal, template!(Word), WarnFollowing,
         EncodeCrossCrate::Yes,
-        "the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable \
-        niche optimizations in libcore and libstd and will never be stable",
+        "the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to document \
+        guaranteed niche optimizations in libcore and libstd and will never be stable\n\
+        (note that the compiler does not even check whether the type indeed is being non-null-optimized; \
+        it is your responsibility to ensure that the attribute is only used on types that are optimized)",
     ),
 
     // ==========================================================================
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index d0c0460ddfe..edc8e5f0752 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -204,7 +204,7 @@ declare_features! (
     /// Changes `impl Trait` to capture all lifetimes in scope.
     (unstable, lifetime_capture_rules_2024, "1.76.0", None),
     /// Allows `#[link(..., cfg(..))]`; perma-unstable per #37406
-    (unstable, link_cfg, "1.14.0", None),
+    (internal, link_cfg, "1.14.0", None),
     /// Allows using `?Trait` trait bounds in more contexts.
     (internal, more_maybe_bounds, "1.82.0", None),
     /// Allows the `multiple_supertrait_upcastable` lint.
@@ -395,7 +395,7 @@ declare_features! (
     (unstable, closure_lifetime_binder, "1.64.0", Some(97362)),
     /// Allows `#[track_caller]` on closures and coroutines.
     (unstable, closure_track_caller, "1.57.0", Some(87417)),
-    /// Allows to use the `#[cmse_nonsecure_entry]` attribute.
+    /// Allows `extern "C-cmse-nonsecure-entry" fn()`.
     (unstable, cmse_nonsecure_entry, "1.48.0", Some(75835)),
     /// Allows `async {}` expressions in const contexts.
     (unstable, const_async_blocks, "1.53.0", Some(85368)),
@@ -558,6 +558,8 @@ declare_features! (
     (unstable, optimize_attribute, "1.34.0", Some(54882)),
     /// Allows specifying nop padding on functions for dynamic patching.
     (unstable, patchable_function_entry, "1.81.0", Some(123115)),
+    /// Experimental features that make `Pin` more ergonomic.
+    (incomplete, pin_ergonomics, "CURRENT_RUSTC_VERSION", Some(130494)),
     /// Allows postfix match `expr.match { ... }`
     (unstable, postfix_match, "1.79.0", Some(121618)),
     /// Allows macro attributes on expressions, statements and non-inline modules.
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 26118bcbb9f..f92c6650355 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1378,7 +1378,8 @@ pub struct LetStmt<'hir> {
     pub hir_id: HirId,
     pub span: Span,
     /// Can be `ForLoopDesugar` if the `let` statement is part of a `for` loop
-    /// desugaring. Otherwise will be `Normal`.
+    /// desugaring, or `AssignDesugar` if it is the result of a complex
+    /// assignment desugaring. Otherwise will be `Normal`.
     pub source: LocalSource,
 }
 
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index bde94be6f51..09d466339ff 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -37,7 +37,7 @@ hir_analysis_assoc_kind_mismatch = expected {$expected}, found {$got}
 
 hir_analysis_assoc_kind_mismatch_wrap_in_braces_sugg = consider adding braces here
 
-hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated type of a trait with uninferred generic parameters
+hir_analysis_associated_type_trait_uninferred_generic_params = cannot use the associated {$what} of a trait with uninferred generic parameters
     .suggestion = use a fully qualified path with inferred lifetimes
 
 hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion = use a fully qualified path with explicit lifetimes
@@ -48,6 +48,8 @@ hir_analysis_auto_deref_reached_recursion_limit = reached the recursion limit wh
 
 hir_analysis_bad_precise_capture = expected {$kind} parameter in `use<...>` precise captures list, found {$found}
 
+hir_analysis_bad_return_type_notation_position = return type notation not allowed in this position yet
+
 hir_analysis_cannot_capture_late_bound_const =
     cannot capture late-bound const parameter in {$what}
     .label = parameter defined here
@@ -467,25 +469,6 @@ hir_analysis_start_not_target_feature = `#[start]` function is not allowed to ha
 hir_analysis_start_not_track_caller = `#[start]` function is not allowed to be `#[track_caller]`
     .label = `#[start]` function is not allowed to be `#[track_caller]`
 
-hir_analysis_static_mut_ref = creating a {$shared} reference to a mutable static
-    .label = {$shared} reference to mutable static
-    .note = {$shared ->
-        [shared] this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
-        *[mutable] 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
-    }
-    .suggestion = use `addr_of!` instead to create a raw pointer
-    .suggestion_mut = use `addr_of_mut!` instead to create a raw pointer
-
-hir_analysis_static_mut_refs_lint = creating a {$shared} reference to mutable static is discouraged
-    .label = {$shared} reference to mutable static
-    .suggestion = use `addr_of!` instead to create a raw pointer
-    .suggestion_mut = use `addr_of_mut!` instead to create a raw pointer
-    .note = this will be a hard error in the 2024 edition
-    .why_note = {$shared ->
-        [shared] this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
-        *[mutable] 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
-    }
-
 hir_analysis_static_specialize = cannot specialize on `'static` lifetime
 
 hir_analysis_tait_forward_compat = item constrains opaque type that is not in its signature
@@ -497,7 +480,7 @@ hir_analysis_tait_forward_compat2 = item does not constrain `{$opaque_type}`, bu
 
 hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]`
 
-hir_analysis_too_large_static = extern static is too large for the current architecture
+hir_analysis_too_large_static = extern static is too large for the target architecture
 
 hir_analysis_track_caller_on_main = `main` function is not allowed to be `#[track_caller]`
     .suggestion = remove this annotation
diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs
index d0b0c08aa79..14ea7816291 100644
--- a/compiler/rustc_hir_analysis/src/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/bounds.rs
@@ -9,6 +9,8 @@ use rustc_middle::ty::{self, Ty, TyCtxt, Upcast};
 use rustc_span::def_id::DefId;
 use rustc_span::Span;
 
+use crate::hir_ty_lowering::OnlySelfBounds;
+
 /// Collects together a list of type bounds. These lists of bounds occur in many places
 /// in Rust's syntax:
 ///
@@ -50,6 +52,7 @@ impl<'tcx> Bounds<'tcx> {
         span: Span,
         polarity: ty::PredicatePolarity,
         constness: ty::BoundConstness,
+        only_self_bounds: OnlySelfBounds,
     ) {
         let clause = (
             bound_trait_ref
@@ -66,7 +69,10 @@ impl<'tcx> Bounds<'tcx> {
             self.clauses.push(clause);
         }
 
-        if !tcx.features().effects {
+        // FIXME(effects): Lift this out of `push_trait_bound`, and move it somewhere else.
+        // Perhaps moving this into `lower_poly_trait_ref`, just like we lower associated
+        // type bounds.
+        if !tcx.features().effects || only_self_bounds.0 {
             return;
         }
         // For `T: ~const Tr` or `T: const Tr`, we need to add an additional bound on the
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index dbdad2eb41d..3a7366ef78a 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -66,7 +66,6 @@ mod check;
 mod compare_impl_item;
 pub mod dropck;
 mod entry;
-mod errs;
 pub mod intrinsic;
 pub mod intrinsicck;
 mod region;
diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs
index 33e58a92e37..1a5f4659812 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -20,8 +20,6 @@ use rustc_middle::ty::TyCtxt;
 use rustc_span::source_map;
 use tracing::debug;
 
-use super::errs::{maybe_expr_static_mut, maybe_stmt_static_mut};
-
 #[derive(Debug, Copy, Clone)]
 struct Context {
     /// The scope that contains any new variables declared, plus its depth in
@@ -229,8 +227,6 @@ fn resolve_stmt<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, stmt: &'tcx h
     let stmt_id = stmt.hir_id.local_id;
     debug!("resolve_stmt(stmt.id={:?})", stmt_id);
 
-    maybe_stmt_static_mut(visitor.tcx, *stmt);
-
     // Every statement will clean up the temporaries created during
     // execution of that statement. Therefore each statement has an
     // associated destruction scope that represents the scope of the
@@ -249,8 +245,6 @@ fn resolve_stmt<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, stmt: &'tcx h
 fn resolve_expr<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
     debug!("resolve_expr - pre-increment {} expr = {:?}", visitor.expr_and_pat_count, expr);
 
-    maybe_expr_static_mut(visitor.tcx, *expr);
-
     let prev_cx = visitor.cx;
     visitor.enter_node_scope_with_dtor(expr.hir_id.local_id);
 
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index ac9976148e2..4c59f7540ee 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -460,7 +460,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
                                 [] => (generics.span, format!("<{lt_name}>")),
                                 [bound, ..] => (bound.span.shrink_to_lo(), format!("{lt_name}, ")),
                             };
-                            mpart_sugg = Some(errors::AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion {
+                            mpart_sugg = Some(errors::AssociatedItemTraitUninferredGenericParamsMultipartSuggestion {
                                 fspan: lt_sp,
                                 first: sugg,
                                 sspan: span.with_hi(item_segment.ident.span.lo()),
@@ -502,11 +502,12 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> {
             }
             Ty::new_error(
                 self.tcx(),
-                self.tcx().dcx().emit_err(errors::AssociatedTypeTraitUninferredGenericParams {
+                self.tcx().dcx().emit_err(errors::AssociatedItemTraitUninferredGenericParams {
                     span,
                     inferred_sugg,
                     bound,
                     mpart_sugg,
+                    what: "type",
                 }),
             )
         }
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index d62727e76b5..7a254c884c2 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -10,6 +10,7 @@ use rustc_span::Span;
 use rustc_type_ir::Upcast;
 use tracing::{debug, instrument};
 
+use super::predicates_of::assert_only_contains_predicates_from;
 use super::ItemCtxt;
 use crate::hir_ty_lowering::{HirTyLowerer, PredicateFilter};
 
@@ -56,6 +57,9 @@ fn associated_type_bounds<'tcx>(
         tcx.def_path_str(assoc_item_def_id.to_def_id()),
         all_bounds
     );
+
+    assert_only_contains_predicates_from(filter, all_bounds, item_ty);
+
     all_bounds
 }
 
@@ -108,18 +112,21 @@ pub(super) fn explicit_item_bounds_with_filter(
         Some(ty::ImplTraitInTraitData::Trait { opaque_def_id, .. }) => {
             let item = tcx.hir_node_by_def_id(opaque_def_id.expect_local()).expect_item();
             let opaque_ty = item.expect_opaque_ty();
-            return ty::EarlyBinder::bind(opaque_type_bounds(
+            let item_ty = Ty::new_projection_from_args(
+                tcx,
+                def_id.to_def_id(),
+                ty::GenericArgs::identity_for_item(tcx, def_id),
+            );
+            let bounds = opaque_type_bounds(
                 tcx,
                 opaque_def_id.expect_local(),
                 opaque_ty.bounds,
-                Ty::new_projection_from_args(
-                    tcx,
-                    def_id.to_def_id(),
-                    ty::GenericArgs::identity_for_item(tcx, def_id),
-                ),
+                item_ty,
                 item.span,
                 filter,
-            ));
+            );
+            assert_only_contains_predicates_from(filter, bounds, item_ty);
+            return ty::EarlyBinder::bind(bounds);
         }
         Some(ty::ImplTraitInTraitData::Impl { .. }) => span_bug!(
             tcx.def_span(def_id),
@@ -167,7 +174,9 @@ pub(super) fn explicit_item_bounds_with_filter(
         }) => {
             let args = GenericArgs::identity_for_item(tcx, def_id);
             let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
-            opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter)
+            let bounds = opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter);
+            assert_only_contains_predicates_from(filter, bounds, item_ty);
+            bounds
         }
         // Since RPITITs are lowered as projections in `<dyn HirTyLowerer>::lower_ty`, when we're
         // asking for the item bounds of the *opaques* in a trait's default method signature, we
@@ -184,15 +193,18 @@ pub(super) fn explicit_item_bounds_with_filter(
             };
             let args = GenericArgs::identity_for_item(tcx, def_id);
             let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), args);
-            tcx.arena.alloc_slice(
+            let bounds = &*tcx.arena.alloc_slice(
                 &opaque_type_bounds(tcx, def_id, bounds, item_ty, *span, filter)
                     .to_vec()
                     .fold_with(&mut AssocTyToOpaque { tcx, fn_def_id: fn_def_id.to_def_id() }),
-            )
+            );
+            assert_only_contains_predicates_from(filter, bounds, item_ty);
+            bounds
         }
         hir::Node::Item(hir::Item { kind: hir::ItemKind::TyAlias(..), .. }) => &[],
         _ => bug!("item_bounds called on {:?}", def_id),
     };
+
     ty::EarlyBinder::bind(bounds)
 }
 
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 7243e85ce98..67d8813d1f7 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -240,7 +240,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
     for predicate in hir_generics.predicates {
         match predicate {
             hir::WherePredicate::BoundPredicate(bound_pred) => {
-                let ty = icx.lower_ty(bound_pred.bounded_ty);
+                let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty);
+
                 let bound_vars = tcx.late_bound_vars(bound_pred.hir_id);
                 // Keep the type around in a dummy predicate, in case of no bounds.
                 // That way, `where Ty:` is not a complete noop (see #53696) and `Ty`
@@ -676,9 +677,63 @@ pub(super) fn implied_predicates_with_filter<'tcx>(
         _ => {}
     }
 
+    assert_only_contains_predicates_from(filter, implied_bounds, tcx.types.self_param);
+
     ty::EarlyBinder::bind(implied_bounds)
 }
 
+// Make sure when elaborating supertraits, probing for associated types, etc.,
+// we really truly are elaborating clauses that have `Self` as their self type.
+// This is very important since downstream code relies on this being correct.
+pub(super) fn assert_only_contains_predicates_from<'tcx>(
+    filter: PredicateFilter,
+    bounds: &'tcx [(ty::Clause<'tcx>, Span)],
+    ty: Ty<'tcx>,
+) {
+    if !cfg!(debug_assertions) {
+        return;
+    }
+
+    match filter {
+        PredicateFilter::SelfOnly | PredicateFilter::SelfThatDefines(_) => {
+            for (clause, _) in bounds {
+                match clause.kind().skip_binder() {
+                    ty::ClauseKind::Trait(trait_predicate) => {
+                        assert_eq!(
+                            trait_predicate.self_ty(),
+                            ty,
+                            "expected `Self` predicate when computing `{filter:?}` implied bounds: {clause:?}"
+                        );
+                    }
+                    ty::ClauseKind::Projection(projection_predicate) => {
+                        assert_eq!(
+                            projection_predicate.self_ty(),
+                            ty,
+                            "expected `Self` predicate when computing `{filter:?}` implied bounds: {clause:?}"
+                        );
+                    }
+                    ty::ClauseKind::TypeOutlives(outlives_predicate) => {
+                        assert_eq!(
+                            outlives_predicate.0, ty,
+                            "expected `Self` predicate when computing `{filter:?}` implied bounds: {clause:?}"
+                        );
+                    }
+
+                    ty::ClauseKind::RegionOutlives(_)
+                    | ty::ClauseKind::ConstArgHasType(_, _)
+                    | ty::ClauseKind::WellFormed(_)
+                    | ty::ClauseKind::ConstEvaluatable(_) => {
+                        bug!(
+                            "unexpected non-`Self` predicate when computing `{filter:?}` implied bounds: {clause:?}"
+                        );
+                    }
+                }
+            }
+        }
+        PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {}
+    }
+}
+
 /// Returns the predicates defined on `item_def_id` of the form
 /// `X: Foo` where `X` is the type parameter `def_id`.
 #[instrument(level = "trace", skip(tcx))]
@@ -770,6 +825,10 @@ impl<'tcx> ItemCtxt<'tcx> {
                 continue;
             };
 
+            // Subtle: If we're collecting `SelfAndAssociatedTypeBounds`, then we
+            // want to only consider predicates with `Self: ...`, but we don't want
+            // `OnlySelfBounds(true)` since we want to collect the nested associated
+            // type bound as well.
             let (only_self_bounds, assoc_name) = match filter {
                 PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
                     (OnlySelfBounds(false), None)
@@ -780,14 +839,10 @@ impl<'tcx> ItemCtxt<'tcx> {
                 }
             };
 
-            // Subtle: If we're collecting `SelfAndAssociatedTypeBounds`, then we
-            // want to only consider predicates with `Self: ...`, but we don't want
-            // `OnlySelfBounds(true)` since we want to collect the nested associated
-            // type bound as well.
             let bound_ty = if predicate.is_param_bound(param_def_id.to_def_id()) {
                 ty
             } else if matches!(filter, PredicateFilter::All) {
-                self.lower_ty(predicate.bounded_ty)
+                self.lowerer().lower_ty_maybe_return_type_notation(predicate.bounded_ty)
             } else {
                 continue;
             };
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 53dcede91c3..d1601446b6f 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -889,7 +889,12 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
                             (pair, r)
                         })
                         .unzip();
+
                 self.record_late_bound_vars(hir_id, binders);
+
+                // If this is an RTN type in the self type, then append those to the binder.
+                self.try_append_return_type_notation_params(hir_id, bounded_ty);
+
                 // Even if there are no lifetimes defined here, we still wrap it in a binder
                 // scope. If there happens to be a nested poly trait ref (an error), that
                 // will be `Concatenating` anyways, so we don't have to worry about the depth
@@ -1635,9 +1640,9 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
             // }
             // ```
             // and a bound that looks like:
-            //    `for<'a> T::Trait<'a, x(): for<'b> Other<'b>>`
+            //    `for<'a> T::Trait<'a, x(..): for<'b> Other<'b>>`
             // this is going to expand to something like:
-            //    `for<'a> for<'r, T> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: for<'b> Other<'b>`.
+            //    `for<'a> for<'r> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: for<'b> Other<'b>`.
             if constraint.gen_args.parenthesized == hir::GenericArgsParentheses::ReturnTypeNotation
             {
                 let bound_vars = if let Some(type_def_id) = type_def_id
@@ -1839,6 +1844,178 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> {
         let old_value = self.map.defs.swap_remove(&lifetime_ref.hir_id);
         assert_eq!(old_value, Some(bad_def));
     }
+
+    // When we have a return type notation type in a where clause, like
+    // `where <T as Trait>::method(..): Send`, we need to introduce new bound
+    // vars to the existing where clause's binder, to represent the lifetimes
+    // elided by the return-type-notation syntax.
+    //
+    // For example, given
+    // ```
+    // trait Foo {
+    //     async fn x<'r>();
+    // }
+    // ```
+    // and a bound that looks like:
+    //    `for<'a, 'b> <T as Trait<'a>>::x(): Other<'b>`
+    // this is going to expand to something like:
+    //    `for<'a, 'b, 'r> <T as Trait<'a>>::x::<'r, T>::{opaque#0}: Other<'b>`.
+    //
+    // We handle this similarly for associated-type-bound style return-type-notation
+    // in `visit_segment_args`.
+    fn try_append_return_type_notation_params(
+        &mut self,
+        hir_id: HirId,
+        hir_ty: &'tcx hir::Ty<'tcx>,
+    ) {
+        let hir::TyKind::Path(qpath) = hir_ty.kind else {
+            // We only care about path types here. All other self types
+            // (including nesting the RTN type in another type) don't do
+            // anything.
+            return;
+        };
+
+        let (mut bound_vars, item_def_id, item_segment) = match qpath {
+            // If we have a fully qualified method, then we don't need to do any special lookup.
+            hir::QPath::Resolved(_, path)
+                if let [.., item_segment] = &path.segments[..]
+                    && item_segment.args.is_some_and(|args| {
+                        matches!(
+                            args.parenthesized,
+                            hir::GenericArgsParentheses::ReturnTypeNotation
+                        )
+                    }) =>
+            {
+                match path.res {
+                    Res::Err => return,
+                    Res::Def(DefKind::AssocFn, item_def_id) => (vec![], item_def_id, item_segment),
+                    _ => bug!("only expected method resolution for fully qualified RTN"),
+                }
+            }
+
+            // If we have a type-dependent path, then we do need to do some lookup.
+            hir::QPath::TypeRelative(qself, item_segment)
+                if item_segment.args.is_some_and(|args| {
+                    matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
+                }) =>
+            {
+                // First, ignore a qself that isn't a type or `Self` param. Those are the
+                // only ones that support `T::Assoc` anyways in HIR lowering.
+                let hir::TyKind::Path(hir::QPath::Resolved(None, path)) = qself.kind else {
+                    return;
+                };
+                match path.res {
+                    Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { trait_: _ } => {
+                        // Get the generics of this type's hir owner. This is *different*
+                        // from the generics of the parameter's definition, since we want
+                        // to be able to resolve an RTN path on a nested body (e.g. method
+                        // inside an impl) using the where clauses on the method.
+                        // FIXME(return_type_notation): Think of some better way of doing this.
+                        let Some(generics) = self.tcx.hir_owner_node(hir_id.owner).generics()
+                        else {
+                            return;
+                        };
+
+                        // Look for the first bound that contains an associated type that
+                        // matches the segment that we're looking for. We ignore any subsequent
+                        // bounds since we'll be emitting a hard error in HIR lowering, so this
+                        // is purely speculative.
+                        let one_bound = generics.predicates.iter().find_map(|predicate| {
+                            let hir::WherePredicate::BoundPredicate(predicate) = predicate else {
+                                return None;
+                            };
+                            let hir::TyKind::Path(hir::QPath::Resolved(None, bounded_path)) =
+                                predicate.bounded_ty.kind
+                            else {
+                                return None;
+                            };
+                            if bounded_path.res != path.res {
+                                return None;
+                            }
+                            predicate.bounds.iter().find_map(|bound| {
+                                let hir::GenericBound::Trait(trait_, _) = bound else {
+                                    return None;
+                                };
+                                BoundVarContext::supertrait_hrtb_vars(
+                                    self.tcx,
+                                    trait_.trait_ref.trait_def_id()?,
+                                    item_segment.ident,
+                                    ty::AssocKind::Fn,
+                                )
+                            })
+                        });
+                        let Some((bound_vars, assoc_item)) = one_bound else {
+                            return;
+                        };
+                        (bound_vars, assoc_item.def_id, item_segment)
+                    }
+                    // If we have a self type alias (in an impl), try to resolve an
+                    // associated item from one of the supertraits of the impl's trait.
+                    Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. } => {
+                        let hir::ItemKind::Impl(hir::Impl { of_trait: Some(trait_ref), .. }) = self
+                            .tcx
+                            .hir_node_by_def_id(impl_def_id.expect_local())
+                            .expect_item()
+                            .kind
+                        else {
+                            return;
+                        };
+                        let Some(trait_def_id) = trait_ref.trait_def_id() else {
+                            return;
+                        };
+                        let Some((bound_vars, assoc_item)) = BoundVarContext::supertrait_hrtb_vars(
+                            self.tcx,
+                            trait_def_id,
+                            item_segment.ident,
+                            ty::AssocKind::Fn,
+                        ) else {
+                            return;
+                        };
+                        (bound_vars, assoc_item.def_id, item_segment)
+                    }
+                    _ => return,
+                }
+            }
+
+            _ => return,
+        };
+
+        // Append the early-bound vars on the function, and then the late-bound ones.
+        // We actually turn type parameters into higher-ranked types here, but we
+        // deny them later in HIR lowering.
+        bound_vars.extend(self.tcx.generics_of(item_def_id).own_params.iter().map(|param| {
+            match param.kind {
+                ty::GenericParamDefKind::Lifetime => ty::BoundVariableKind::Region(
+                    ty::BoundRegionKind::BrNamed(param.def_id, param.name),
+                ),
+                ty::GenericParamDefKind::Type { .. } => {
+                    ty::BoundVariableKind::Ty(ty::BoundTyKind::Param(param.def_id, param.name))
+                }
+                ty::GenericParamDefKind::Const { .. } => ty::BoundVariableKind::Const,
+            }
+        }));
+        bound_vars.extend(self.tcx.fn_sig(item_def_id).instantiate_identity().bound_vars());
+
+        // SUBTLE: Stash the old bound vars onto the *item segment* before appending
+        // the new bound vars. We do this because we need to know how many bound vars
+        // are present on the binder explicitly (i.e. not return-type-notation vars)
+        // to do bound var shifting correctly in HIR lowering.
+        //
+        // For example, in `where for<'a> <T as Trait<'a>>::method(..): Other`,
+        // the `late_bound_vars` of the where clause predicate (i.e. this HIR ty's
+        // parent) will include `'a` AND all the early- and late-bound vars of the
+        // method. But when lowering the RTN type, we just want the list of vars
+        // we used to resolve the trait ref. We explicitly stored those back onto
+        // the item segment, since there's no other good place to put them.
+        //
+        // See where these vars are used in `HirTyLowerer::lower_ty_maybe_return_type_notation`.
+        // And this is exercised in:
+        // `tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.rs`.
+        let existing_bound_vars = self.map.late_bound_vars.get_mut(&hir_id).unwrap();
+        let existing_bound_vars_saved = existing_bound_vars.clone();
+        existing_bound_vars.extend(bound_vars);
+        self.record_late_bound_vars(item_segment.hir_id, existing_bound_vars_saved);
+    }
 }
 
 /// Detects late-bound lifetimes and inserts them into
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 39df18ff658..4edb68e6199 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -780,14 +780,15 @@ pub(crate) struct PlaceholderNotAllowedItemSignatures {
 
 #[derive(Diagnostic)]
 #[diag(hir_analysis_associated_type_trait_uninferred_generic_params, code = E0212)]
-pub(crate) struct AssociatedTypeTraitUninferredGenericParams {
+pub(crate) struct AssociatedItemTraitUninferredGenericParams {
     #[primary_span]
     pub span: Span,
     #[suggestion(style = "verbose", applicability = "maybe-incorrect", code = "{bound}")]
     pub inferred_sugg: Option<Span>,
     pub bound: String,
     #[subdiagnostic]
-    pub mpart_sugg: Option<AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion>,
+    pub mpart_sugg: Option<AssociatedItemTraitUninferredGenericParamsMultipartSuggestion>,
+    pub what: &'static str,
 }
 
 #[derive(Subdiagnostic)]
@@ -795,7 +796,7 @@ pub(crate) struct AssociatedTypeTraitUninferredGenericParams {
     hir_analysis_associated_type_trait_uninferred_generic_params_multipart_suggestion,
     applicability = "maybe-incorrect"
 )]
-pub(crate) struct AssociatedTypeTraitUninferredGenericParamsMultipartSuggestion {
+pub(crate) struct AssociatedItemTraitUninferredGenericParamsMultipartSuggestion {
     #[suggestion_part(code = "{first}")]
     pub fspan: Span,
     pub first: String,
@@ -1523,57 +1524,6 @@ pub(crate) struct OnlyCurrentTraitsPointerSugg<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_static_mut_ref, code = E0796)]
-#[note]
-pub(crate) struct StaticMutRef<'a> {
-    #[primary_span]
-    #[label]
-    pub span: Span,
-    #[subdiagnostic]
-    pub sugg: MutRefSugg,
-    pub shared: &'a str,
-}
-
-#[derive(Subdiagnostic)]
-pub(crate) enum MutRefSugg {
-    #[multipart_suggestion(
-        hir_analysis_suggestion,
-        style = "verbose",
-        applicability = "maybe-incorrect"
-    )]
-    Shared {
-        #[suggestion_part(code = "addr_of!(")]
-        lo: Span,
-        #[suggestion_part(code = ")")]
-        hi: Span,
-    },
-    #[multipart_suggestion(
-        hir_analysis_suggestion_mut,
-        style = "verbose",
-        applicability = "maybe-incorrect"
-    )]
-    Mut {
-        #[suggestion_part(code = "addr_of_mut!(")]
-        lo: Span,
-        #[suggestion_part(code = ")")]
-        hi: Span,
-    },
-}
-
-// STATIC_MUT_REF lint
-#[derive(LintDiagnostic)]
-#[diag(hir_analysis_static_mut_refs_lint)]
-#[note]
-#[note(hir_analysis_why_note)]
-pub(crate) struct RefOfMutStatic<'a> {
-    #[label]
-    pub span: Span,
-    #[subdiagnostic]
-    pub sugg: MutRefSugg,
-    pub shared: &'a str,
-}
-
-#[derive(Diagnostic)]
 #[diag(hir_analysis_not_supported_delegation)]
 pub(crate) struct UnsupportedDelegation<'a> {
     #[primary_span]
@@ -1744,3 +1694,10 @@ pub(crate) struct CmseCallGeneric {
     #[primary_span]
     pub span: Span,
 }
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_bad_return_type_notation_position)]
+pub(crate) struct BadReturnTypeNotation {
+    #[primary_span]
+    pub span: Span,
+}
diff --git a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs
index 97402dd1109..236543007fc 100644
--- a/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/errors/wrong_number_of_generic_args.rs
@@ -1048,7 +1048,18 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
                 },
             );
 
-            err.span_suggestion(span, msg, "", Applicability::MaybeIncorrect);
+            if span.is_empty() {
+                // HACK: Avoid ICE when types with the same name with `derive`s are in the same scope:
+                //     struct NotSM;
+                //     #[derive(PartialEq, Eq)]
+                //     struct NotSM<T>(T);
+                // With the above code, the suggestion would be to remove the generics of the first
+                // `NotSM`, which doesn't *have* generics, so we would suggest to remove no code with
+                // no code, which would trigger an `assert!` later. Ideally, we would do something a
+                // bit more principled. See closed PR #109082.
+            } else {
+                err.span_suggestion(span, msg, "", Applicability::MaybeIncorrect);
+            }
         } else if redundant_lifetime_args && redundant_type_or_const_args {
             remove_lifetime_args(err);
             remove_type_or_const_args(err);
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
index bffe68f9b74..6f7f3128347 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
@@ -6,6 +6,7 @@ use rustc_errors::struct_span_code_err;
 use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::HirId;
 use rustc_middle::bug;
 use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt};
 use rustc_span::symbol::Ident;
@@ -15,6 +16,7 @@ use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
 use smallvec::SmallVec;
 use tracing::{debug, instrument};
 
+use super::errors::GenericsArgsErrExtend;
 use crate::bounds::Bounds;
 use crate::errors;
 use crate::hir_ty_lowering::{
@@ -332,74 +334,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             .or_insert(constraint.span);
 
         let projection_term = if let ty::AssocKind::Fn = assoc_kind {
-            let mut emitted_bad_param_err = None;
-            // If we have an method return type bound, then we need to instantiate
-            // the method's early bound params with suitable late-bound params.
-            let mut num_bound_vars = candidate.bound_vars().len();
-            let args =
-                candidate.skip_binder().args.extend_to(tcx, assoc_item.def_id, |param, _| {
-                    let arg = match param.kind {
-                        ty::GenericParamDefKind::Lifetime => ty::Region::new_bound(
-                            tcx,
-                            ty::INNERMOST,
-                            ty::BoundRegion {
-                                var: ty::BoundVar::from_usize(num_bound_vars),
-                                kind: ty::BoundRegionKind::BrNamed(param.def_id, param.name),
-                            },
-                        )
-                        .into(),
-                        ty::GenericParamDefKind::Type { .. } => {
-                            let guar = *emitted_bad_param_err.get_or_insert_with(|| {
-                                self.dcx().emit_err(
-                                    crate::errors::ReturnTypeNotationIllegalParam::Type {
-                                        span: path_span,
-                                        param_span: tcx.def_span(param.def_id),
-                                    },
-                                )
-                            });
-                            Ty::new_error(tcx, guar).into()
-                        }
-                        ty::GenericParamDefKind::Const { .. } => {
-                            let guar = *emitted_bad_param_err.get_or_insert_with(|| {
-                                self.dcx().emit_err(
-                                    crate::errors::ReturnTypeNotationIllegalParam::Const {
-                                        span: path_span,
-                                        param_span: tcx.def_span(param.def_id),
-                                    },
-                                )
-                            });
-                            ty::Const::new_error(tcx, guar).into()
-                        }
-                    };
-                    num_bound_vars += 1;
-                    arg
-                });
-
-            // Next, we need to check that the return-type notation is being used on
-            // an RPITIT (return-position impl trait in trait) or AFIT (async fn in trait).
-            let output = tcx.fn_sig(assoc_item.def_id).skip_binder().output();
-            let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind()
-                && tcx.is_impl_trait_in_trait(alias_ty.def_id)
-            {
-                alias_ty.into()
-            } else {
-                return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationOnNonRpitit {
-                    span: constraint.span,
-                    ty: tcx.liberate_late_bound_regions(assoc_item.def_id, output),
-                    fn_span: tcx.hir().span_if_local(assoc_item.def_id),
-                    note: (),
-                }));
-            };
-
-            // Finally, move the fn return type's bound vars over to account for the early bound
-            // params (and trait ref's late bound params). This logic is very similar to
-            // `rustc_middle::ty::predicate::Clause::instantiate_supertrait`
-            // and it's no coincidence why.
-            let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
-            let instantiation_output = ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args);
-
             let bound_vars = tcx.late_bound_vars(constraint.hir_id);
-            ty::Binder::bind_with_vars(instantiation_output, bound_vars)
+            ty::Binder::bind_with_vars(
+                self.lower_return_type_notation_ty(candidate, assoc_item.def_id, path_span)?.into(),
+                bound_vars,
+            )
         } else {
             // 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
@@ -525,6 +464,269 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         }
         Ok(())
     }
+
+    /// Lower a type, possibly specially handling the type if it's a return type notation
+    /// which we otherwise deny in other positions.
+    pub fn lower_ty_maybe_return_type_notation(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> {
+        let hir::TyKind::Path(qpath) = hir_ty.kind else {
+            return self.lower_ty(hir_ty);
+        };
+
+        let tcx = self.tcx();
+        match qpath {
+            hir::QPath::Resolved(opt_self_ty, path)
+                if let [mod_segments @ .., trait_segment, item_segment] = &path.segments[..]
+                    && item_segment.args.is_some_and(|args| {
+                        matches!(
+                            args.parenthesized,
+                            hir::GenericArgsParentheses::ReturnTypeNotation
+                        )
+                    }) =>
+            {
+                // We don't allow generics on the module segments.
+                let _ =
+                    self.prohibit_generic_args(mod_segments.iter(), GenericsArgsErrExtend::None);
+
+                let item_def_id = match path.res {
+                    Res::Def(DefKind::AssocFn, item_def_id) => item_def_id,
+                    Res::Err => {
+                        return Ty::new_error_with_message(
+                            tcx,
+                            hir_ty.span,
+                            "failed to resolve RTN",
+                        );
+                    }
+                    _ => bug!("only expected method resolution for fully qualified RTN"),
+                };
+                let trait_def_id = tcx.parent(item_def_id);
+
+                // Good error for `where Trait::method(..): Send`.
+                let Some(self_ty) = opt_self_ty else {
+                    return self.error_missing_qpath_self_ty(
+                        trait_def_id,
+                        hir_ty.span,
+                        item_segment,
+                    );
+                };
+                let self_ty = self.lower_ty(self_ty);
+
+                let trait_ref = self.lower_mono_trait_ref(
+                    hir_ty.span,
+                    trait_def_id,
+                    self_ty,
+                    trait_segment,
+                    false,
+                    ty::BoundConstness::NotConst,
+                );
+
+                // SUBTLE: As noted at the end of `try_append_return_type_notation_params`
+                // in `resolve_bound_vars`, we stash the explicit bound vars of the where
+                // clause onto the item segment of the RTN type. This allows us to know
+                // how many bound vars are *not* coming from the signature of the function
+                // from lowering RTN itself.
+                //
+                // For example, in `where for<'a> <T as Trait<'a>>::method(..): Other`,
+                // the `late_bound_vars` of the where clause predicate (i.e. this HIR ty's
+                // parent) will include `'a` AND all the early- and late-bound vars of the
+                // method. But when lowering the RTN type, we just want the list of vars
+                // we used to resolve the trait ref. We explicitly stored those back onto
+                // the item segment, since there's no other good place to put them.
+                let candidate =
+                    ty::Binder::bind_with_vars(trait_ref, tcx.late_bound_vars(item_segment.hir_id));
+
+                match self.lower_return_type_notation_ty(candidate, item_def_id, hir_ty.span) {
+                    Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
+                    Err(guar) => Ty::new_error(tcx, guar),
+                }
+            }
+            hir::QPath::TypeRelative(qself, item_segment)
+                if item_segment.args.is_some_and(|args| {
+                    matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
+                }) =>
+            {
+                match self
+                    .resolve_type_relative_return_type_notation(
+                        qself,
+                        item_segment,
+                        hir_ty.hir_id,
+                        hir_ty.span,
+                    )
+                    .and_then(|(candidate, item_def_id)| {
+                        self.lower_return_type_notation_ty(candidate, item_def_id, hir_ty.span)
+                    }) {
+                    Ok(ty) => Ty::new_alias(tcx, ty::Projection, ty),
+                    Err(guar) => Ty::new_error(tcx, guar),
+                }
+            }
+            _ => self.lower_ty(hir_ty),
+        }
+    }
+
+    /// Perform type-dependent lookup for a *method* for return type notation.
+    /// This generally mirrors `<dyn HirTyLowerer>::lower_assoc_path`.
+    fn resolve_type_relative_return_type_notation(
+        &self,
+        qself: &'tcx hir::Ty<'tcx>,
+        item_segment: &'tcx hir::PathSegment<'tcx>,
+        qpath_hir_id: HirId,
+        span: Span,
+    ) -> Result<(ty::PolyTraitRef<'tcx>, DefId), ErrorGuaranteed> {
+        let tcx = self.tcx();
+        let qself_ty = self.lower_ty(qself);
+        let assoc_ident = item_segment.ident;
+        let qself_res = if let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = &qself.kind {
+            path.res
+        } else {
+            Res::Err
+        };
+
+        let bound = match (qself_ty.kind(), qself_res) {
+            (_, Res::SelfTyAlias { alias_to: impl_def_id, is_trait_impl: true, .. }) => {
+                // `Self` in an impl of a trait -- we have a concrete self type and a
+                // trait reference.
+                let Some(trait_ref) = tcx.impl_trait_ref(impl_def_id) else {
+                    // A cycle error occurred, most likely.
+                    self.dcx().span_bug(span, "expected cycle error");
+                };
+
+                self.probe_single_bound_for_assoc_item(
+                    || {
+                        traits::supertraits(
+                            tcx,
+                            ty::Binder::dummy(trait_ref.instantiate_identity()),
+                        )
+                    },
+                    AssocItemQSelf::SelfTyAlias,
+                    ty::AssocKind::Fn,
+                    assoc_ident,
+                    span,
+                    None,
+                )?
+            }
+            (
+                &ty::Param(_),
+                Res::SelfTyParam { trait_: param_did } | Res::Def(DefKind::TyParam, param_did),
+            ) => self.probe_single_ty_param_bound_for_assoc_item(
+                param_did.expect_local(),
+                qself.span,
+                ty::AssocKind::Fn,
+                assoc_ident,
+                span,
+            )?,
+            _ => {
+                if let Err(reported) = qself_ty.error_reported() {
+                    return Err(reported);
+                } else {
+                    // FIXME(return_type_notation): Provide some structured suggestion here.
+                    let err = struct_span_code_err!(
+                        self.dcx(),
+                        span,
+                        E0223,
+                        "ambiguous associated function"
+                    );
+                    return Err(err.emit());
+                }
+            }
+        };
+
+        // Don't let `T::method` resolve to some `for<'a> <T as Tr<'a>>::method`,
+        // which may happen via a higher-ranked where clause or supertrait.
+        // This is the same restrictions as associated types; even though we could
+        // support it, it just makes things a lot more difficult to support in
+        // `resolve_bound_vars`, since we'd need to introduce those as elided
+        // bound vars on the where clause too.
+        if bound.has_bound_vars() {
+            return Err(self.tcx().dcx().emit_err(
+                errors::AssociatedItemTraitUninferredGenericParams {
+                    span,
+                    inferred_sugg: Some(span.with_hi(item_segment.ident.span.lo())),
+                    bound: format!("{}::", tcx.anonymize_bound_vars(bound).skip_binder(),),
+                    mpart_sugg: None,
+                    what: "function",
+                },
+            ));
+        }
+
+        let trait_def_id = bound.def_id();
+        let assoc_ty = self
+            .probe_assoc_item(assoc_ident, ty::AssocKind::Fn, qpath_hir_id, span, trait_def_id)
+            .expect("failed to find associated type");
+
+        Ok((bound, assoc_ty.def_id))
+    }
+
+    /// Do the common parts of lowering an RTN type. This involves extending the
+    /// candidate binder to include all of the early- and late-bound vars that are
+    /// defined on the function itself, and constructing a projection to the RPITIT
+    /// return type of that function.
+    fn lower_return_type_notation_ty(
+        &self,
+        candidate: ty::PolyTraitRef<'tcx>,
+        item_def_id: DefId,
+        path_span: Span,
+    ) -> Result<ty::AliasTy<'tcx>, ErrorGuaranteed> {
+        let tcx = self.tcx();
+        let mut emitted_bad_param_err = None;
+        // If we have an method return type bound, then we need to instantiate
+        // the method's early bound params with suitable late-bound params.
+        let mut num_bound_vars = candidate.bound_vars().len();
+        let args = candidate.skip_binder().args.extend_to(tcx, item_def_id, |param, _| {
+            let arg = match param.kind {
+                ty::GenericParamDefKind::Lifetime => ty::Region::new_bound(
+                    tcx,
+                    ty::INNERMOST,
+                    ty::BoundRegion {
+                        var: ty::BoundVar::from_usize(num_bound_vars),
+                        kind: ty::BoundRegionKind::BrNamed(param.def_id, param.name),
+                    },
+                )
+                .into(),
+                ty::GenericParamDefKind::Type { .. } => {
+                    let guar = *emitted_bad_param_err.get_or_insert_with(|| {
+                        self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Type {
+                            span: path_span,
+                            param_span: tcx.def_span(param.def_id),
+                        })
+                    });
+                    Ty::new_error(tcx, guar).into()
+                }
+                ty::GenericParamDefKind::Const { .. } => {
+                    let guar = *emitted_bad_param_err.get_or_insert_with(|| {
+                        self.dcx().emit_err(crate::errors::ReturnTypeNotationIllegalParam::Const {
+                            span: path_span,
+                            param_span: tcx.def_span(param.def_id),
+                        })
+                    });
+                    ty::Const::new_error(tcx, guar).into()
+                }
+            };
+            num_bound_vars += 1;
+            arg
+        });
+
+        // Next, we need to check that the return-type notation is being used on
+        // an RPITIT (return-position impl trait in trait) or AFIT (async fn in trait).
+        let output = tcx.fn_sig(item_def_id).skip_binder().output();
+        let output = if let ty::Alias(ty::Projection, alias_ty) = *output.skip_binder().kind()
+            && tcx.is_impl_trait_in_trait(alias_ty.def_id)
+        {
+            alias_ty
+        } else {
+            return Err(self.dcx().emit_err(crate::errors::ReturnTypeNotationOnNonRpitit {
+                span: path_span,
+                ty: tcx.liberate_late_bound_regions(item_def_id, output),
+                fn_span: tcx.hir().span_if_local(item_def_id),
+                note: (),
+            }));
+        };
+
+        // Finally, move the fn return type's bound vars over to account for the early bound
+        // params (and trait ref's late bound params). This logic is very similar to
+        // `rustc_middle::ty::predicate::Clause::instantiate_supertrait`
+        // and it's no coincidence why.
+        let shifted_output = tcx.shift_bound_var_indices(num_bound_vars, output);
+        Ok(ty::EarlyBinder::bind(shifted_output).instantiate(tcx, args))
+    }
 }
 
 /// Detect and reject early-bound & escaping late-bound generic params in the type of assoc const bindings.
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 7163352e8a4..35eebcb6be1 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -53,7 +53,7 @@ use rustc_trait_selection::traits::{self, ObligationCtxt};
 use tracing::{debug, debug_span, instrument};
 
 use crate::bounds::Bounds;
-use crate::errors::{AmbiguousLifetimeBound, WildPatTy};
+use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, WildPatTy};
 use crate::hir_ty_lowering::errors::{prohibit_assoc_item_constraint, GenericsArgsErrExtend};
 use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args};
 use crate::middle::resolve_bound_vars as rbv;
@@ -719,6 +719,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             span,
             polarity,
             constness,
+            only_self_bounds,
         );
 
         let mut dup_constraints = FxIndexMap::default();
@@ -813,17 +814,19 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         }
     }
 
-    /// Search for a trait bound on a type parameter whose trait defines the associated type given by `assoc_name`.
+    /// Search for a trait bound on a type parameter whose trait defines the associated item
+    /// given by `assoc_name` and `kind`.
     ///
     /// This fails if there is no such bound in the list of candidates or if there are multiple
     /// candidates in which case it reports ambiguity.
     ///
     /// `ty_param_def_id` is the `LocalDefId` of the type parameter.
     #[instrument(level = "debug", skip_all, ret)]
-    fn probe_single_ty_param_bound_for_assoc_ty(
+    fn probe_single_ty_param_bound_for_assoc_item(
         &self,
         ty_param_def_id: LocalDefId,
         ty_param_span: Span,
+        kind: ty::AssocKind,
         assoc_name: Ident,
         span: Span,
     ) -> Result<ty::PolyTraitRef<'tcx>, ErrorGuaranteed> {
@@ -841,7 +844,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 traits::transitive_bounds_that_define_assoc_item(tcx, trait_refs, assoc_name)
             },
             AssocItemQSelf::TyParam(ty_param_def_id, ty_param_span),
-            ty::AssocKind::Type,
+            kind,
             assoc_name,
             span,
             None,
@@ -1081,9 +1084,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
             (
                 &ty::Param(_),
                 Res::SelfTyParam { trait_: param_did } | Res::Def(DefKind::TyParam, param_did),
-            ) => self.probe_single_ty_param_bound_for_assoc_ty(
+            ) => self.probe_single_ty_param_bound_for_assoc_item(
                 param_did.expect_local(),
                 qself.span,
+                ty::AssocKind::Type,
                 assoc_ident,
                 span,
             )?,
@@ -1545,48 +1549,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         debug!(?trait_def_id);
 
         let Some(self_ty) = opt_self_ty else {
-            let path_str = tcx.def_path_str(trait_def_id);
-
-            let def_id = self.item_def_id();
-            debug!(item_def_id = ?def_id);
-
-            // FIXME: document why/how this is different from `tcx.local_parent(def_id)`
-            let parent_def_id =
-                tcx.hir().get_parent_item(tcx.local_def_id_to_hir_id(def_id)).to_def_id();
-            debug!(?parent_def_id);
-
-            // If the trait in segment is the same as the trait defining the item,
-            // use the `<Self as ..>` syntax in the error.
-            let is_part_of_self_trait_constraints = def_id.to_def_id() == trait_def_id;
-            let is_part_of_fn_in_self_trait = parent_def_id == trait_def_id;
-
-            let type_names = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait {
-                vec!["Self".to_string()]
-            } else {
-                // Find all the types that have an `impl` for the trait.
-                tcx.all_impls(trait_def_id)
-                    .filter_map(|impl_def_id| tcx.impl_trait_header(impl_def_id))
-                    .filter(|header| {
-                        // Consider only accessible traits
-                        tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx)
-                            && header.polarity != ty::ImplPolarity::Negative
-                    })
-                    .map(|header| header.trait_ref.instantiate_identity().self_ty())
-                    // We don't care about blanket impls.
-                    .filter(|self_ty| !self_ty.has_non_region_param())
-                    .map(|self_ty| tcx.erase_regions(self_ty).to_string())
-                    .collect()
-            };
-            // FIXME: also look at `tcx.generics_of(self.item_def_id()).params` any that
-            // references the trait. Relevant for the first case in
-            // `src/test/ui/associated-types/associated-types-in-ambiguous-context.rs`
-            let reported = self.report_ambiguous_assoc_ty(
-                span,
-                &type_names,
-                &[path_str],
-                item_segment.ident.name,
-            );
-            return Ty::new_error(tcx, reported);
+            return self.error_missing_qpath_self_ty(trait_def_id, span, item_segment);
         };
         debug!(?self_ty);
 
@@ -1600,6 +1563,53 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         Ty::new_projection_from_args(tcx, item_def_id, item_args)
     }
 
+    fn error_missing_qpath_self_ty(
+        &self,
+        trait_def_id: DefId,
+        span: Span,
+        item_segment: &hir::PathSegment<'tcx>,
+    ) -> Ty<'tcx> {
+        let tcx = self.tcx();
+        let path_str = tcx.def_path_str(trait_def_id);
+
+        let def_id = self.item_def_id();
+        debug!(item_def_id = ?def_id);
+
+        // FIXME: document why/how this is different from `tcx.local_parent(def_id)`
+        let parent_def_id =
+            tcx.hir().get_parent_item(tcx.local_def_id_to_hir_id(def_id)).to_def_id();
+        debug!(?parent_def_id);
+
+        // If the trait in segment is the same as the trait defining the item,
+        // use the `<Self as ..>` syntax in the error.
+        let is_part_of_self_trait_constraints = def_id.to_def_id() == trait_def_id;
+        let is_part_of_fn_in_self_trait = parent_def_id == trait_def_id;
+
+        let type_names = if is_part_of_self_trait_constraints || is_part_of_fn_in_self_trait {
+            vec!["Self".to_string()]
+        } else {
+            // Find all the types that have an `impl` for the trait.
+            tcx.all_impls(trait_def_id)
+                .filter_map(|impl_def_id| tcx.impl_trait_header(impl_def_id))
+                .filter(|header| {
+                    // Consider only accessible traits
+                    tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx)
+                        && header.polarity != ty::ImplPolarity::Negative
+                })
+                .map(|header| header.trait_ref.instantiate_identity().self_ty())
+                // We don't care about blanket impls.
+                .filter(|self_ty| !self_ty.has_non_region_param())
+                .map(|self_ty| tcx.erase_regions(self_ty).to_string())
+                .collect()
+        };
+        // FIXME: also look at `tcx.generics_of(self.item_def_id()).params` any that
+        // references the trait. Relevant for the first case in
+        // `src/test/ui/associated-types/associated-types-in-ambiguous-context.rs`
+        let reported =
+            self.report_ambiguous_assoc_ty(span, &type_names, &[path_str], item_segment.ident.name);
+        Ty::new_error(tcx, reported)
+    }
+
     pub fn prohibit_generic_args<'a>(
         &self,
         segments: impl Iterator<Item = &'a hir::PathSegment<'a>> + Clone,
@@ -1930,7 +1940,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     .tcx()
                     .dcx()
                     .span_delayed_bug(path.span, "path with `Res::Err` but no error emitted");
-                Ty::new_error(self.tcx(), e)
+                Ty::new_error(tcx, e)
             }
             Res::Def(..) => {
                 assert_eq!(
@@ -2061,6 +2071,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 };
                 self.lower_trait_object_ty(hir_ty.span, hir_ty.hir_id, bounds, lifetime, repr)
             }
+            // If we encounter a fully qualified path with RTN generics, then it must have
+            // *not* gone through `lower_ty_maybe_return_type_notation`, and therefore
+            // it's certainly in an illegal position.
+            hir::TyKind::Path(hir::QPath::Resolved(_, path))
+                if path.segments.last().and_then(|segment| segment.args).is_some_and(|args| {
+                    matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
+                }) =>
+            {
+                let guar = self.dcx().emit_err(BadReturnTypeNotation { span: hir_ty.span });
+                Ty::new_error(tcx, guar)
+            }
             hir::TyKind::Path(hir::QPath::Resolved(maybe_qself, path)) => {
                 debug!(?maybe_qself, ?path);
                 let opt_self_ty = maybe_qself.as_ref().map(|qself| self.lower_ty(qself));
@@ -2085,6 +2106,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     ref i => bug!("`impl Trait` pointed to non-opaque type?? {:#?}", i),
                 }
             }
+            // If we encounter a type relative path with RTN generics, then it must have
+            // *not* gone through `lower_ty_maybe_return_type_notation`, and therefore
+            // it's certainly in an illegal position.
+            hir::TyKind::Path(hir::QPath::TypeRelative(_, segment))
+                if segment.args.is_some_and(|args| {
+                    matches!(args.parenthesized, hir::GenericArgsParentheses::ReturnTypeNotation)
+                }) =>
+            {
+                let guar = self.dcx().emit_err(BadReturnTypeNotation { span: hir_ty.span });
+                Ty::new_error(tcx, guar)
+            }
             hir::TyKind::Path(hir::QPath::TypeRelative(qself, segment)) => {
                 debug!(?qself, ?segment);
                 let ty = self.lower_ty(qself);
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index fca7babea30..26c9b8dfdc3 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -214,6 +214,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
             ty::Dynamic(predicates, region, ty::DynStar) if self.tcx.features().dyn_star => {
                 return self.coerce_dyn_star(a, b, predicates, region);
             }
+            ty::Adt(pin, _)
+                if self.tcx.features().pin_ergonomics
+                    && self.tcx.is_lang_item(pin.did(), hir::LangItem::Pin) =>
+            {
+                return self.coerce_pin(a, b);
+            }
             _ => {}
         }
 
@@ -774,6 +780,62 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         })
     }
 
+    /// Applies reborrowing for `Pin`
+    ///
+    /// We currently only support reborrowing `Pin<&mut T>` as `Pin<&mut T>`. This is accomplished
+    /// by inserting a call to `Pin::as_mut` during MIR building.
+    ///
+    /// In the future we might want to support other reborrowing coercions, such as:
+    /// - `Pin<&mut T>` as `Pin<&T>`
+    /// - `Pin<&T>` as `Pin<&T>`
+    /// - `Pin<Box<T>>` as `Pin<&T>`
+    /// - `Pin<Box<T>>` as `Pin<&mut T>`
+    #[instrument(skip(self), level = "trace")]
+    fn coerce_pin(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> CoerceResult<'tcx> {
+        // We need to make sure the two types are compatible for coercion.
+        // Then we will build a ReborrowPin adjustment and return that as an InferOk.
+
+        // Right now we can only reborrow if this is a `Pin<&mut T>`.
+        let extract_pin_mut = |ty: Ty<'tcx>| {
+            // Get the T out of Pin<T>
+            let (pin, ty) = match ty.kind() {
+                ty::Adt(pin, args) if self.tcx.is_lang_item(pin.did(), hir::LangItem::Pin) => {
+                    (*pin, args[0].expect_ty())
+                }
+                _ => {
+                    debug!("can't reborrow {:?} as pinned", ty);
+                    return Err(TypeError::Mismatch);
+                }
+            };
+            // Make sure the T is something we understand (just `&mut U` for now)
+            match ty.kind() {
+                ty::Ref(region, ty, mutbl) => Ok((pin, *region, *ty, *mutbl)),
+                _ => {
+                    debug!("can't reborrow pin of inner type {:?}", ty);
+                    Err(TypeError::Mismatch)
+                }
+            }
+        };
+
+        let (pin, a_region, a_ty, mut_a) = extract_pin_mut(a)?;
+        let (_, b_region, _b_ty, mut_b) = extract_pin_mut(b)?;
+
+        coerce_mutbls(mut_a, mut_b)?;
+
+        // update a with b's mutability since we'll be coercing mutability
+        let a = Ty::new_adt(
+            self.tcx,
+            pin,
+            self.tcx.mk_args(&[Ty::new_ref(self.tcx, a_region, a_ty, mut_b).into()]),
+        );
+
+        // To complete the reborrow, we need to make sure we can unify the inner types, and if so we
+        // add the adjustments.
+        self.unify_and(a, b, |_inner_ty| {
+            vec![Adjustment { kind: Adjust::ReborrowPin(b_region, mut_b), target: b }]
+        })
+    }
+
     fn coerce_from_safe_fn<F, G>(
         &self,
         a: Ty<'tcx>,
diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
index da8c0ad3a30..3b2ddf659a1 100644
--- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
+++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs
@@ -780,6 +780,16 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
                 adjustment::Adjust::Borrow(ref autoref) => {
                     self.walk_autoref(expr, &place_with_id, autoref);
                 }
+
+                adjustment::Adjust::ReborrowPin(_, mutbl) => {
+                    // Reborrowing a Pin is like a combinations of a deref and a borrow, so we do
+                    // both.
+                    let bk = match mutbl {
+                        ty::Mutability::Not => ty::BorrowKind::ImmBorrow,
+                        ty::Mutability::Mut => ty::BorrowKind::MutBorrow,
+                    };
+                    self.delegate.borrow_mut().borrow(&place_with_id, place_with_id.hir_id, bk);
+                }
             }
             place_with_id = self.cat_expr_adjusted(expr, place_with_id, adjustment)?;
         }
@@ -1284,6 +1294,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
             adjustment::Adjust::NeverToAny
             | adjustment::Adjust::Pointer(_)
             | adjustment::Adjust::Borrow(_)
+            | adjustment::Adjust::ReborrowPin(..)
             | adjustment::Adjust::DynStar => {
                 // Result is an rvalue.
                 Ok(self.cat_rvalue(expr.hir_id, target))
diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs
index f39d83a2a6f..81d940a3f9b 100644
--- a/compiler/rustc_hir_typeck/src/intrinsicck.rs
+++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs
@@ -95,7 +95,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     format!("{v} bits")
                 } else {
                     // `u128` should definitely be able to hold the size of different architectures
-                    // larger sizes should be reported as error `are too big for the current architecture`
+                    // larger sizes should be reported as error `are too big for the target architecture`
                     // otherwise we have a bug somewhere
                     bug!("{:?} overflow for u128", size)
                 }
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 45a6efc7a6a..7dd6deb4fe6 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -11,7 +11,6 @@ use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::pat_util::EnumerateAndAdjustIterator;
 use rustc_hir::{self as hir, BindingMode, ByRef, HirId, LangItem, Mutability, Pat, PatKind};
 use rustc_infer::infer;
-use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 use rustc_middle::{bug, span_bug};
 use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
@@ -2413,17 +2412,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         len: ty::Const<'tcx>,
         min_len: u64,
     ) -> (Option<Ty<'tcx>>, Ty<'tcx>) {
-        let len = match len.eval(self.tcx, self.param_env, span) {
-            Ok((_, val)) => val
-                .try_to_scalar()
-                .and_then(|scalar| scalar.try_to_scalar_int().ok())
-                .map(|int| int.to_target_usize(self.tcx)),
-            Err(ErrorHandled::Reported(..)) => {
-                let guar = self.error_scrutinee_unfixed_length(span);
-                return (Some(Ty::new_error(self.tcx, guar)), arr_ty);
-            }
-            Err(ErrorHandled::TooGeneric(..)) => None,
-        };
+        let len = len.try_eval_target_usize(self.tcx, self.param_env);
 
         let guar = if let Some(len) = len {
             // Now we know the length...
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index c2555d2bb47..2fbbc3200e1 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -803,7 +803,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
         // We must deeply normalize in the new solver, since later lints
         // expect that types that show up in the typeck are fully
         // normalized.
-        let value = if self.should_normalize {
+        let mut value = if self.should_normalize {
             let body_id = tcx.hir().body_owner_def_id(self.body.id());
             let cause = ObligationCause::misc(self.span.to_span(tcx), body_id);
             let at = self.fcx.at(&cause, self.fcx.param_env);
@@ -818,12 +818,27 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
             value
         };
 
+        // Bail if there are any non-region infer.
         if value.has_non_region_infer() {
             let guar = self.report_error(value);
-            new_err(tcx, guar)
-        } else {
-            tcx.fold_regions(value, |_, _| tcx.lifetimes.re_erased)
+            value = new_err(tcx, guar);
+        }
+
+        // Erase the regions from the ty, since it's not really meaningful what
+        // these region values are; there's not a trivial correspondence between
+        // regions in the HIR and MIR, so when we turn the body into MIR, there's
+        // no reason to keep regions around. They will be repopulated during MIR
+        // borrowck, and specifically region constraints will be populated during
+        // MIR typeck which is run on the new body.
+        value = tcx.fold_regions(value, |_, _| tcx.lifetimes.re_erased);
+
+        // Normalize consts in writeback, because GCE doesn't normalize eagerly.
+        if tcx.features().generic_const_exprs {
+            value =
+                value.fold_with(&mut EagerlyNormalizeConsts { tcx, param_env: self.fcx.param_env });
         }
+
+        value
     }
 }
 
@@ -858,3 +873,17 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Resolver<'cx, 'tcx> {
         predicate
     }
 }
+
+struct EagerlyNormalizeConsts<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+}
+impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EagerlyNormalizeConsts<'tcx> {
+    fn cx(&self) -> TyCtxt<'tcx> {
+        self.tcx
+    }
+
+    fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
+        self.tcx.try_normalize_erasing_regions(self.param_env, ct).unwrap_or(ct)
+    }
+}
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 4aa86944a0b..e71c5676ce4 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -395,6 +395,8 @@ lint_improper_ctypes_opaque = opaque types have no C equivalent
 lint_improper_ctypes_pat_help = consider using the base type instead
 
 lint_improper_ctypes_pat_reason = pattern types have no C equivalent
+
+lint_improper_ctypes_recursion_limit_reached = type is infinitely recursive
 lint_improper_ctypes_slice_help = consider using a raw pointer instead
 
 lint_improper_ctypes_slice_reason = slices have no C equivalent
@@ -769,6 +771,13 @@ lint_single_use_lifetime = lifetime parameter `{$ident}` only used once
 
 lint_span_use_eq_ctxt = use `.eq_ctxt()` instead of `.ctxt() == .ctxt()`
 
+lint_static_mut_refs_lint = creating a {$shared_label}reference to mutable static is discouraged
+    .label = {$shared_label}reference to mutable static
+    .suggestion = use `&raw const` instead to create a raw pointer
+    .suggestion_mut = use `&raw mut` instead to create a raw pointer
+    .shared_note = shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+    .mut_note = mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives
+
 lint_supertrait_as_deref_target = this `Deref` implementation is covered by an implicit supertrait coercion
     .label = `{$self_ty}` implements `Deref<Target = dyn {$target_principal}>` which conflicts with supertrait `{$supertrait_principal}`
     .label2 = target type is a supertrait of `{$self_ty}`
diff --git a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
index ddaa819df14..38c4e48928f 100644
--- a/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
+++ b/compiler/rustc_lint/src/context/diagnostics/check_cfg.rs
@@ -2,6 +2,7 @@ use rustc_middle::bug;
 use rustc_session::config::ExpectedValues;
 use rustc_session::Session;
 use rustc_span::edit_distance::find_best_match_for_name;
+use rustc_span::symbol::Ident;
 use rustc_span::{sym, Span, Symbol};
 
 use crate::lints;
@@ -30,7 +31,7 @@ enum EscapeQuotes {
     No,
 }
 
-fn to_check_cfg_arg(name: Symbol, value: Option<Symbol>, quotes: EscapeQuotes) -> String {
+fn to_check_cfg_arg(name: Ident, value: Option<Symbol>, quotes: EscapeQuotes) -> String {
     if let Some(value) = value {
         let value = str::escape_debug(value.as_str()).to_string();
         let values = match quotes {
@@ -110,6 +111,7 @@ pub(super) fn unexpected_cfg_name(
                 }
             };
 
+            let best_match = Ident::new(best_match, name_span);
             if let Some((value, value_span)) = value {
                 if best_match_values.contains(&Some(value)) {
                     lints::unexpected_cfg_name::CodeSuggestion::SimilarNameAndValue {
@@ -163,6 +165,8 @@ pub(super) fn unexpected_cfg_name(
         };
         let expected_names = if !possibilities.is_empty() {
             let (possibilities, and_more) = sort_and_truncate_possibilities(sess, possibilities);
+            let possibilities: Vec<_> =
+                possibilities.into_iter().map(|s| Ident::new(s, name_span)).collect();
             Some(lints::unexpected_cfg_name::ExpectedNames {
                 possibilities: possibilities.into(),
                 and_more,
@@ -176,7 +180,9 @@ pub(super) fn unexpected_cfg_name(
         }
     };
 
-    let inst = |escape_quotes| to_check_cfg_arg(name, value.map(|(v, _s)| v), escape_quotes);
+    let inst = |escape_quotes| {
+        to_check_cfg_arg(Ident::new(name, name_span), value.map(|(v, _s)| v), escape_quotes)
+    };
 
     let invocation_help = if is_from_cargo {
         let sub = if !is_feature_cfg { Some(cargo_help_sub(sess, &inst)) } else { None };
@@ -273,7 +279,9 @@ pub(super) fn unexpected_cfg_value(
         || (matches!(sess.psess.unstable_features, rustc_feature::UnstableFeatures::Cheat)
             && !sess.opts.unstable_opts.ui_testing);
 
-    let inst = |escape_quotes| to_check_cfg_arg(name, value.map(|(v, _s)| v), escape_quotes);
+    let inst = |escape_quotes| {
+        to_check_cfg_arg(Ident::new(name, name_span), value.map(|(v, _s)| v), escape_quotes)
+    };
 
     let invocation_help = if is_from_cargo {
         let help = if name == sym::feature {
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index e8229b72182..d1da2809cc7 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -81,6 +81,7 @@ mod ptr_nulls;
 mod redundant_semicolon;
 mod reference_casting;
 mod shadowed_into_iter;
+mod static_mut_refs;
 mod tail_expr_drop_order;
 mod traits;
 mod types;
@@ -120,6 +121,7 @@ use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
 use shadowed_into_iter::ShadowedIntoIter;
 pub use shadowed_into_iter::{ARRAY_INTO_ITER, BOXED_SLICE_INTO_ITER};
+use static_mut_refs::*;
 use tail_expr_drop_order::TailExprDropOrder;
 use traits::*;
 use types::*;
@@ -246,6 +248,7 @@ late_lint_methods!(
             ImplTraitOvercaptures: ImplTraitOvercaptures,
             TailExprDropOrder: TailExprDropOrder,
             IfLetRescope: IfLetRescope::default(),
+            StaticMutRefs: StaticMutRefs,
         ]
     ]
 );
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index a2ccb93347a..11006862d05 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -2180,6 +2180,7 @@ pub(crate) struct UnexpectedCfgName {
 pub(crate) mod unexpected_cfg_name {
     use rustc_errors::DiagSymbolList;
     use rustc_macros::Subdiagnostic;
+    use rustc_span::symbol::Ident;
     use rustc_span::{Span, Symbol};
 
     #[derive(Subdiagnostic)]
@@ -2260,7 +2261,7 @@ pub(crate) mod unexpected_cfg_name {
     #[derive(Subdiagnostic)]
     #[help_once(lint_unexpected_cfg_name_expected_names)]
     pub(crate) struct ExpectedNames {
-        pub possibilities: DiagSymbolList,
+        pub possibilities: DiagSymbolList<Ident>,
         pub and_more: usize,
     }
 
@@ -3060,3 +3061,35 @@ pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion {
 pub(crate) struct OutOfScopeMacroCalls {
     pub path: String,
 }
+
+#[derive(LintDiagnostic)]
+#[diag(lint_static_mut_refs_lint)]
+pub(crate) struct RefOfMutStatic<'a> {
+    #[label]
+    pub span: Span,
+    #[subdiagnostic]
+    pub sugg: Option<MutRefSugg>,
+    pub shared_label: &'a str,
+    #[note(lint_shared_note)]
+    pub shared_note: bool,
+    #[note(lint_mut_note)]
+    pub mut_note: bool,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum MutRefSugg {
+    #[multipart_suggestion(lint_suggestion, style = "verbose", applicability = "maybe-incorrect")]
+    Shared {
+        #[suggestion_part(code = "&raw const ")]
+        span: Span,
+    },
+    #[multipart_suggestion(
+        lint_suggestion_mut,
+        style = "verbose",
+        applicability = "maybe-incorrect"
+    )]
+    Mut {
+        #[suggestion_part(code = "&raw mut ")]
+        span: Span,
+    },
+}
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index d81052b5e24..ce4ee45c485 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -332,6 +332,9 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
             return;
         }
 
+        // Issue #45127: don't enforce `snake_case` for binary crates as binaries are not intended
+        // to be distributed and depended on like libraries. The lint is not suppressed for cdylib
+        // or staticlib because it's not clear what the desired lint behavior for those are.
         if cx.tcx.crate_types().iter().all(|&crate_type| crate_type == CrateType::Executable) {
             return;
         }
diff --git a/compiler/rustc_lint/src/static_mut_refs.rs b/compiler/rustc_lint/src/static_mut_refs.rs
new file mode 100644
index 00000000000..3dd26fb9c53
--- /dev/null
+++ b/compiler/rustc_lint/src/static_mut_refs.rs
@@ -0,0 +1,154 @@
+use rustc_hir as hir;
+use rustc_hir::{Expr, Stmt};
+use rustc_middle::ty::{Mutability, TyKind};
+use rustc_session::lint::FutureIncompatibilityReason;
+use rustc_session::{declare_lint, declare_lint_pass};
+use rustc_span::edition::Edition;
+use rustc_span::Span;
+
+use crate::lints::{MutRefSugg, RefOfMutStatic};
+use crate::{LateContext, LateLintPass, LintContext};
+
+declare_lint! {
+    /// The `static_mut_refs` lint checks for shared or mutable references
+    /// of mutable static inside `unsafe` blocks and `unsafe` functions.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,edition2021
+    /// fn main() {
+    ///     static mut X: i32 = 23;
+    ///     static mut Y: i32 = 24;
+    ///
+    ///     unsafe {
+    ///         let y = &X;
+    ///         let ref x = X;
+    ///         let (x, y) = (&X, &Y);
+    ///         foo(&X);
+    ///     }
+    /// }
+    ///
+    /// unsafe fn _foo() {
+    ///     static mut X: i32 = 23;
+    ///     static mut Y: i32 = 24;
+    ///
+    ///     let y = &X;
+    ///     let ref x = X;
+    ///     let (x, y) = (&X, &Y);
+    ///     foo(&X);
+    /// }
+    ///
+    /// fn foo<'a>(_x: &'a i32) {}
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Shared or mutable references of mutable static are almost always a mistake and
+    /// can lead to undefined behavior and various other problems in your code.
+    ///
+    /// This lint is "warn" by default on editions up to 2021, in 2024 is "deny".
+    pub STATIC_MUT_REFS,
+    Warn,
+    "shared references or mutable references of mutable static is discouraged",
+    @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::EditionError(Edition::Edition2024),
+        reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>",
+        explain_reason: false,
+    };
+    @edition Edition2024 => Deny;
+}
+
+declare_lint_pass!(StaticMutRefs => [STATIC_MUT_REFS]);
+
+impl<'tcx> LateLintPass<'tcx> for StaticMutRefs {
+    #[allow(rustc::usage_of_ty_tykind)]
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) {
+        let err_span = expr.span;
+        match expr.kind {
+            hir::ExprKind::AddrOf(borrow_kind, m, ex)
+                if matches!(borrow_kind, hir::BorrowKind::Ref)
+                    && let Some(err_span) = path_is_static_mut(ex, err_span) =>
+            {
+                emit_static_mut_refs(
+                    cx,
+                    err_span,
+                    err_span.with_hi(ex.span.lo()),
+                    m,
+                    !expr.span.from_expansion(),
+                );
+            }
+            hir::ExprKind::MethodCall(_, e, _, _)
+                if let Some(err_span) = path_is_static_mut(e, expr.span)
+                    && let typeck = cx.typeck_results()
+                    && let Some(method_def_id) = typeck.type_dependent_def_id(expr.hir_id)
+                    && let inputs =
+                        cx.tcx.fn_sig(method_def_id).skip_binder().inputs().skip_binder()
+                    && let Some(receiver) = inputs.get(0)
+                    && let TyKind::Ref(_, _, m) = receiver.kind() =>
+            {
+                emit_static_mut_refs(cx, err_span, err_span.shrink_to_lo(), *m, false);
+            }
+            _ => {}
+        }
+    }
+
+    fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &Stmt<'_>) {
+        if let hir::StmtKind::Let(loc) = stmt.kind
+            && let hir::PatKind::Binding(ba, _, _, _) = loc.pat.kind
+            && let hir::ByRef::Yes(m) = ba.0
+            && let Some(init) = loc.init
+            && let Some(err_span) = path_is_static_mut(init, init.span)
+        {
+            emit_static_mut_refs(cx, err_span, err_span.shrink_to_lo(), m, false);
+        }
+    }
+}
+
+fn path_is_static_mut(mut expr: &hir::Expr<'_>, mut err_span: Span) -> Option<Span> {
+    if err_span.from_expansion() {
+        err_span = expr.span;
+    }
+
+    while let hir::ExprKind::Field(e, _) = expr.kind {
+        expr = e;
+    }
+
+    if let hir::ExprKind::Path(qpath) = expr.kind
+        && let hir::QPath::Resolved(_, path) = qpath
+        && let hir::def::Res::Def(def_kind, _) = path.res
+        && let hir::def::DefKind::Static { safety: _, mutability: Mutability::Mut, nested: false } =
+            def_kind
+    {
+        return Some(err_span);
+    }
+    None
+}
+
+fn emit_static_mut_refs(
+    cx: &LateContext<'_>,
+    span: Span,
+    sugg_span: Span,
+    mutable: Mutability,
+    suggest_addr_of: bool,
+) {
+    let (shared_label, shared_note, mut_note, sugg) = match mutable {
+        Mutability::Mut => {
+            let sugg =
+                if suggest_addr_of { Some(MutRefSugg::Mut { span: sugg_span }) } else { None };
+            ("mutable ", false, true, sugg)
+        }
+        Mutability::Not => {
+            let sugg =
+                if suggest_addr_of { Some(MutRefSugg::Shared { span: sugg_span }) } else { None };
+            ("shared ", true, false, sugg)
+        }
+    };
+
+    cx.emit_span_lint(
+        STATIC_MUT_REFS,
+        span,
+        RefOfMutStatic { span, sugg, shared_label, shared_note, mut_note },
+    );
+}
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 900c496e033..3d042f21745 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -3,9 +3,9 @@ use std::ops::ControlFlow;
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::DiagMessage;
-use rustc_hir::{is_range_literal, Expr, ExprKind, Node};
+use rustc_hir::{Expr, ExprKind};
 use rustc_middle::bug;
-use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton};
+use rustc_middle::ty::layout::{LayoutOf, SizeSkeleton};
 use rustc_middle::ty::{
     self, AdtKind, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
 };
@@ -13,22 +13,23 @@ use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::sym;
 use rustc_span::{source_map, Span, Symbol};
-use rustc_target::abi::{Abi, Integer, Size, TagEncoding, Variants, WrappingRange};
+use rustc_target::abi::{Abi, TagEncoding, Variants, WrappingRange};
 use rustc_target::spec::abi::Abi as SpecAbi;
 use tracing::debug;
-use {rustc_ast as ast, rustc_attr as attr, rustc_hir as hir};
+use {rustc_ast as ast, rustc_hir as hir};
 
 use crate::lints::{
     AmbiguousWidePointerComparisons, AmbiguousWidePointerComparisonsAddrMetadataSuggestion,
     AmbiguousWidePointerComparisonsAddrSuggestion, AtomicOrderingFence, AtomicOrderingLoad,
     AtomicOrderingStore, ImproperCTypes, InvalidAtomicOrderingDiag, InvalidNanComparisons,
-    InvalidNanComparisonsSuggestion, OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign,
-    OverflowingBinHexSignBitSub, OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp,
-    OverflowingLiteral, OverflowingUInt, RangeEndpointOutOfRange, UnusedComparisons,
-    UseInclusiveRange, VariantSizeDifferencesDiag,
+    InvalidNanComparisonsSuggestion, UnusedComparisons, VariantSizeDifferencesDiag,
 };
 use crate::{fluent_generated as fluent, LateContext, LateLintPass, LintContext};
 
+mod literal;
+
+use literal::{int_ty_range, lint_literal, uint_ty_range};
+
 declare_lint! {
     /// The `unused_comparisons` lint detects comparisons made useless by
     /// limits of the types involved.
@@ -185,403 +186,6 @@ impl TypeLimits {
     }
 }
 
-/// Attempts to special-case the overflowing literal lint when it occurs as a range endpoint (`expr..MAX+1`).
-/// Returns `true` iff the lint was emitted.
-fn lint_overflowing_range_endpoint<'tcx>(
-    cx: &LateContext<'tcx>,
-    lit: &hir::Lit,
-    lit_val: u128,
-    max: u128,
-    expr: &'tcx hir::Expr<'tcx>,
-    ty: &str,
-) -> bool {
-    // Look past casts to support cases like `0..256 as u8`
-    let (expr, lit_span) = if let Node::Expr(par_expr) = cx.tcx.parent_hir_node(expr.hir_id)
-        && let ExprKind::Cast(_, _) = par_expr.kind
-    {
-        (par_expr, expr.span)
-    } else {
-        (expr, expr.span)
-    };
-
-    // We only want to handle exclusive (`..`) ranges,
-    // which are represented as `ExprKind::Struct`.
-    let Node::ExprField(field) = cx.tcx.parent_hir_node(expr.hir_id) else { return false };
-    let Node::Expr(struct_expr) = cx.tcx.parent_hir_node(field.hir_id) else { return false };
-    if !is_range_literal(struct_expr) {
-        return false;
-    };
-    let ExprKind::Struct(_, [start, end], _) = &struct_expr.kind else { return false };
-
-    // We can suggest using an inclusive range
-    // (`..=`) instead only if it is the `end` that is
-    // overflowing and only by 1.
-    if !(end.expr.hir_id == expr.hir_id && lit_val - 1 == max) {
-        return false;
-    };
-
-    use rustc_ast::{LitIntType, LitKind};
-    let suffix = match lit.node {
-        LitKind::Int(_, LitIntType::Signed(s)) => s.name_str(),
-        LitKind::Int(_, LitIntType::Unsigned(s)) => s.name_str(),
-        LitKind::Int(_, LitIntType::Unsuffixed) => "",
-        _ => bug!(),
-    };
-
-    let sub_sugg = if expr.span.lo() == lit_span.lo() {
-        let Ok(start) = cx.sess().source_map().span_to_snippet(start.span) else { return false };
-        UseInclusiveRange::WithoutParen {
-            sugg: struct_expr.span.shrink_to_lo().to(lit_span.shrink_to_hi()),
-            start,
-            literal: lit_val - 1,
-            suffix,
-        }
-    } else {
-        UseInclusiveRange::WithParen {
-            eq_sugg: expr.span.shrink_to_lo(),
-            lit_sugg: lit_span,
-            literal: lit_val - 1,
-            suffix,
-        }
-    };
-
-    cx.emit_span_lint(
-        OVERFLOWING_LITERALS,
-        struct_expr.span,
-        RangeEndpointOutOfRange { ty, sub: sub_sugg },
-    );
-
-    // We've just emitted a lint, special cased for `(...)..MAX+1` ranges,
-    // return `true` so the callers don't also emit a lint
-    true
-}
-
-// For `isize` & `usize`, be conservative with the warnings, so that the
-// warnings are consistent between 32- and 64-bit platforms.
-fn int_ty_range(int_ty: ty::IntTy) -> (i128, i128) {
-    match int_ty {
-        ty::IntTy::Isize => (i64::MIN.into(), i64::MAX.into()),
-        ty::IntTy::I8 => (i8::MIN.into(), i8::MAX.into()),
-        ty::IntTy::I16 => (i16::MIN.into(), i16::MAX.into()),
-        ty::IntTy::I32 => (i32::MIN.into(), i32::MAX.into()),
-        ty::IntTy::I64 => (i64::MIN.into(), i64::MAX.into()),
-        ty::IntTy::I128 => (i128::MIN, i128::MAX),
-    }
-}
-
-fn uint_ty_range(uint_ty: ty::UintTy) -> (u128, u128) {
-    let max = match uint_ty {
-        ty::UintTy::Usize => u64::MAX.into(),
-        ty::UintTy::U8 => u8::MAX.into(),
-        ty::UintTy::U16 => u16::MAX.into(),
-        ty::UintTy::U32 => u32::MAX.into(),
-        ty::UintTy::U64 => u64::MAX.into(),
-        ty::UintTy::U128 => u128::MAX,
-    };
-    (0, max)
-}
-
-fn get_bin_hex_repr(cx: &LateContext<'_>, lit: &hir::Lit) -> Option<String> {
-    let src = cx.sess().source_map().span_to_snippet(lit.span).ok()?;
-    let firstch = src.chars().next()?;
-
-    if firstch == '0' {
-        match src.chars().nth(1) {
-            Some('x' | 'b') => return Some(src),
-            _ => return None,
-        }
-    }
-
-    None
-}
-
-fn report_bin_hex_error(
-    cx: &LateContext<'_>,
-    expr: &hir::Expr<'_>,
-    ty: attr::IntType,
-    size: Size,
-    repr_str: String,
-    val: u128,
-    negative: bool,
-) {
-    let (t, actually) = match ty {
-        attr::IntType::SignedInt(t) => {
-            let actually = if negative { -(size.sign_extend(val)) } else { size.sign_extend(val) };
-            (t.name_str(), actually.to_string())
-        }
-        attr::IntType::UnsignedInt(t) => {
-            let actually = size.truncate(val);
-            (t.name_str(), actually.to_string())
-        }
-    };
-    let sign =
-        if negative { OverflowingBinHexSign::Negative } else { OverflowingBinHexSign::Positive };
-    let sub = get_type_suggestion(cx.typeck_results().node_type(expr.hir_id), val, negative).map(
-        |suggestion_ty| {
-            if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
-                let (sans_suffix, _) = repr_str.split_at(pos);
-                OverflowingBinHexSub::Suggestion { span: expr.span, suggestion_ty, sans_suffix }
-            } else {
-                OverflowingBinHexSub::Help { suggestion_ty }
-            }
-        },
-    );
-    let sign_bit_sub = (!negative)
-        .then(|| {
-            let ty::Int(int_ty) = cx.typeck_results().node_type(expr.hir_id).kind() else {
-                return None;
-            };
-
-            let Some(bit_width) = int_ty.bit_width() else {
-                return None; // isize case
-            };
-
-            // Skip if sign bit is not set
-            if (val & (1 << (bit_width - 1))) == 0 {
-                return None;
-            }
-
-            let lit_no_suffix =
-                if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
-                    repr_str.split_at(pos).0
-                } else {
-                    &repr_str
-                };
-
-            Some(OverflowingBinHexSignBitSub {
-                span: expr.span,
-                lit_no_suffix,
-                negative_val: actually.clone(),
-                int_ty: int_ty.name_str(),
-                uint_ty: int_ty.to_unsigned().name_str(),
-            })
-        })
-        .flatten();
-
-    cx.emit_span_lint(
-        OVERFLOWING_LITERALS,
-        expr.span,
-        OverflowingBinHex {
-            ty: t,
-            lit: repr_str.clone(),
-            dec: val,
-            actually,
-            sign,
-            sub,
-            sign_bit_sub,
-        },
-    )
-}
-
-// This function finds the next fitting type and generates a suggestion string.
-// It searches for fitting types in the following way (`X < Y`):
-//  - `iX`: if literal fits in `uX` => `uX`, else => `iY`
-//  - `-iX` => `iY`
-//  - `uX` => `uY`
-//
-// No suggestion for: `isize`, `usize`.
-fn get_type_suggestion(t: Ty<'_>, val: u128, negative: bool) -> Option<&'static str> {
-    use ty::IntTy::*;
-    use ty::UintTy::*;
-    macro_rules! find_fit {
-        ($ty:expr, $val:expr, $negative:expr,
-         $($type:ident => [$($utypes:expr),*] => [$($itypes:expr),*]),+) => {
-            {
-                let _neg = if negative { 1 } else { 0 };
-                match $ty {
-                    $($type => {
-                        $(if !negative && val <= uint_ty_range($utypes).1 {
-                            return Some($utypes.name_str())
-                        })*
-                        $(if val <= int_ty_range($itypes).1 as u128 + _neg {
-                            return Some($itypes.name_str())
-                        })*
-                        None
-                    },)+
-                    _ => None
-                }
-            }
-        }
-    }
-    match t.kind() {
-        ty::Int(i) => find_fit!(i, val, negative,
-                      I8 => [U8] => [I16, I32, I64, I128],
-                      I16 => [U16] => [I32, I64, I128],
-                      I32 => [U32] => [I64, I128],
-                      I64 => [U64] => [I128],
-                      I128 => [U128] => []),
-        ty::Uint(u) => find_fit!(u, val, negative,
-                      U8 => [U8, U16, U32, U64, U128] => [],
-                      U16 => [U16, U32, U64, U128] => [],
-                      U32 => [U32, U64, U128] => [],
-                      U64 => [U64, U128] => [],
-                      U128 => [U128] => []),
-        _ => None,
-    }
-}
-
-fn lint_int_literal<'tcx>(
-    cx: &LateContext<'tcx>,
-    type_limits: &TypeLimits,
-    e: &'tcx hir::Expr<'tcx>,
-    lit: &hir::Lit,
-    t: ty::IntTy,
-    v: u128,
-) {
-    let int_type = t.normalize(cx.sess().target.pointer_width);
-    let (min, max) = int_ty_range(int_type);
-    let max = max as u128;
-    let negative = type_limits.negated_expr_id == Some(e.hir_id);
-
-    // Detect literal value out of range [min, max] inclusive
-    // avoiding use of -min to prevent overflow/panic
-    if (negative && v > max + 1) || (!negative && v > max) {
-        if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
-            report_bin_hex_error(
-                cx,
-                e,
-                attr::IntType::SignedInt(ty::ast_int_ty(t)),
-                Integer::from_int_ty(cx, t).size(),
-                repr_str,
-                v,
-                negative,
-            );
-            return;
-        }
-
-        if lint_overflowing_range_endpoint(cx, lit, v, max, e, t.name_str()) {
-            // The overflowing literal lint was emitted by `lint_overflowing_range_endpoint`.
-            return;
-        }
-
-        let span = if negative { type_limits.negated_expr_span.unwrap() } else { e.span };
-        let lit = cx
-            .sess()
-            .source_map()
-            .span_to_snippet(span)
-            .unwrap_or_else(|_| if negative { format!("-{v}") } else { v.to_string() });
-        let help = get_type_suggestion(cx.typeck_results().node_type(e.hir_id), v, negative)
-            .map(|suggestion_ty| OverflowingIntHelp { suggestion_ty });
-
-        cx.emit_span_lint(
-            OVERFLOWING_LITERALS,
-            span,
-            OverflowingInt { ty: t.name_str(), lit, min, max, help },
-        );
-    }
-}
-
-fn lint_uint_literal<'tcx>(
-    cx: &LateContext<'tcx>,
-    e: &'tcx hir::Expr<'tcx>,
-    lit: &hir::Lit,
-    t: ty::UintTy,
-) {
-    let uint_type = t.normalize(cx.sess().target.pointer_width);
-    let (min, max) = uint_ty_range(uint_type);
-    let lit_val: u128 = match lit.node {
-        // _v is u8, within range by definition
-        ast::LitKind::Byte(_v) => return,
-        ast::LitKind::Int(v, _) => v.get(),
-        _ => bug!(),
-    };
-
-    if lit_val < min || lit_val > max {
-        if let Node::Expr(par_e) = cx.tcx.parent_hir_node(e.hir_id) {
-            match par_e.kind {
-                hir::ExprKind::Cast(..) => {
-                    if let ty::Char = cx.typeck_results().expr_ty(par_e).kind() {
-                        cx.emit_span_lint(
-                            OVERFLOWING_LITERALS,
-                            par_e.span,
-                            OnlyCastu8ToChar { span: par_e.span, literal: lit_val },
-                        );
-                        return;
-                    }
-                }
-                _ => {}
-            }
-        }
-        if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, t.name_str()) {
-            // The overflowing literal lint was emitted by `lint_overflowing_range_endpoint`.
-            return;
-        }
-        if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
-            report_bin_hex_error(
-                cx,
-                e,
-                attr::IntType::UnsignedInt(ty::ast_uint_ty(t)),
-                Integer::from_uint_ty(cx, t).size(),
-                repr_str,
-                lit_val,
-                false,
-            );
-            return;
-        }
-        cx.emit_span_lint(
-            OVERFLOWING_LITERALS,
-            e.span,
-            OverflowingUInt {
-                ty: t.name_str(),
-                lit: cx
-                    .sess()
-                    .source_map()
-                    .span_to_snippet(lit.span)
-                    .unwrap_or_else(|_| lit_val.to_string()),
-                min,
-                max,
-            },
-        );
-    }
-}
-
-fn lint_literal<'tcx>(
-    cx: &LateContext<'tcx>,
-    type_limits: &TypeLimits,
-    e: &'tcx hir::Expr<'tcx>,
-    lit: &hir::Lit,
-) {
-    match *cx.typeck_results().node_type(e.hir_id).kind() {
-        ty::Int(t) => {
-            match lit.node {
-                ast::LitKind::Int(v, ast::LitIntType::Signed(_) | ast::LitIntType::Unsuffixed) => {
-                    lint_int_literal(cx, type_limits, e, lit, t, v.get())
-                }
-                _ => bug!(),
-            };
-        }
-        ty::Uint(t) => lint_uint_literal(cx, e, lit, t),
-        ty::Float(t) => {
-            let (is_infinite, sym) = match lit.node {
-                ast::LitKind::Float(v, _) => match t {
-                    // FIXME(f16_f128): add this check once `is_infinite` is reliable (ABI
-                    // issues resolved).
-                    ty::FloatTy::F16 => (Ok(false), v),
-                    ty::FloatTy::F32 => (v.as_str().parse().map(f32::is_infinite), v),
-                    ty::FloatTy::F64 => (v.as_str().parse().map(f64::is_infinite), v),
-                    ty::FloatTy::F128 => (Ok(false), v),
-                },
-                _ => bug!(),
-            };
-            if is_infinite == Ok(true) {
-                cx.emit_span_lint(
-                    OVERFLOWING_LITERALS,
-                    e.span,
-                    OverflowingLiteral {
-                        ty: t.name_str(),
-                        lit: cx
-                            .sess()
-                            .source_map()
-                            .span_to_snippet(lit.span)
-                            .unwrap_or_else(|_| sym.to_string()),
-                    },
-                );
-            }
-        }
-        _ => {}
-    }
-}
-
 fn lint_nan<'tcx>(
     cx: &LateContext<'tcx>,
     e: &'tcx hir::Expr<'tcx>,
@@ -991,6 +595,8 @@ struct CTypesVisitorState<'tcx> {
     /// The original type being checked, before we recursed
     /// to any other types it contains.
     base_ty: Ty<'tcx>,
+    /// Number of times we recursed while checking the type
+    recursion_depth: usize,
 }
 
 enum FfiResult<'tcx> {
@@ -1296,12 +902,23 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
 
         // Protect against infinite recursion, for example
         // `struct S(*mut S);`.
-        // FIXME: A recursion limit is necessary as well, for irregular
-        // recursive types.
         if !acc.cache.insert(ty) {
             return FfiSafe;
         }
 
+        // Additional recursion check for more complex types like
+        // `struct A<T> { v: *const A<A<T>>, ... }` for which the
+        // cache check above won't be enough (fixes #130310)
+        if !tcx.recursion_limit().value_within_limit(acc.recursion_depth) {
+            return FfiUnsafe {
+                ty: acc.base_ty,
+                reason: fluent::lint_improper_ctypes_recursion_limit_reached,
+                help: None,
+            };
+        }
+
+        acc.recursion_depth += 1;
+
         match *ty.kind() {
             ty::Adt(def, args) => {
                 if let Some(boxed) = ty.boxed_ty()
@@ -1644,7 +1261,8 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
             return;
         }
 
-        let mut acc = CTypesVisitorState { cache: FxHashSet::default(), base_ty: ty };
+        let mut acc =
+            CTypesVisitorState { cache: FxHashSet::default(), base_ty: ty, recursion_depth: 0 };
         match self.check_type_for_ffi(&mut acc, ty) {
             FfiResult::FfiSafe => {}
             FfiResult::FfiPhantom(ty) => {
@@ -1702,7 +1320,10 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
     }
 
     fn is_internal_abi(&self, abi: SpecAbi) -> bool {
-        matches!(abi, SpecAbi::Rust | SpecAbi::RustCall | SpecAbi::RustIntrinsic)
+        matches!(
+            abi,
+            SpecAbi::Rust | SpecAbi::RustCall | SpecAbi::RustCold | SpecAbi::RustIntrinsic
+        )
     }
 
     /// Find any fn-ptr types with external ABIs in `ty`.
diff --git a/compiler/rustc_lint/src/types/literal.rs b/compiler/rustc_lint/src/types/literal.rs
new file mode 100644
index 00000000000..67404be24b5
--- /dev/null
+++ b/compiler/rustc_lint/src/types/literal.rs
@@ -0,0 +1,386 @@
+use hir::{is_range_literal, ExprKind, Node};
+use rustc_middle::ty::layout::IntegerExt;
+use rustc_middle::ty::Ty;
+use rustc_middle::{bug, ty};
+use rustc_target::abi::{Integer, Size};
+use {rustc_ast as ast, rustc_attr as attr, rustc_hir as hir};
+
+use crate::context::LintContext;
+use crate::lints::{
+    OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, OverflowingBinHexSignBitSub,
+    OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp, OverflowingLiteral, OverflowingUInt,
+    RangeEndpointOutOfRange, UseInclusiveRange,
+};
+use crate::types::{TypeLimits, OVERFLOWING_LITERALS};
+use crate::LateContext;
+
+/// Attempts to special-case the overflowing literal lint when it occurs as a range endpoint (`expr..MAX+1`).
+/// Returns `true` iff the lint was emitted.
+fn lint_overflowing_range_endpoint<'tcx>(
+    cx: &LateContext<'tcx>,
+    lit: &hir::Lit,
+    lit_val: u128,
+    max: u128,
+    expr: &'tcx hir::Expr<'tcx>,
+    ty: &str,
+) -> bool {
+    // Look past casts to support cases like `0..256 as u8`
+    let (expr, lit_span) = if let Node::Expr(par_expr) = cx.tcx.parent_hir_node(expr.hir_id)
+        && let ExprKind::Cast(_, _) = par_expr.kind
+    {
+        (par_expr, expr.span)
+    } else {
+        (expr, expr.span)
+    };
+
+    // We only want to handle exclusive (`..`) ranges,
+    // which are represented as `ExprKind::Struct`.
+    let Node::ExprField(field) = cx.tcx.parent_hir_node(expr.hir_id) else { return false };
+    let Node::Expr(struct_expr) = cx.tcx.parent_hir_node(field.hir_id) else { return false };
+    if !is_range_literal(struct_expr) {
+        return false;
+    };
+    let ExprKind::Struct(_, [start, end], _) = &struct_expr.kind else { return false };
+
+    // We can suggest using an inclusive range
+    // (`..=`) instead only if it is the `end` that is
+    // overflowing and only by 1.
+    if !(end.expr.hir_id == expr.hir_id && lit_val - 1 == max) {
+        return false;
+    };
+
+    use rustc_ast::{LitIntType, LitKind};
+    let suffix = match lit.node {
+        LitKind::Int(_, LitIntType::Signed(s)) => s.name_str(),
+        LitKind::Int(_, LitIntType::Unsigned(s)) => s.name_str(),
+        LitKind::Int(_, LitIntType::Unsuffixed) => "",
+        _ => bug!(),
+    };
+
+    let sub_sugg = if expr.span.lo() == lit_span.lo() {
+        let Ok(start) = cx.sess().source_map().span_to_snippet(start.span) else { return false };
+        UseInclusiveRange::WithoutParen {
+            sugg: struct_expr.span.shrink_to_lo().to(lit_span.shrink_to_hi()),
+            start,
+            literal: lit_val - 1,
+            suffix,
+        }
+    } else {
+        UseInclusiveRange::WithParen {
+            eq_sugg: expr.span.shrink_to_lo(),
+            lit_sugg: lit_span,
+            literal: lit_val - 1,
+            suffix,
+        }
+    };
+
+    cx.emit_span_lint(
+        OVERFLOWING_LITERALS,
+        struct_expr.span,
+        RangeEndpointOutOfRange { ty, sub: sub_sugg },
+    );
+
+    // We've just emitted a lint, special cased for `(...)..MAX+1` ranges,
+    // return `true` so the callers don't also emit a lint
+    true
+}
+
+// For `isize` & `usize`, be conservative with the warnings, so that the
+// warnings are consistent between 32- and 64-bit platforms.
+pub(crate) fn int_ty_range(int_ty: ty::IntTy) -> (i128, i128) {
+    match int_ty {
+        ty::IntTy::Isize => (i64::MIN.into(), i64::MAX.into()),
+        ty::IntTy::I8 => (i8::MIN.into(), i8::MAX.into()),
+        ty::IntTy::I16 => (i16::MIN.into(), i16::MAX.into()),
+        ty::IntTy::I32 => (i32::MIN.into(), i32::MAX.into()),
+        ty::IntTy::I64 => (i64::MIN.into(), i64::MAX.into()),
+        ty::IntTy::I128 => (i128::MIN, i128::MAX),
+    }
+}
+
+pub(crate) fn uint_ty_range(uint_ty: ty::UintTy) -> (u128, u128) {
+    let max = match uint_ty {
+        ty::UintTy::Usize => u64::MAX.into(),
+        ty::UintTy::U8 => u8::MAX.into(),
+        ty::UintTy::U16 => u16::MAX.into(),
+        ty::UintTy::U32 => u32::MAX.into(),
+        ty::UintTy::U64 => u64::MAX.into(),
+        ty::UintTy::U128 => u128::MAX,
+    };
+    (0, max)
+}
+
+fn get_bin_hex_repr(cx: &LateContext<'_>, lit: &hir::Lit) -> Option<String> {
+    let src = cx.sess().source_map().span_to_snippet(lit.span).ok()?;
+    let firstch = src.chars().next()?;
+
+    if firstch == '0' {
+        match src.chars().nth(1) {
+            Some('x' | 'b') => return Some(src),
+            _ => return None,
+        }
+    }
+
+    None
+}
+
+fn report_bin_hex_error(
+    cx: &LateContext<'_>,
+    expr: &hir::Expr<'_>,
+    ty: attr::IntType,
+    size: Size,
+    repr_str: String,
+    val: u128,
+    negative: bool,
+) {
+    let (t, actually) = match ty {
+        attr::IntType::SignedInt(t) => {
+            let actually = if negative { -(size.sign_extend(val)) } else { size.sign_extend(val) };
+            (t.name_str(), actually.to_string())
+        }
+        attr::IntType::UnsignedInt(t) => {
+            let actually = size.truncate(val);
+            (t.name_str(), actually.to_string())
+        }
+    };
+    let sign =
+        if negative { OverflowingBinHexSign::Negative } else { OverflowingBinHexSign::Positive };
+    let sub = get_type_suggestion(cx.typeck_results().node_type(expr.hir_id), val, negative).map(
+        |suggestion_ty| {
+            if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
+                let (sans_suffix, _) = repr_str.split_at(pos);
+                OverflowingBinHexSub::Suggestion { span: expr.span, suggestion_ty, sans_suffix }
+            } else {
+                OverflowingBinHexSub::Help { suggestion_ty }
+            }
+        },
+    );
+    let sign_bit_sub = (!negative)
+        .then(|| {
+            let ty::Int(int_ty) = cx.typeck_results().node_type(expr.hir_id).kind() else {
+                return None;
+            };
+
+            let Some(bit_width) = int_ty.bit_width() else {
+                return None; // isize case
+            };
+
+            // Skip if sign bit is not set
+            if (val & (1 << (bit_width - 1))) == 0 {
+                return None;
+            }
+
+            let lit_no_suffix =
+                if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
+                    repr_str.split_at(pos).0
+                } else {
+                    &repr_str
+                };
+
+            Some(OverflowingBinHexSignBitSub {
+                span: expr.span,
+                lit_no_suffix,
+                negative_val: actually.clone(),
+                int_ty: int_ty.name_str(),
+                uint_ty: int_ty.to_unsigned().name_str(),
+            })
+        })
+        .flatten();
+
+    cx.emit_span_lint(
+        OVERFLOWING_LITERALS,
+        expr.span,
+        OverflowingBinHex {
+            ty: t,
+            lit: repr_str.clone(),
+            dec: val,
+            actually,
+            sign,
+            sub,
+            sign_bit_sub,
+        },
+    )
+}
+
+// Find the "next" fitting integer and return a suggestion string
+//
+// No suggestion is offered for `{i,u}size`. Otherwise, we try to suggest an equal-sized type.
+fn get_type_suggestion(t: Ty<'_>, val: u128, negative: bool) -> Option<&'static str> {
+    match t.kind() {
+        ty::Uint(ty::UintTy::Usize) | ty::Int(ty::IntTy::Isize) => None,
+        ty::Uint(_) => Some(Integer::fit_unsigned(val).uint_ty_str()),
+        ty::Int(_) if negative => Some(Integer::fit_signed(-(val as i128)).int_ty_str()),
+        ty::Int(int) => {
+            let signed = Integer::fit_signed(val as i128);
+            let unsigned = Integer::fit_unsigned(val);
+            Some(if Some(unsigned.size().bits()) == int.bit_width() {
+                unsigned.uint_ty_str()
+            } else {
+                signed.int_ty_str()
+            })
+        }
+        _ => None,
+    }
+}
+
+fn lint_int_literal<'tcx>(
+    cx: &LateContext<'tcx>,
+    type_limits: &TypeLimits,
+    e: &'tcx hir::Expr<'tcx>,
+    lit: &hir::Lit,
+    t: ty::IntTy,
+    v: u128,
+) {
+    let int_type = t.normalize(cx.sess().target.pointer_width);
+    let (min, max) = int_ty_range(int_type);
+    let max = max as u128;
+    let negative = type_limits.negated_expr_id == Some(e.hir_id);
+
+    // Detect literal value out of range [min, max] inclusive
+    // avoiding use of -min to prevent overflow/panic
+    if (negative && v > max + 1) || (!negative && v > max) {
+        if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
+            report_bin_hex_error(
+                cx,
+                e,
+                attr::IntType::SignedInt(ty::ast_int_ty(t)),
+                Integer::from_int_ty(cx, t).size(),
+                repr_str,
+                v,
+                negative,
+            );
+            return;
+        }
+
+        if lint_overflowing_range_endpoint(cx, lit, v, max, e, t.name_str()) {
+            // The overflowing literal lint was emitted by `lint_overflowing_range_endpoint`.
+            return;
+        }
+
+        let span = if negative { type_limits.negated_expr_span.unwrap() } else { e.span };
+        let lit = cx
+            .sess()
+            .source_map()
+            .span_to_snippet(span)
+            .unwrap_or_else(|_| if negative { format!("-{v}") } else { v.to_string() });
+        let help = get_type_suggestion(cx.typeck_results().node_type(e.hir_id), v, negative)
+            .map(|suggestion_ty| OverflowingIntHelp { suggestion_ty });
+
+        cx.emit_span_lint(
+            OVERFLOWING_LITERALS,
+            span,
+            OverflowingInt { ty: t.name_str(), lit, min, max, help },
+        );
+    }
+}
+
+fn lint_uint_literal<'tcx>(
+    cx: &LateContext<'tcx>,
+    e: &'tcx hir::Expr<'tcx>,
+    lit: &hir::Lit,
+    t: ty::UintTy,
+) {
+    let uint_type = t.normalize(cx.sess().target.pointer_width);
+    let (min, max) = uint_ty_range(uint_type);
+    let lit_val: u128 = match lit.node {
+        // _v is u8, within range by definition
+        ast::LitKind::Byte(_v) => return,
+        ast::LitKind::Int(v, _) => v.get(),
+        _ => bug!(),
+    };
+
+    if lit_val < min || lit_val > max {
+        if let Node::Expr(par_e) = cx.tcx.parent_hir_node(e.hir_id) {
+            match par_e.kind {
+                hir::ExprKind::Cast(..) => {
+                    if let ty::Char = cx.typeck_results().expr_ty(par_e).kind() {
+                        cx.emit_span_lint(
+                            OVERFLOWING_LITERALS,
+                            par_e.span,
+                            OnlyCastu8ToChar { span: par_e.span, literal: lit_val },
+                        );
+                        return;
+                    }
+                }
+                _ => {}
+            }
+        }
+        if lint_overflowing_range_endpoint(cx, lit, lit_val, max, e, t.name_str()) {
+            // The overflowing literal lint was emitted by `lint_overflowing_range_endpoint`.
+            return;
+        }
+        if let Some(repr_str) = get_bin_hex_repr(cx, lit) {
+            report_bin_hex_error(
+                cx,
+                e,
+                attr::IntType::UnsignedInt(ty::ast_uint_ty(t)),
+                Integer::from_uint_ty(cx, t).size(),
+                repr_str,
+                lit_val,
+                false,
+            );
+            return;
+        }
+        cx.emit_span_lint(
+            OVERFLOWING_LITERALS,
+            e.span,
+            OverflowingUInt {
+                ty: t.name_str(),
+                lit: cx
+                    .sess()
+                    .source_map()
+                    .span_to_snippet(lit.span)
+                    .unwrap_or_else(|_| lit_val.to_string()),
+                min,
+                max,
+            },
+        );
+    }
+}
+
+pub(crate) fn lint_literal<'tcx>(
+    cx: &LateContext<'tcx>,
+    type_limits: &TypeLimits,
+    e: &'tcx hir::Expr<'tcx>,
+    lit: &hir::Lit,
+) {
+    match *cx.typeck_results().node_type(e.hir_id).kind() {
+        ty::Int(t) => {
+            match lit.node {
+                ast::LitKind::Int(v, ast::LitIntType::Signed(_) | ast::LitIntType::Unsuffixed) => {
+                    lint_int_literal(cx, type_limits, e, lit, t, v.get())
+                }
+                _ => bug!(),
+            };
+        }
+        ty::Uint(t) => lint_uint_literal(cx, e, lit, t),
+        ty::Float(t) => {
+            let (is_infinite, sym) = match lit.node {
+                ast::LitKind::Float(v, _) => match t {
+                    // FIXME(f16_f128): add this check once `is_infinite` is reliable (ABI
+                    // issues resolved).
+                    ty::FloatTy::F16 => (Ok(false), v),
+                    ty::FloatTy::F32 => (v.as_str().parse().map(f32::is_infinite), v),
+                    ty::FloatTy::F64 => (v.as_str().parse().map(f64::is_infinite), v),
+                    ty::FloatTy::F128 => (Ok(false), v),
+                },
+                _ => bug!(),
+            };
+            if is_infinite == Ok(true) {
+                cx.emit_span_lint(
+                    OVERFLOWING_LITERALS,
+                    e.span,
+                    OverflowingLiteral {
+                        ty: t.name_str(),
+                        lit: cx
+                            .sess()
+                            .source_map()
+                            .span_to_snippet(lit.span)
+                            .unwrap_or_else(|_| sym.to_string()),
+                    },
+                );
+            }
+        }
+        _ => {}
+    }
+}
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 9b6d63c2ef4..acdedb06141 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -99,7 +99,6 @@ declare_lint_pass! {
         SINGLE_USE_LIFETIMES,
         SOFT_UNSTABLE,
         STABLE_FEATURES,
-        STATIC_MUT_REFS,
         TEST_UNSTABLE_LINT,
         TEXT_DIRECTION_CODEPOINT_IN_COMMENT,
         TRIVIAL_CASTS,
@@ -1928,57 +1927,6 @@ declare_lint! {
 }
 
 declare_lint! {
-    /// The `static_mut_refs` lint checks for shared or mutable references
-    /// of mutable static inside `unsafe` blocks and `unsafe` functions.
-    ///
-    /// ### Example
-    ///
-    /// ```rust,edition2021
-    /// fn main() {
-    ///     static mut X: i32 = 23;
-    ///     static mut Y: i32 = 24;
-    ///
-    ///     unsafe {
-    ///         let y = &X;
-    ///         let ref x = X;
-    ///         let (x, y) = (&X, &Y);
-    ///         foo(&X);
-    ///     }
-    /// }
-    ///
-    /// unsafe fn _foo() {
-    ///     static mut X: i32 = 23;
-    ///     static mut Y: i32 = 24;
-    ///
-    ///     let y = &X;
-    ///     let ref x = X;
-    ///     let (x, y) = (&X, &Y);
-    ///     foo(&X);
-    /// }
-    ///
-    /// fn foo<'a>(_x: &'a i32) {}
-    /// ```
-    ///
-    /// {{produces}}
-    ///
-    /// ### Explanation
-    ///
-    /// Shared or mutable references of mutable static are almost always a mistake and
-    /// can lead to undefined behavior and various other problems in your code.
-    ///
-    /// This lint is "warn" by default on editions up to 2021, in 2024 there is
-    /// a hard error instead.
-    pub STATIC_MUT_REFS,
-    Warn,
-    "shared references or mutable references of mutable static is discouraged",
-    @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::EditionError(Edition::Edition2024),
-        reference: "issue #114447 <https://github.com/rust-lang/rust/issues/114447>",
-        explain_reason: false,
-    };
-}
-
-declare_lint! {
     /// The `absolute_paths_not_starting_with_crate` lint detects fully
     /// qualified paths that start with a module name instead of `crate`,
     /// `self`, or an extern crate name
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index 5c4b7e5664d..f5ed69658ce 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -12,7 +12,7 @@ use rustc_error_messages::{DiagMessage, MultiSpan};
 use rustc_hir::def::Namespace;
 use rustc_hir::{HashStableContext, HirId, MissingLifetimeKind};
 use rustc_macros::{Decodable, Encodable, HashStable_Generic};
-use rustc_span::edition::Edition;
+pub use rustc_span::edition::Edition;
 use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent};
 use rustc_span::{sym, Span, Symbol};
 use rustc_target::spec::abi::Abi;
diff --git a/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp
index a8c278741a7..feac6a5649c 100644
--- a/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/ArchiveWrapper.cpp
@@ -196,14 +196,10 @@ extern "C" LLVMRustResult LLVMRustWriteArchive(
     }
   }
 
-#if LLVM_VERSION_LT(18, 0)
-  auto Result = writeArchive(Dst, Members, WriteSymbtab, Kind, true, false);
-#else
   auto SymtabMode = WriteSymbtab ? SymtabWritingMode::NormalSymtab
                                  : SymtabWritingMode::NoSymtab;
   auto Result =
       writeArchive(Dst, Members, SymtabMode, Kind, true, false, nullptr, isEC);
-#endif
   if (!Result)
     return LLVMRustResult::Success;
   LLVMRustSetLastError(toString(std::move(Result)).c_str());
diff --git a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
index e842f47f48c..4532fd8d48d 100644
--- a/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/CoverageMappingWrapper.cpp
@@ -58,17 +58,10 @@ fromRust(LLVMRustCounterMappingRegionKind Kind) {
     return coverage::CounterMappingRegion::GapRegion;
   case LLVMRustCounterMappingRegionKind::BranchRegion:
     return coverage::CounterMappingRegion::BranchRegion;
-#if LLVM_VERSION_GE(18, 0)
   case LLVMRustCounterMappingRegionKind::MCDCDecisionRegion:
     return coverage::CounterMappingRegion::MCDCDecisionRegion;
   case LLVMRustCounterMappingRegionKind::MCDCBranchRegion:
     return coverage::CounterMappingRegion::MCDCBranchRegion;
-#else
-  case LLVMRustCounterMappingRegionKind::MCDCDecisionRegion:
-    break;
-  case LLVMRustCounterMappingRegionKind::MCDCBranchRegion:
-    break;
-#endif
   }
   report_fatal_error("Bad LLVMRustCounterMappingRegionKind!");
 }
@@ -100,7 +93,7 @@ struct LLVMRustMCDCParameters {
 // https://github.com/rust-lang/llvm-project/blob/66a2881a/llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h#L253-L263
 // and representations in 19
 // https://github.com/llvm/llvm-project/blob/843cc474faefad1d639f4c44c1cf3ad7dbda76c8/llvm/include/llvm/ProfileData/Coverage/MCDCTypes.h
-#if LLVM_VERSION_GE(18, 0) && LLVM_VERSION_LT(19, 0)
+#if LLVM_VERSION_LT(19, 0)
 static coverage::CounterMappingRegion::MCDCParameters
 fromRust(LLVMRustMCDCParameters Params) {
   auto parameter = coverage::CounterMappingRegion::MCDCParameters{};
@@ -126,7 +119,7 @@ fromRust(LLVMRustMCDCParameters Params) {
   }
   report_fatal_error("Bad LLVMRustMCDCParametersTag!");
 }
-#elif LLVM_VERSION_GE(19, 0)
+#else
 static coverage::mcdc::Parameters fromRust(LLVMRustMCDCParameters Params) {
   switch (Params.Tag) {
   case LLVMRustMCDCParametersTag::None:
@@ -221,7 +214,7 @@ extern "C" void LLVMRustCoverageWriteMappingToBuffer(
            RustMappingRegions, NumMappingRegions)) {
     MappingRegions.emplace_back(
         fromRust(Region.Count), fromRust(Region.FalseCount),
-#if LLVM_VERSION_GE(18, 0) && LLVM_VERSION_LT(19, 0)
+#if LLVM_VERSION_LT(19, 0)
         // LLVM 19 may move this argument to last.
         fromRust(Region.MCDCParameters),
 #endif
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 4a4ba165b57..165fb7aa6c3 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -26,21 +26,19 @@
 #include "llvm/Passes/StandardInstrumentations.h"
 #include "llvm/Support/CBindingWrapping.h"
 #include "llvm/Support/FileSystem.h"
+#include "llvm/Support/TimeProfiler.h"
 #include "llvm/Support/VirtualFileSystem.h"
 #include "llvm/Target/TargetMachine.h"
+#include "llvm/TargetParser/Host.h"
 #include "llvm/Transforms/IPO/AlwaysInliner.h"
 #include "llvm/Transforms/IPO/FunctionImport.h"
 #include "llvm/Transforms/IPO/Internalize.h"
 #include "llvm/Transforms/IPO/LowerTypeTests.h"
 #include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
-#include "llvm/Transforms/Utils/AddDiscriminators.h"
-#include "llvm/Transforms/Utils/FunctionImportUtils.h"
-#if LLVM_VERSION_GE(18, 0)
-#include "llvm/TargetParser/Host.h"
-#endif
-#include "llvm/Support/TimeProfiler.h"
 #include "llvm/Transforms/Instrumentation/AddressSanitizer.h"
 #include "llvm/Transforms/Instrumentation/DataFlowSanitizer.h"
+#include "llvm/Transforms/Utils/AddDiscriminators.h"
+#include "llvm/Transforms/Utils/FunctionImportUtils.h"
 #if LLVM_VERSION_GE(19, 0)
 #include "llvm/Support/PGOOptions.h"
 #endif
@@ -240,11 +238,7 @@ enum class LLVMRustCodeGenOptLevel {
   Aggressive,
 };
 
-#if LLVM_VERSION_GE(18, 0)
 using CodeGenOptLevelEnum = llvm::CodeGenOptLevel;
-#else
-using CodeGenOptLevelEnum = llvm::CodeGenOpt::Level;
-#endif
 
 static CodeGenOptLevelEnum fromRust(LLVMRustCodeGenOptLevel Level) {
   switch (Level) {
@@ -370,21 +364,16 @@ extern "C" void LLVMRustPrintTargetCPUs(LLVMTargetMachineRef TM,
 }
 
 extern "C" size_t LLVMRustGetTargetFeaturesCount(LLVMTargetMachineRef TM) {
-#if LLVM_VERSION_GE(18, 0)
   const TargetMachine *Target = unwrap(TM);
   const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
   const ArrayRef<SubtargetFeatureKV> FeatTable =
       MCInfo->getAllProcessorFeatures();
   return FeatTable.size();
-#else
-  return 0;
-#endif
 }
 
 extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef TM, size_t Index,
                                          const char **Feature,
                                          const char **Desc) {
-#if LLVM_VERSION_GE(18, 0)
   const TargetMachine *Target = unwrap(TM);
   const MCSubtargetInfo *MCInfo = Target->getMCSubtargetInfo();
   const ArrayRef<SubtargetFeatureKV> FeatTable =
@@ -392,7 +381,6 @@ extern "C" void LLVMRustGetTargetFeature(LLVMTargetMachineRef TM, size_t Index,
   const SubtargetFeatureKV Feat = FeatTable[Index];
   *Feature = Feat.Key;
   *Desc = Feat.Desc;
-#endif
 }
 
 extern "C" const char *LLVMRustGetHostCPUName(size_t *len) {
@@ -497,6 +485,22 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
   Options.EmitStackSizeSection = EmitStackSizeSection;
 
   if (ArgsCstrBuff != nullptr) {
+#if LLVM_VERSION_GE(20, 0)
+    int buffer_offset = 0;
+    assert(ArgsCstrBuff[ArgsCstrBuffLen - 1] == '\0');
+    auto Arg0 = std::string(ArgsCstrBuff);
+    buffer_offset = Arg0.size() + 1;
+    auto ArgsCppStr =
+        std::string(ArgsCstrBuff + buffer_offset, ArgsCstrBuffLen - 1);
+    auto i = 0;
+    while (i != std::string::npos) {
+      i = ArgsCppStr.find('\0', i + 1);
+      if (i != std::string::npos)
+        ArgsCppStr.replace(i, i + 1, " ");
+    }
+    Options.MCOptions.Argv0 = Arg0;
+    Options.MCOptions.CommandlineArgs = ArgsCppStr;
+#else
     int buffer_offset = 0;
     assert(ArgsCstrBuff[ArgsCstrBuffLen - 1] == '\0');
 
@@ -522,6 +526,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
     Options.MCOptions.Argv0 = arg0;
     Options.MCOptions.CommandLineArgs =
         llvm::ArrayRef<std::string>(cmd_arg_strings, num_cmd_arg_strings);
+#endif
   }
 
   TargetMachine *TM = TheTarget->createTargetMachine(
@@ -530,10 +535,11 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
 }
 
 extern "C" void LLVMRustDisposeTargetMachine(LLVMTargetMachineRef TM) {
-
+#if LLVM_VERSION_LT(20, 0)
   MCTargetOptions &MCOptions = unwrap(TM)->Options.MCOptions;
   delete[] MCOptions.Argv0;
   delete[] MCOptions.CommandLineArgs.data();
+#endif
 
   delete unwrap(TM);
 }
@@ -569,17 +575,9 @@ enum class LLVMRustFileType {
 static CodeGenFileType fromRust(LLVMRustFileType Type) {
   switch (Type) {
   case LLVMRustFileType::AssemblyFile:
-#if LLVM_VERSION_GE(18, 0)
     return CodeGenFileType::AssemblyFile;
-#else
-    return CGFT_AssemblyFile;
-#endif
   case LLVMRustFileType::ObjectFile:
-#if LLVM_VERSION_GE(18, 0)
     return CodeGenFileType::ObjectFile;
-#else
-    return CGFT_ObjectFile;
-#endif
   default:
     report_fatal_error("Bad FileType.");
   }
@@ -865,11 +863,7 @@ extern "C" LLVMRustResult LLVMRustOptimize(
           // cargo run tests in multhreading mode by default
           // so use atomics for coverage counters
           Options.Atomic = true;
-#if LLVM_VERSION_GE(18, 0)
           MPM.addPass(InstrProfilingLoweringPass(Options, false));
-#else
-          MPM.addPass(InstrProfiling(Options, false));
-#endif
         });
   }
 
@@ -1210,15 +1204,13 @@ struct LLVMRustThinLTOData {
 
   // Not 100% sure what these are, but they impact what's internalized and
   // what's inlined across modules, I believe.
-#if LLVM_VERSION_GE(18, 0)
+#if LLVM_VERSION_GE(20, 0)
+  FunctionImporter::ImportListsTy ImportLists;
+#else
   DenseMap<StringRef, FunctionImporter::ImportMapTy> ImportLists;
+#endif
   DenseMap<StringRef, FunctionImporter::ExportSetTy> ExportLists;
   DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries;
-#else
-  StringMap<FunctionImporter::ImportMapTy> ImportLists;
-  StringMap<FunctionImporter::ExportSetTy> ExportLists;
-  StringMap<GVSummaryMapTy> ModuleToDefinedGVSummaries;
-#endif
   StringMap<std::map<GlobalValue::GUID, GlobalValue::LinkageTypes>> ResolvedODR;
 
   LLVMRustThinLTOData() : Index(/* HaveGVs = */ false) {}
@@ -1270,11 +1262,7 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, int num_modules,
 
     Ret->ModuleMap[module->identifier] = mem_buffer;
 
-#if LLVM_VERSION_GE(18, 0)
     if (Error Err = readModuleSummaryIndex(mem_buffer, Ret->Index)) {
-#else
-    if (Error Err = readModuleSummaryIndex(mem_buffer, Ret->Index, i)) {
-#endif
       LLVMRustSetLastError(toString(std::move(Err)).c_str());
       return nullptr;
     }
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index ed12318c88d..f9fc2bd6da3 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -310,16 +310,10 @@ static Attribute::AttrKind fromRust(LLVMRustAttribute Kind) {
     return Attribute::SafeStack;
   case FnRetThunkExtern:
     return Attribute::FnRetThunkExtern;
-#if LLVM_VERSION_GE(18, 0)
   case Writable:
     return Attribute::Writable;
   case DeadOnUnwind:
     return Attribute::DeadOnUnwind;
-#else
-  case Writable:
-  case DeadOnUnwind:
-    report_fatal_error("Not supported on this LLVM version");
-#endif
   }
   report_fatal_error("bad AttributeKind");
 }
@@ -1061,11 +1055,7 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateStaticMemberType(
   return wrap(Builder->createStaticMemberType(
       unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
       unwrapDI<DIFile>(File), LineNo, unwrapDI<DIType>(Ty), fromRust(Flags),
-      unwrap<llvm::ConstantInt>(val),
-#if LLVM_VERSION_GE(18, 0)
-      llvm::dwarf::DW_TAG_member,
-#endif
-      AlignInBits));
+      unwrap<llvm::ConstantInt>(val), llvm::dwarf::DW_TAG_member, AlignInBits));
 }
 
 extern "C" LLVMMetadataRef
@@ -1182,10 +1172,7 @@ extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateEnumerationType(
       unwrapDI<DIDescriptor>(Scope), StringRef(Name, NameLen),
       unwrapDI<DIFile>(File), LineNumber, SizeInBits, AlignInBits,
       DINodeArray(unwrapDI<MDTuple>(Elements)), unwrapDI<DIType>(ClassTy),
-#if LLVM_VERSION_GE(18, 0)
-      /* RunTimeLang */ 0,
-#endif
-      "", IsScoped));
+      /* RunTimeLang */ 0, "", IsScoped));
 }
 
 extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateUnionType(
@@ -1552,27 +1539,19 @@ LLVMRustGetInstrProfIncrementIntrinsic(LLVMModuleRef M) {
 
 extern "C" LLVMValueRef
 LLVMRustGetInstrProfMCDCParametersIntrinsic(LLVMModuleRef M) {
-#if LLVM_VERSION_GE(18, 0)
   return wrap(llvm::Intrinsic::getDeclaration(
       unwrap(M), llvm::Intrinsic::instrprof_mcdc_parameters));
-#else
-  report_fatal_error("LLVM 18.0 is required for mcdc intrinsic functions");
-#endif
 }
 
 extern "C" LLVMValueRef
 LLVMRustGetInstrProfMCDCTVBitmapUpdateIntrinsic(LLVMModuleRef M) {
-#if LLVM_VERSION_GE(18, 0)
   return wrap(llvm::Intrinsic::getDeclaration(
       unwrap(M), llvm::Intrinsic::instrprof_mcdc_tvbitmap_update));
-#else
-  report_fatal_error("LLVM 18.0 is required for mcdc intrinsic functions");
-#endif
 }
 
 extern "C" LLVMValueRef
 LLVMRustGetInstrProfMCDCCondBitmapIntrinsic(LLVMModuleRef M) {
-#if LLVM_VERSION_GE(18, 0) && LLVM_VERSION_LT(19, 0)
+#if LLVM_VERSION_LT(19, 0)
   return wrap(llvm::Intrinsic::getDeclaration(
       unwrap(M), llvm::Intrinsic::instrprof_mcdc_condbitmap_update));
 #else
diff --git a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp
index d625935d925..54ee79dc290 100644
--- a/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/SymbolWrapper.cpp
@@ -150,11 +150,9 @@ extern "C" bool LLVMRustIsECObject(char *BufPtr, size_t BufLen) {
     return cast<llvm::object::COFFObjectFile>(&*Obj)->getMachine() !=
            COFF::IMAGE_FILE_MACHINE_ARM64;
 
-#if LLVM_VERSION_GE(18, 0)
   if (Obj->isCOFFImportFile())
     return cast<llvm::object::COFFImportFile>(&*Obj)->getMachine() !=
            COFF::IMAGE_FILE_MACHINE_ARM64;
-#endif
 
   if (Obj->isIR()) {
     Expected<std::string> TripleStr =
diff --git a/compiler/rustc_middle/messages.ftl b/compiler/rustc_middle/messages.ftl
index 2b9d9a07a98..39485a324f2 100644
--- a/compiler/rustc_middle/messages.ftl
+++ b/compiler/rustc_middle/messages.ftl
@@ -103,5 +103,5 @@ middle_unknown_layout =
     the type `{$ty}` has an unknown layout
 
 middle_values_too_big =
-    values of the type `{$ty}` are too big for the current architecture
+    values of the type `{$ty}` are too big for the target architecture
 middle_written_to_path = the full type name has been written to '{$path}'
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index fd6e2ad79b1..23cd247e884 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -33,6 +33,7 @@
 #![feature(allocator_api)]
 #![feature(array_windows)]
 #![feature(assert_matches)]
+#![feature(associated_type_defaults)]
 #![feature(box_as_ptr)]
 #![feature(box_patterns)]
 #![feature(closure_track_caller)]
diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
index b7d290e58d2..90dff0f5c7d 100644
--- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
+++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
@@ -120,9 +120,7 @@ bitflags::bitflags! {
         /// #[ffi_const]: applies clang's `const` attribute to a foreign function
         /// declaration.
         const FFI_CONST                 = 1 << 12;
-        /// #[cmse_nonsecure_entry]: with a TrustZone-M extension, declare a
-        /// function as an entry function from Non-Secure code.
-        const CMSE_NONSECURE_ENTRY      = 1 << 13;
+        // (Bit 13 was used for `#[cmse_nonsecure_entry]`, but is now unused.)
         // (Bit 14 was used for `#[coverage(off)]`, but is now unused.)
         /// `#[used(linker)]`:
         /// indicates that neither LLVM nor the linker will eliminate this function.
diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs
index 183b898253e..63ce47ef327 100644
--- a/compiler/rustc_middle/src/mir/basic_blocks.rs
+++ b/compiler/rustc_middle/src/mir/basic_blocks.rs
@@ -71,7 +71,7 @@ impl<'tcx> BasicBlocks<'tcx> {
     #[inline]
     pub fn reverse_postorder(&self) -> &[BasicBlock] {
         self.cache.reverse_postorder.get_or_init(|| {
-            let mut rpo: Vec<_> = Postorder::new(&self.basic_blocks, START_BLOCK).collect();
+            let mut rpo: Vec<_> = Postorder::new(&self.basic_blocks, START_BLOCK, ()).collect();
             rpo.reverse();
             rpo
         })
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index e312e65cc21..54dcfaf5d54 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1424,6 +1424,19 @@ impl<'tcx> BasicBlockData<'tcx> {
     pub fn is_empty_unreachable(&self) -> bool {
         self.statements.is_empty() && matches!(self.terminator().kind, TerminatorKind::Unreachable)
     }
+
+    /// Like [`Terminator::successors`] but tries to use information available from the [`Instance`]
+    /// to skip successors like the `false` side of an `if const {`.
+    ///
+    /// This is used to implement [`traversal::mono_reachable`] and
+    /// [`traversal::mono_reachable_reverse_postorder`].
+    pub fn mono_successors(&self, tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Successors<'_> {
+        if let Some((bits, targets)) = Body::try_const_mono_switchint(tcx, instance, self) {
+            targets.successors_for_value(bits)
+        } else {
+            self.terminator().successors()
+        }
+    }
 }
 
 ///////////////////////////////////////////////////////////////////////////
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index 962b93a25aa..c34e22eb873 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -413,6 +413,17 @@ mod helper {
     use super::*;
     pub type Successors<'a> = impl DoubleEndedIterator<Item = BasicBlock> + 'a;
     pub type SuccessorsMut<'a> = impl DoubleEndedIterator<Item = &'a mut BasicBlock> + 'a;
+
+    impl SwitchTargets {
+        /// Like [`SwitchTargets::target_for_value`], but returning the same type as
+        /// [`Terminator::successors`].
+        #[inline]
+        pub fn successors_for_value(&self, value: u128) -> Successors<'_> {
+            let target = self.target_for_value(value);
+            (&[]).into_iter().copied().chain(Some(target))
+        }
+    }
+
     impl<'tcx> TerminatorKind<'tcx> {
         #[inline]
         pub fn successors(&self) -> Successors<'_> {
diff --git a/compiler/rustc_middle/src/mir/traversal.rs b/compiler/rustc_middle/src/mir/traversal.rs
index 245e9096bad..b8b74da401c 100644
--- a/compiler/rustc_middle/src/mir/traversal.rs
+++ b/compiler/rustc_middle/src/mir/traversal.rs
@@ -104,36 +104,46 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> {
 /// ```
 ///
 /// A Postorder traversal of this graph is `D B C A` or `D C B A`
-pub struct Postorder<'a, 'tcx> {
+pub struct Postorder<'a, 'tcx, C> {
     basic_blocks: &'a IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
     visited: BitSet<BasicBlock>,
     visit_stack: Vec<(BasicBlock, Successors<'a>)>,
     root_is_start_block: bool,
+    extra: C,
 }
 
-impl<'a, 'tcx> Postorder<'a, 'tcx> {
+impl<'a, 'tcx, C> Postorder<'a, 'tcx, C>
+where
+    C: Customization<'tcx>,
+{
     pub fn new(
         basic_blocks: &'a IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
         root: BasicBlock,
-    ) -> Postorder<'a, 'tcx> {
+        extra: C,
+    ) -> Postorder<'a, 'tcx, C> {
         let mut po = Postorder {
             basic_blocks,
             visited: BitSet::new_empty(basic_blocks.len()),
             visit_stack: Vec::new(),
             root_is_start_block: root == START_BLOCK,
+            extra,
         };
 
-        let data = &po.basic_blocks[root];
-
-        if let Some(ref term) = data.terminator {
-            po.visited.insert(root);
-            po.visit_stack.push((root, term.successors()));
-            po.traverse_successor();
-        }
+        po.visit(root);
+        po.traverse_successor();
 
         po
     }
 
+    fn visit(&mut self, bb: BasicBlock) {
+        if !self.visited.insert(bb) {
+            return;
+        }
+        let data = &self.basic_blocks[bb];
+        let successors = C::successors(data, self.extra);
+        self.visit_stack.push((bb, successors));
+    }
+
     fn traverse_successor(&mut self) {
         // This is quite a complex loop due to 1. the borrow checker not liking it much
         // and 2. what exactly is going on is not clear
@@ -183,16 +193,15 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
         // since we've already visited `E`, that child isn't added to the stack. The last
         // two iterations yield `B` and finally `A` for a final traversal of [E, D, C, B, A]
         while let Some(bb) = self.visit_stack.last_mut().and_then(|(_, iter)| iter.next_back()) {
-            if self.visited.insert(bb) {
-                if let Some(term) = &self.basic_blocks[bb].terminator {
-                    self.visit_stack.push((bb, term.successors()));
-                }
-            }
+            self.visit(bb);
         }
     }
 }
 
-impl<'tcx> Iterator for Postorder<'_, 'tcx> {
+impl<'tcx, C> Iterator for Postorder<'_, 'tcx, C>
+where
+    C: Customization<'tcx>,
+{
     type Item = BasicBlock;
 
     fn next(&mut self) -> Option<BasicBlock> {
@@ -232,6 +241,40 @@ pub fn postorder<'a, 'tcx>(
     reverse_postorder(body).rev()
 }
 
+/// Lets us plug in some additional logic and data into a Postorder traversal. Or not.
+pub trait Customization<'tcx>: Copy {
+    fn successors<'a>(_: &'a BasicBlockData<'tcx>, _: Self) -> Successors<'a>;
+}
+
+impl<'tcx> Customization<'tcx> for () {
+    fn successors<'a>(data: &'a BasicBlockData<'tcx>, _: ()) -> Successors<'a> {
+        data.terminator().successors()
+    }
+}
+
+impl<'tcx> Customization<'tcx> for (TyCtxt<'tcx>, Instance<'tcx>) {
+    fn successors<'a>(
+        data: &'a BasicBlockData<'tcx>,
+        (tcx, instance): (TyCtxt<'tcx>, Instance<'tcx>),
+    ) -> Successors<'a> {
+        data.mono_successors(tcx, instance)
+    }
+}
+
+pub fn mono_reachable_reverse_postorder<'a, 'tcx>(
+    body: &'a Body<'tcx>,
+    tcx: TyCtxt<'tcx>,
+    instance: Instance<'tcx>,
+) -> Vec<BasicBlock> {
+    let mut iter = Postorder::new(&body.basic_blocks, START_BLOCK, (tcx, instance));
+    let mut items = Vec::with_capacity(body.basic_blocks.len());
+    while let Some(block) = iter.next() {
+        items.push(block);
+    }
+    items.reverse();
+    items
+}
+
 /// Returns an iterator over all basic blocks reachable from the `START_BLOCK` in no particular
 /// order.
 ///
@@ -358,14 +401,8 @@ impl<'a, 'tcx> Iterator for MonoReachable<'a, 'tcx> {
 
             let data = &self.body[idx];
 
-            if let Some((bits, targets)) =
-                Body::try_const_mono_switchint(self.tcx, self.instance, data)
-            {
-                let target = targets.target_for_value(bits);
-                self.add_work([target]);
-            } else {
-                self.add_work(data.terminator().successors());
-            }
+            let targets = data.mono_successors(self.tcx, self.instance);
+            self.add_work(targets);
 
             return Some((idx, data));
         }
diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs
index 1236c9efb41..5a32078760e 100644
--- a/compiler/rustc_middle/src/ty/adjustment.rs
+++ b/compiler/rustc_middle/src/ty/adjustment.rs
@@ -104,6 +104,9 @@ pub enum Adjust<'tcx> {
 
     /// Cast into a dyn* object.
     DynStar,
+
+    /// Take a pinned reference and reborrow as a `Pin<&mut T>` or `Pin<&T>`.
+    ReborrowPin(ty::Region<'tcx>, hir::Mutability),
 }
 
 /// An overloaded autoderef step, representing a `Deref(Mut)::deref(_mut)`
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 6708ae60562..1a584cf2890 100644
--- a/compiler/rustc_middle/src/ty/consts.rs
+++ b/compiler/rustc_middle/src/ty/consts.rs
@@ -521,6 +521,10 @@ impl<'tcx> Const<'tcx> {
         self.try_to_valtree()?.try_to_scalar()
     }
 
+    pub fn try_to_bool(self) -> Option<bool> {
+        self.try_to_scalar()?.to_bool().ok()
+    }
+
     #[inline]
     pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option<u64> {
         self.try_to_valtree()?.try_to_target_usize(tcx)
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 6d878ab7654..941091b71d3 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -264,7 +264,7 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
         match *self {
             LayoutError::Unknown(ty) => write!(f, "the type `{ty}` has an unknown layout"),
             LayoutError::SizeOverflow(ty) => {
-                write!(f, "values of the type `{ty}` are too big for the current architecture")
+                write!(f, "values of the type `{ty}` are too big for the target architecture")
             }
             LayoutError::NormalizationFailure(t, e) => write!(
                 f,
@@ -627,7 +627,7 @@ pub type TyAndLayout<'tcx> = rustc_target::abi::TyAndLayout<'tcx, Ty<'tcx>>;
 pub trait LayoutOfHelpers<'tcx>: HasDataLayout + HasTyCtxt<'tcx> + HasParamEnv<'tcx> {
     /// The `TyAndLayout`-wrapping type (or `TyAndLayout` itself), which will be
     /// returned from `layout_of` (see also `handle_layout_err`).
-    type LayoutOfResult: MaybeResult<TyAndLayout<'tcx>>;
+    type LayoutOfResult: MaybeResult<TyAndLayout<'tcx>> = TyAndLayout<'tcx>;
 
     /// `Span` to use for `tcx.at(span)`, from `layout_of`.
     // FIXME(eddyb) perhaps make this mandatory to get contexts to track it better?
@@ -1191,6 +1191,7 @@ pub fn fn_can_unwind(tcx: TyCtxt<'_>, fn_def_id: Option<DefId>, abi: SpecAbi) ->
         | RiscvInterruptM
         | RiscvInterruptS
         | CCmseNonSecureCall
+        | CCmseNonSecureEntry
         | Unadjusted => false,
         Rust | RustCall | RustCold | RustIntrinsic => {
             tcx.sess.panic_strategy() == PanicStrategy::Unwind
@@ -1233,7 +1234,7 @@ pub enum FnAbiRequest<'tcx> {
 pub trait FnAbiOfHelpers<'tcx>: LayoutOfHelpers<'tcx> {
     /// The `&FnAbi`-wrapping type (or `&FnAbi` itself), which will be
     /// returned from `fn_abi_of_*` (see also `handle_fn_abi_err`).
-    type FnAbiOfResult: MaybeResult<&'tcx FnAbi<'tcx, Ty<'tcx>>>;
+    type FnAbiOfResult: MaybeResult<&'tcx FnAbi<'tcx, Ty<'tcx>>> = &'tcx FnAbi<'tcx, Ty<'tcx>>;
 
     /// Helper used for `fn_abi_of_*`, to adapt `tcx.fn_abi_of_*(...)` into a
     /// `Self::FnAbiOfResult` (which does not need to be a `Result<...>`).
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index c7fcfe3ce2a..4fe984b961e 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -218,6 +218,13 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
                 warnings: self.warnings,
                 suggest_unsafe_block: self.suggest_unsafe_block,
             };
+            // params in THIR may be unsafe, e.g. a union pattern.
+            for param in &inner_thir.params {
+                if let Some(param_pat) = param.pat.as_deref() {
+                    inner_visitor.visit_pat(param_pat);
+                }
+            }
+            // Visit the body.
             inner_visitor.visit_expr(&inner_thir[expr]);
             // Unsafe blocks can be used in the inner body, make sure to take it into account
             self.safety_context = inner_visitor.safety_context;
@@ -315,14 +322,15 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
                 | PatKind::DerefPattern { .. }
                 | PatKind::Range { .. }
                 | PatKind::Slice { .. }
-                | PatKind::Array { .. } => {
+                | PatKind::Array { .. }
+                // Never constitutes a witness of uninhabitedness.
+                | PatKind::Never => {
                     self.requires_unsafe(pat.span, AccessToUnionField);
                     return; // we can return here since this already requires unsafe
                 }
-                // wildcard/never don't take anything
+                // wildcard doesn't read anything.
                 PatKind::Wild |
-                PatKind::Never |
-                // these just wrap other patterns
+                // these just wrap other patterns, which we recurse on below.
                 PatKind::Or { .. } |
                 PatKind::InlineConstant { .. } |
                 PatKind::AscribeUserType { .. } |
@@ -1032,6 +1040,13 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
         warnings: &mut warnings,
         suggest_unsafe_block: true,
     };
+    // params in THIR may be unsafe, e.g. a union pattern.
+    for param in &thir.params {
+        if let Some(param_pat) = param.pat.as_deref() {
+            visitor.visit_pat(param_pat);
+        }
+    }
+    // Visit the body.
     visitor.visit_expr(&thir[expr]);
 
     warnings.sort_by_key(|w| w.block_span);
diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs
index aa8ccc8b7dd..3f730b5d183 100644
--- a/compiler/rustc_mir_build/src/thir/cx/expr.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs
@@ -74,6 +74,7 @@ impl<'tcx> Cx<'tcx> {
         self.thir.exprs.push(expr)
     }
 
+    #[instrument(level = "trace", skip(self, expr, span))]
     fn apply_adjustment(
         &mut self,
         hir_expr: &'tcx hir::Expr<'tcx>,
@@ -146,6 +147,67 @@ impl<'tcx> Cx<'tcx> {
                 ExprKind::RawBorrow { mutability, arg: self.thir.exprs.push(expr) }
             }
             Adjust::DynStar => ExprKind::Cast { source: self.thir.exprs.push(expr) },
+            Adjust::ReborrowPin(region, mutbl) => {
+                debug!("apply ReborrowPin adjustment");
+                // Rewrite `$expr` as `Pin { __pointer: &(mut)? *($expr).__pointer }`
+
+                // We'll need these types later on
+                let pin_ty_args = match expr.ty.kind() {
+                    ty::Adt(_, args) => args,
+                    _ => bug!("ReborrowPin with non-Pin type"),
+                };
+                let pin_ty = pin_ty_args.iter().next().unwrap().expect_ty();
+                let ptr_target_ty = match pin_ty.kind() {
+                    ty::Ref(_, ty, _) => *ty,
+                    _ => bug!("ReborrowPin with non-Ref type"),
+                };
+
+                // pointer = ($expr).__pointer
+                let pointer_target = ExprKind::Field {
+                    lhs: self.thir.exprs.push(expr),
+                    variant_index: FIRST_VARIANT,
+                    name: FieldIdx::from(0u32),
+                };
+                let arg = Expr { temp_lifetime, ty: pin_ty, span, kind: pointer_target };
+                let arg = self.thir.exprs.push(arg);
+
+                // arg = *pointer
+                let expr = ExprKind::Deref { arg };
+                let arg = self.thir.exprs.push(Expr {
+                    temp_lifetime,
+                    ty: ptr_target_ty,
+                    span,
+                    kind: expr,
+                });
+
+                // expr = &mut target
+                let borrow_kind = match mutbl {
+                    hir::Mutability::Mut => BorrowKind::Mut { kind: mir::MutBorrowKind::Default },
+                    hir::Mutability::Not => BorrowKind::Shared,
+                };
+                let new_pin_target = Ty::new_ref(self.tcx, region, ptr_target_ty, mutbl);
+                let expr = self.thir.exprs.push(Expr {
+                    temp_lifetime,
+                    ty: new_pin_target,
+                    span,
+                    kind: ExprKind::Borrow { borrow_kind, arg },
+                });
+
+                // kind = Pin { __pointer: pointer }
+                let pin_did = self.tcx.require_lang_item(rustc_hir::LangItem::Pin, Some(span));
+                let args = self.tcx.mk_args(&[new_pin_target.into()]);
+                let kind = ExprKind::Adt(Box::new(AdtExpr {
+                    adt_def: self.tcx.adt_def(pin_did),
+                    variant_index: FIRST_VARIANT,
+                    args,
+                    fields: Box::new([FieldExpr { name: FieldIdx::from(0u32), expr }]),
+                    user_ty: None,
+                    base: None,
+                }));
+
+                debug!(?kind);
+                kind
+            }
         };
 
         Expr { temp_lifetime, ty: adjustment.target, span, kind }
@@ -1014,7 +1076,7 @@ impl<'tcx> Cx<'tcx> {
 
         // Reconstruct the output assuming it's a reference with the
         // same region and mutability as the receiver. This holds for
-        // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
+        // `Deref(Mut)::deref(_mut)` and `Index(Mut)::index(_mut)`.
         let ty::Ref(region, _, mutbl) = *self.thir[args[0]].ty.kind() else {
             span_bug!(span, "overloaded_place: receiver is not a reference");
         };
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
index 5acfec3dee3..4d743c05190 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
@@ -157,6 +157,17 @@ where
             },
         );
 
+        // HACK: We bail with overflow if the response would have too many non-region
+        // inference variables. This tends to only happen if we encounter a lot of
+        // ambiguous alias types which get replaced with fresh inference variables
+        // during generalization. This prevents a hang in nalgebra.
+        let num_non_region_vars = canonical.variables.iter().filter(|c| !c.is_region()).count();
+        if num_non_region_vars > self.cx().recursion_limit() {
+            return Ok(self.make_ambiguous_response_no_constraints(MaybeCause::Overflow {
+                suggest_increasing_limit: true,
+            }));
+        }
+
         Ok(canonical)
     }
 
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index ec9a676ea31..6cb851eb8df 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -670,7 +670,7 @@ parse_parentheses_with_struct_fields = invalid `struct` delimiters or `fn` call
 parse_parenthesized_lifetime = parenthesized lifetime bounds are not supported
 parse_parenthesized_lifetime_suggestion = remove the parentheses
 
-parse_path_single_colon = path separator must be a double colon
+parse_path_double_colon = path separator must be a double colon
     .suggestion = use a double colon instead
 
 parse_pattern_method_param_without_body = patterns aren't allowed in methods without bodies
@@ -803,15 +803,17 @@ parse_unexpected_expr_in_pat =
     expected {$is_bound ->
         [true] a pattern range bound
        *[false] a pattern
-    }, found {$is_method_call ->
-        [true] a method call
-       *[false] an expression
-    }
+    }, found an expression
+
+    .label = arbitrary expressions are not allowed in patterns
+
+parse_unexpected_expr_in_pat_const_sugg = consider extracting the expression into a `const`
+
+parse_unexpected_expr_in_pat_create_guard_sugg = consider moving the expression to a match arm guard
+
+parse_unexpected_expr_in_pat_inline_const_sugg = consider wrapping the expression in an inline `const` (requires `{"#"}![feature(inline_const_pat)]`)
 
-    .label = {$is_method_call ->
-        [true] method calls
-       *[false] arbitrary expressions
-    } are not allowed in patterns
+parse_unexpected_expr_in_pat_update_guard_sugg = consider moving the expression to the match arm guard
 
 parse_unexpected_if_with_if = unexpected `if` in the condition expression
     .suggestion = remove the `if`
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index da1103a4fe5..e9fe2e6c1dd 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -1,3 +1,5 @@
+// ignore-tidy-filelength
+
 use std::borrow::Cow;
 
 use rustc_ast::token::Token;
@@ -1569,7 +1571,7 @@ pub(crate) struct ExpectedFnPathFoundFnKeyword {
 }
 
 #[derive(Diagnostic)]
-#[diag(parse_path_single_colon)]
+#[diag(parse_path_double_colon)]
 pub(crate) struct PathSingleColon {
     #[primary_span]
     pub span: Span,
@@ -1582,6 +1584,14 @@ pub(crate) struct PathSingleColon {
 }
 
 #[derive(Diagnostic)]
+#[diag(parse_path_double_colon)]
+pub(crate) struct PathTripleColon {
+    #[primary_span]
+    #[suggestion(applicability = "maybe-incorrect", code = "", style = "verbose")]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(parse_colon_as_semi)]
 pub(crate) struct ColonAsSemi {
     #[primary_span]
@@ -2592,13 +2602,86 @@ pub(crate) struct ExpectedCommaAfterPatternField {
 #[derive(Diagnostic)]
 #[diag(parse_unexpected_expr_in_pat)]
 pub(crate) struct UnexpectedExpressionInPattern {
+    /// The unexpected expr's span.
     #[primary_span]
     #[label]
     pub span: Span,
     /// Was a `RangePatternBound` expected?
     pub is_bound: bool,
-    /// Was the unexpected expression a `MethodCallExpression`?
-    pub is_method_call: bool,
+    /// The unexpected expr's precedence (used in match arm guard suggestions).
+    pub expr_precedence: i8,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum UnexpectedExpressionInPatternSugg {
+    #[multipart_suggestion(
+        parse_unexpected_expr_in_pat_create_guard_sugg,
+        applicability = "maybe-incorrect"
+    )]
+    CreateGuard {
+        /// Where to put the suggested identifier.
+        #[suggestion_part(code = "{ident}")]
+        ident_span: Span,
+        /// Where to put the match arm.
+        #[suggestion_part(code = " if {ident} == {expr}")]
+        pat_hi: Span,
+        /// The suggested identifier.
+        ident: String,
+        /// The unexpected expression.
+        expr: String,
+    },
+
+    #[multipart_suggestion(
+        parse_unexpected_expr_in_pat_update_guard_sugg,
+        applicability = "maybe-incorrect"
+    )]
+    UpdateGuard {
+        /// Where to put the suggested identifier.
+        #[suggestion_part(code = "{ident}")]
+        ident_span: Span,
+        /// The beginning of the match arm guard's expression (insert a `(` if `Some`).
+        #[suggestion_part(code = "(")]
+        guard_lo: Option<Span>,
+        /// The end of the match arm guard's expression.
+        #[suggestion_part(code = "{guard_hi_paren} && {ident} == {expr}")]
+        guard_hi: Span,
+        /// Either `")"` or `""`.
+        guard_hi_paren: &'static str,
+        /// The suggested identifier.
+        ident: String,
+        /// The unexpected expression.
+        expr: String,
+    },
+
+    #[multipart_suggestion(
+        parse_unexpected_expr_in_pat_const_sugg,
+        applicability = "has-placeholders"
+    )]
+    Const {
+        /// Where to put the extracted constant declaration.
+        #[suggestion_part(code = "{indentation}const {ident}: /* Type */ = {expr};\n")]
+        stmt_lo: Span,
+        /// Where to put the suggested identifier.
+        #[suggestion_part(code = "{ident}")]
+        ident_span: Span,
+        /// The suggested identifier.
+        ident: String,
+        /// The unexpected expression.
+        expr: String,
+        /// The statement's block's indentation.
+        indentation: String,
+    },
+
+    #[multipart_suggestion(
+        parse_unexpected_expr_in_pat_inline_const_sugg,
+        applicability = "maybe-incorrect"
+    )]
+    InlineConst {
+        #[suggestion_part(code = "const {{ ")]
+        start_span: Span,
+        #[suggestion_part(code = " }}")]
+        end_span: Span,
+    },
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 2d5a1914fa6..f19cba4c1bf 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -41,7 +41,7 @@ use super::{
 use crate::{errors, maybe_recover_from_interpolated_ty_qpath};
 
 #[derive(Debug)]
-enum DestructuredFloat {
+pub(super) enum DestructuredFloat {
     /// 1e2
     Single(Symbol, Span),
     /// 1.
@@ -1041,7 +1041,7 @@ impl<'a> Parser<'a> {
     //  support pushing "future tokens" (would be also helpful to `break_and_eat`), or
     //  we should break everything including floats into more basic proc-macro style
     //  tokens in the lexer (probably preferable).
-    fn break_up_float(&self, float: Symbol, span: Span) -> DestructuredFloat {
+    pub(super) fn break_up_float(&self, float: Symbol, span: Span) -> DestructuredFloat {
         #[derive(Debug)]
         enum FloatComponent {
             IdentLike(String),
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 104678e081c..afd9871a635 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -707,7 +707,7 @@ impl<'a> Parser<'a> {
             })
         };
 
-        let (ident, item_kind) = if self.eat(&token::PathSep) {
+        let (ident, item_kind) = if self.eat_path_sep() {
             let suffixes = if self.eat(&token::BinOp(token::Star)) {
                 None
             } else {
@@ -1054,7 +1054,7 @@ impl<'a> Parser<'a> {
         {
             // `use *;` or `use ::*;` or `use {...};` or `use ::{...};`
             let mod_sep_ctxt = self.token.span.ctxt();
-            if self.eat(&token::PathSep) {
+            if self.eat_path_sep() {
                 prefix
                     .segments
                     .push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
@@ -1065,7 +1065,7 @@ impl<'a> Parser<'a> {
             // `use path::*;` or `use path::{...};` or `use path;` or `use path as bar;`
             prefix = self.parse_path(PathStyle::Mod)?;
 
-            if self.eat(&token::PathSep) {
+            if self.eat_path_sep() {
                 self.parse_use_tree_glob_or_nested()?
             } else {
                 // Recover from using a colon as path separator.
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 9d9265d5318..3b58b2337f3 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1562,12 +1562,25 @@ impl<'a> Parser<'a> {
         })
     }
 
+    /// Checks for `::` or, potentially, `:::` and then look ahead after it.
+    fn check_path_sep_and_look_ahead(&mut self, looker: impl Fn(&Token) -> bool) -> bool {
+        if self.check(&token::PathSep) {
+            if self.may_recover() && self.look_ahead(1, |t| t.kind == token::Colon) {
+                debug_assert!(!self.look_ahead(1, &looker), "Looker must not match on colon");
+                self.look_ahead(2, looker)
+            } else {
+                self.look_ahead(1, looker)
+            }
+        } else {
+            false
+        }
+    }
+
     /// `::{` or `::*`
     fn is_import_coupler(&mut self) -> bool {
-        self.check(&token::PathSep)
-            && self.look_ahead(1, |t| {
-                *t == token::OpenDelim(Delimiter::Brace) || *t == token::BinOp(token::Star)
-            })
+        self.check_path_sep_and_look_ahead(|t| {
+            matches!(t.kind, token::OpenDelim(Delimiter::Brace) | token::BinOp(token::Star))
+        })
     }
 
     // Debug view of the parser's token stream, up to `{lookahead}` tokens.
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index daced411b8f..647df25c82e 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -1,12 +1,14 @@
-use rustc_ast::mut_visit::{walk_pat, MutVisitor};
+use rustc_ast::mut_visit::{self, MutVisitor};
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, BinOpToken, Delimiter, IdentIsRaw, Token};
+use rustc_ast::visit::{self, Visitor};
 use rustc_ast::{
-    self as ast, AttrVec, BindingMode, ByRef, Expr, ExprKind, MacCall, Mutability, Pat, PatField,
-    PatFieldsRest, PatKind, Path, QSelf, RangeEnd, RangeSyntax,
+    self as ast, Arm, AttrVec, BinOpKind, BindingMode, ByRef, Expr, ExprKind, ExprPrecedence,
+    LocalKind, MacCall, Mutability, Pat, PatField, PatFieldsRest, PatKind, Path, QSelf, RangeEnd,
+    RangeSyntax, Stmt, StmtKind,
 };
 use rustc_ast_pretty::pprust;
-use rustc_errors::{Applicability, Diag, PResult};
+use rustc_errors::{Applicability, Diag, DiagArgValue, PResult, StashKey};
 use rustc_session::errors::ExprParenthesesNeeded;
 use rustc_span::source_map::{respan, Spanned};
 use rustc_span::symbol::{kw, sym, Ident};
@@ -21,11 +23,11 @@ use crate::errors::{
     InclusiveRangeExtraEquals, InclusiveRangeMatchArrow, InclusiveRangeNoEnd, InvalidMutInPattern,
     ParenRangeSuggestion, PatternOnWrongSideOfAt, RemoveLet, RepeatedMutInPattern,
     SwitchRefBoxOrder, TopLevelOrPatternNotAllowed, TopLevelOrPatternNotAllowedSugg,
-    TrailingVertNotAllowed, UnexpectedExpressionInPattern, UnexpectedLifetimeInPattern,
-    UnexpectedParenInRangePat, UnexpectedParenInRangePatSugg,
+    TrailingVertNotAllowed, UnexpectedExpressionInPattern, UnexpectedExpressionInPatternSugg,
+    UnexpectedLifetimeInPattern, UnexpectedParenInRangePat, UnexpectedParenInRangePatSugg,
     UnexpectedVertVertBeforeFunctionParam, UnexpectedVertVertInPattern, WrapInParens,
 };
-use crate::parser::expr::could_be_unclosed_char_literal;
+use crate::parser::expr::{could_be_unclosed_char_literal, DestructuredFloat};
 use crate::{maybe_recover_from_interpolated_ty_qpath, maybe_whole};
 
 #[derive(PartialEq, Copy, Clone)]
@@ -342,7 +344,7 @@ impl<'a> Parser<'a> {
         }
     }
 
-    /// Ensures that the last parsed pattern (or pattern range bound) is not followed by a method call or an operator.
+    /// Ensures that the last parsed pattern (or pattern range bound) is not followed by an expression.
     ///
     /// `is_end_bound` indicates whether the last parsed thing was the end bound of a range pattern (see [`parse_pat_range_end`](Self::parse_pat_range_end))
     /// in order to say "expected a pattern range bound" instead of "expected a pattern";
@@ -350,38 +352,64 @@ impl<'a> Parser<'a> {
     /// 0..=1 + 2
     ///     ^^^^^
     /// ```
-    /// Only the end bound is spanned, and this function have no idea if there were a `..=` before `pat_span`, hence the parameter.
+    /// Only the end bound is spanned in this case, and this function has no idea if there was a `..=` before `pat_span`, hence the parameter.
+    ///
+    /// This function returns `Some` if a trailing expression was recovered, and said expression's span.
     #[must_use = "the pattern must be discarded as `PatKind::Err` if this function returns Some"]
     fn maybe_recover_trailing_expr(
         &mut self,
         pat_span: Span,
         is_end_bound: bool,
-    ) -> Option<ErrorGuaranteed> {
+    ) -> Option<(ErrorGuaranteed, Span)> {
         if self.prev_token.is_keyword(kw::Underscore) || !self.may_recover() {
             // Don't recover anything after an `_` or if recovery is disabled.
             return None;
         }
 
-        // Check for `.hello()`, but allow `.Hello()` to be recovered as `, Hello()` in `parse_seq_to_before_tokens()`.
-        let has_trailing_method = self.check_noexpect(&token::Dot)
+        // Returns `true` iff `token` is an unsuffixed integer.
+        let is_one_tuple_index = |_: &Self, token: &Token| -> bool {
+            use token::{Lit, LitKind};
+
+            matches!(
+                token.kind,
+                token::Literal(Lit { kind: LitKind::Integer, symbol: _, suffix: None })
+            )
+        };
+
+        // Returns `true` iff `token` is an unsuffixed `x.y` float.
+        let is_two_tuple_indexes = |this: &Self, token: &Token| -> bool {
+            use token::{Lit, LitKind};
+
+            if let token::Literal(Lit { kind: LitKind::Float, symbol, suffix: None }) = token.kind
+                && let DestructuredFloat::MiddleDot(..) = this.break_up_float(symbol, token.span)
+            {
+                true
+            } else {
+                false
+            }
+        };
+
+        // Check for `.hello` or `.0`.
+        let has_dot_expr = self.check_noexpect(&token::Dot) // `.`
             && self.look_ahead(1, |tok| {
-                tok.ident()
-                    .and_then(|(ident, _)| ident.name.as_str().chars().next())
-                    .is_some_and(char::is_lowercase)
-            })
-            && self.look_ahead(2, |t| *t == token::OpenDelim(Delimiter::Parenthesis));
+                tok.is_ident() // `hello`
+                || is_one_tuple_index(&self, &tok) // `0`
+                || is_two_tuple_indexes(&self, &tok) // `0.0`
+            });
 
         // Check for operators.
         // `|` is excluded as it is used in pattern alternatives and lambdas,
         // `?` is included for error propagation,
         // `[` is included for indexing operations,
-        // `[]` is excluded as `a[]` isn't an expression and should be recovered as `a, []` (cf. `tests/ui/parser/pat-lt-bracket-7.rs`)
+        // `[]` is excluded as `a[]` isn't an expression and should be recovered as `a, []` (cf. `tests/ui/parser/pat-lt-bracket-7.rs`),
+        // `as` is included for type casts
         let has_trailing_operator = matches!(self.token.kind, token::BinOp(op) if op != BinOpToken::Or)
             || self.token == token::Question
             || (self.token == token::OpenDelim(Delimiter::Bracket)
-                && self.look_ahead(1, |t| *t != token::CloseDelim(Delimiter::Bracket)));
+                && self.look_ahead(1, |t| *t != token::CloseDelim(Delimiter::Bracket))) // excludes `[]`
+            || self.token.is_keyword(kw::As);
 
-        if !has_trailing_method && !has_trailing_operator {
+        if !has_dot_expr && !has_trailing_operator {
             // Nothing to recover here.
             return None;
         }
@@ -391,44 +419,248 @@ impl<'a> Parser<'a> {
         snapshot.restrictions.insert(Restrictions::IS_PAT);
 
         // Parse `?`, `.f`, `(arg0, arg1, ...)` or `[expr]` until they've all been eaten.
-        if let Ok(expr) = snapshot
+        let Ok(expr) = snapshot
             .parse_expr_dot_or_call_with(
                 AttrVec::new(),
                 self.mk_expr(pat_span, ExprKind::Dummy), // equivalent to transforming the parsed pattern into an `Expr`
                 pat_span,
             )
             .map_err(|err| err.cancel())
-        {
-            let non_assoc_span = expr.span;
+        else {
+            // We got a trailing method/operator, but that wasn't an expression.
+            return None;
+        };
 
-            // Parse an associative expression such as `+ expr`, `% expr`, ...
-            // Assignments, ranges and `|` are disabled by [`Restrictions::IS_PAT`].
-            if let Ok((expr, _)) =
-                snapshot.parse_expr_assoc_rest_with(0, false, expr).map_err(|err| err.cancel())
-            {
-                // We got a valid expression.
-                self.restore_snapshot(snapshot);
-                self.restrictions.remove(Restrictions::IS_PAT);
+        // Parse an associative expression such as `+ expr`, `% expr`, ...
+        // Assignments, ranges and `|` are disabled by [`Restrictions::IS_PAT`].
+        let Ok((expr, _)) =
+            snapshot.parse_expr_assoc_rest_with(0, false, expr).map_err(|err| err.cancel())
+        else {
+            // We got a trailing method/operator, but that wasn't an expression.
+            return None;
+        };
 
-                let is_bound = is_end_bound
-                    // is_start_bound: either `..` or `)..`
-                    || self.token.is_range_separator()
-                    || self.token == token::CloseDelim(Delimiter::Parenthesis)
-                        && self.look_ahead(1, Token::is_range_separator);
+        // We got a valid expression.
+        self.restore_snapshot(snapshot);
+        self.restrictions.remove(Restrictions::IS_PAT);
 
-                // Check that `parse_expr_assoc_with` didn't eat a rhs.
-                let is_method_call = has_trailing_method && non_assoc_span == expr.span;
+        let is_bound = is_end_bound
+            // is_start_bound: either `..` or `)..`
+            || self.token.is_range_separator()
+            || self.token == token::CloseDelim(Delimiter::Parenthesis)
+                && self.look_ahead(1, Token::is_range_separator);
 
-                return Some(self.dcx().emit_err(UnexpectedExpressionInPattern {
-                    span: expr.span,
+        let span = expr.span;
+
+        Some((
+            self.dcx()
+                .create_err(UnexpectedExpressionInPattern {
+                    span,
                     is_bound,
-                    is_method_call,
-                }));
+                    expr_precedence: expr.precedence().order(),
+                })
+                .stash(span, StashKey::ExprInPat)
+                .unwrap(),
+            span,
+        ))
+    }
+
+    /// Called by [`Parser::parse_stmt_without_recovery`], used to add statement-aware subdiagnostics to the errors stashed
+    /// by [`Parser::maybe_recover_trailing_expr`].
+    pub(super) fn maybe_augment_stashed_expr_in_pats_with_suggestions(&mut self, stmt: &Stmt) {
+        if self.dcx().has_errors().is_none() {
+            // No need to walk the statement if there's no stashed errors.
+            return;
+        }
+
+        struct PatVisitor<'a> {
+            /// `self`
+            parser: &'a Parser<'a>,
+            /// The freshly-parsed statement.
+            stmt: &'a Stmt,
+            /// The current match arm (for arm guard suggestions).
+            arm: Option<&'a Arm>,
+            /// The current struct field (for variable name suggestions).
+            field: Option<&'a PatField>,
+        }
+
+        impl<'a> PatVisitor<'a> {
+            /// Looks for stashed [`StashKey::ExprInPat`] errors in `stash_span`, and emit them with suggestions.
+            /// `stash_span` is contained in `expr_span`, the latter being larger in borrow patterns;
+            /// ```txt
+            /// &mut x.y
+            /// -----^^^ `stash_span`
+            /// |
+            /// `expr_span`
+            /// ```
+            /// `is_range_bound` is used to exclude arm guard suggestions in range pattern bounds.
+            fn maybe_add_suggestions_then_emit(
+                &self,
+                stash_span: Span,
+                expr_span: Span,
+                is_range_bound: bool,
+            ) {
+                self.parser.dcx().try_steal_modify_and_emit_err(
+                    stash_span,
+                    StashKey::ExprInPat,
+                    |err| {
+                        // Includes pre-pats (e.g. `&mut <err>`) in the diagnostic.
+                        err.span.replace(stash_span, expr_span);
+
+                        let sm = self.parser.psess.source_map();
+                        let stmt = self.stmt;
+                        let line_lo = sm.span_extend_to_line(stmt.span).shrink_to_lo();
+                        let indentation = sm.indentation_before(stmt.span).unwrap_or_default();
+                        let Ok(expr) = self.parser.span_to_snippet(expr_span) else {
+                            // FIXME: some suggestions don't actually need the snippet; see PR #123877's unresolved conversations.
+                            return;
+                        };
+
+                        if let StmtKind::Let(local) = &stmt.kind {
+                            match &local.kind {
+                                LocalKind::Decl | LocalKind::Init(_) => {
+                                    // It's kinda hard to guess what the user intended, so don't make suggestions.
+                                    return;
+                                }
+
+                                LocalKind::InitElse(_, _) => {}
+                            }
+                        }
+
+                        // help: use an arm guard `if val == expr`
+                        // FIXME(guard_patterns): suggest this regardless of a match arm.
+                        if let Some(arm) = &self.arm
+                            && !is_range_bound
+                        {
+                            let (ident, ident_span) = match self.field {
+                                Some(field) => {
+                                    (field.ident.to_string(), field.ident.span.to(expr_span))
+                                }
+                                None => ("val".to_owned(), expr_span),
+                            };
+
+                            // Are parentheses required around `expr`?
+                            // HACK: a neater way would be preferable.
+                            let expr = match &err.args["expr_precedence"] {
+                                DiagArgValue::Number(expr_precedence) => {
+                                    if *expr_precedence
+                                        <= ExprPrecedence::Binary(BinOpKind::Eq).order() as i32
+                                    {
+                                        format!("({expr})")
+                                    } else {
+                                        format!("{expr}")
+                                    }
+                                }
+                                _ => unreachable!(),
+                            };
+
+                            match &arm.guard {
+                                None => {
+                                    err.subdiagnostic(
+                                        UnexpectedExpressionInPatternSugg::CreateGuard {
+                                            ident_span,
+                                            pat_hi: arm.pat.span.shrink_to_hi(),
+                                            ident,
+                                            expr,
+                                        },
+                                    );
+                                }
+                                Some(guard) => {
+                                    // Are parentheses required around the old guard?
+                                    let wrap_guard = guard.precedence().order()
+                                        <= ExprPrecedence::Binary(BinOpKind::And).order();
+
+                                    err.subdiagnostic(
+                                        UnexpectedExpressionInPatternSugg::UpdateGuard {
+                                            ident_span,
+                                            guard_lo: if wrap_guard {
+                                                Some(guard.span.shrink_to_lo())
+                                            } else {
+                                                None
+                                            },
+                                            guard_hi: guard.span.shrink_to_hi(),
+                                            guard_hi_paren: if wrap_guard { ")" } else { "" },
+                                            ident,
+                                            expr,
+                                        },
+                                    );
+                                }
+                            }
+                        }
+
+                        // help: extract the expr into a `const VAL: _ = expr`
+                        let ident = match self.field {
+                            Some(field) => field.ident.as_str().to_uppercase(),
+                            None => "VAL".to_owned(),
+                        };
+                        err.subdiagnostic(UnexpectedExpressionInPatternSugg::Const {
+                            stmt_lo: line_lo,
+                            ident_span: expr_span,
+                            expr,
+                            ident,
+                            indentation,
+                        });
+
+                        // help: wrap the expr in a `const { expr }`
+                        // FIXME(inline_const_pat): once stabilized, remove this check and remove the `(requires #[feature(inline_const_pat)])` note from the message
+                        if self.parser.psess.unstable_features.is_nightly_build() {
+                            err.subdiagnostic(UnexpectedExpressionInPatternSugg::InlineConst {
+                                start_span: expr_span.shrink_to_lo(),
+                                end_span: expr_span.shrink_to_hi(),
+                            });
+                        }
+                    },
+                );
             }
         }
 
-        // We got a trailing method/operator, but we couldn't parse an expression.
-        None
+        impl<'a> Visitor<'a> for PatVisitor<'a> {
+            fn visit_arm(&mut self, a: &'a Arm) -> Self::Result {
+                self.arm = Some(a);
+                visit::walk_arm(self, a);
+                self.arm = None;
+            }
+
+            fn visit_pat_field(&mut self, fp: &'a PatField) -> Self::Result {
+                self.field = Some(fp);
+                visit::walk_pat_field(self, fp);
+                self.field = None;
+            }
+
+            fn visit_pat(&mut self, p: &'a Pat) -> Self::Result {
+                match &p.kind {
+                    // Base expression
+                    PatKind::Err(_) | PatKind::Lit(_) => {
+                        self.maybe_add_suggestions_then_emit(p.span, p.span, false)
+                    }
+
+                    // Sub-patterns
+                    // FIXME: this doesn't work with recursive subpats (`&mut &mut <err>`)
+                    PatKind::Box(subpat) | PatKind::Ref(subpat, _)
+                        if matches!(subpat.kind, PatKind::Err(_) | PatKind::Lit(_)) =>
+                    {
+                        self.maybe_add_suggestions_then_emit(subpat.span, p.span, false)
+                    }
+
+                    // Sub-expressions
+                    PatKind::Range(start, end, _) => {
+                        if let Some(start) = start {
+                            self.maybe_add_suggestions_then_emit(start.span, start.span, true);
+                        }
+
+                        if let Some(end) = end {
+                            self.maybe_add_suggestions_then_emit(end.span, end.span, true);
+                        }
+                    }
+
+                    // Walk continuation
+                    _ => visit::walk_pat(self, p),
+                }
+            }
+        }
+
+        // Starts the visit.
+        PatVisitor { parser: self, stmt, arm: None, field: None }.visit_stmt(stmt);
     }
 
     /// Parses a pattern, with a setting whether modern range patterns (e.g., `a..=b`, `a..b` are
@@ -544,7 +776,7 @@ impl<'a> Parser<'a> {
                 self.parse_pat_tuple_struct(qself, path)?
             } else {
                 match self.maybe_recover_trailing_expr(span, false) {
-                    Some(guar) => PatKind::Err(guar),
+                    Some((guar, _)) => PatKind::Err(guar),
                     None => PatKind::Path(qself, path),
                 }
             }
@@ -577,10 +809,10 @@ impl<'a> Parser<'a> {
             // Try to parse everything else as literal with optional minus
             match self.parse_literal_maybe_minus() {
                 Ok(begin) => {
-                    let begin = match self.maybe_recover_trailing_expr(begin.span, false) {
-                        Some(guar) => self.mk_expr_err(begin.span, guar),
-                        None => begin,
-                    };
+                    let begin = self
+                        .maybe_recover_trailing_expr(begin.span, false)
+                        .map(|(guar, sp)| self.mk_expr_err(sp, guar))
+                        .unwrap_or(begin);
 
                     match self.parse_range_end() {
                         Some(form) => self.parse_pat_range_begin_with(begin, form)?,
@@ -721,7 +953,8 @@ impl<'a> Parser<'a> {
         // For backward compatibility, `(..)` is a tuple pattern as well.
         let paren_pattern =
             fields.len() == 1 && !(matches!(trailing_comma, Trailing::Yes) || fields[0].is_rest());
-        if paren_pattern {
+
+        let pat = if paren_pattern {
             let pat = fields.into_iter().next().unwrap();
             let close_paren = self.prev_token.span;
 
@@ -739,7 +972,7 @@ impl<'a> Parser<'a> {
                         },
                     });
 
-                    self.parse_pat_range_begin_with(begin.clone(), form)
+                    self.parse_pat_range_begin_with(begin.clone(), form)?
                 }
                 // recover ranges with parentheses around the `(start)..`
                 PatKind::Err(guar)
@@ -754,15 +987,20 @@ impl<'a> Parser<'a> {
                         },
                     });
 
-                    self.parse_pat_range_begin_with(self.mk_expr_err(pat.span, *guar), form)
+                    self.parse_pat_range_begin_with(self.mk_expr_err(pat.span, *guar), form)?
                 }
 
                 // (pat) with optional parentheses
-                _ => Ok(PatKind::Paren(pat)),
+                _ => PatKind::Paren(pat),
             }
         } else {
-            Ok(PatKind::Tuple(fields))
-        }
+            PatKind::Tuple(fields)
+        };
+
+        Ok(match self.maybe_recover_trailing_expr(open_paren.to(self.prev_token.span), false) {
+            None => pat,
+            Some((guar, _)) => PatKind::Err(guar),
+        })
     }
 
     /// Parse a mutable binding with the `mut` token already eaten.
@@ -816,7 +1054,7 @@ impl<'a> Parser<'a> {
                     self.0 = true;
                     *m = Mutability::Mut;
                 }
-                walk_pat(self, pat);
+                mut_visit::walk_pat(self, pat);
             }
         }
 
@@ -1015,7 +1253,7 @@ impl<'a> Parser<'a> {
         }
 
         Ok(match recovered {
-            Some(guar) => self.mk_expr_err(bound.span, guar),
+            Some((guar, sp)) => self.mk_expr_err(sp, guar),
             None => bound,
         })
     }
@@ -1084,7 +1322,7 @@ impl<'a> Parser<'a> {
         // but not `ident @ subpat` as `subpat` was already checked and `ident` continues with `@`.
 
         let pat = if sub.is_none()
-            && let Some(guar) = self.maybe_recover_trailing_expr(ident.span, false)
+            && let Some((guar, _)) = self.maybe_recover_trailing_expr(ident.span, false)
         {
             PatKind::Err(guar)
         } else {
diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs
index 42039c621d6..961679b1f56 100644
--- a/compiler/rustc_parse/src/parser/path.rs
+++ b/compiler/rustc_parse/src/parser/path.rs
@@ -16,7 +16,7 @@ use tracing::debug;
 
 use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
 use super::{Parser, Restrictions, TokenType};
-use crate::errors::PathSingleColon;
+use crate::errors::{PathSingleColon, PathTripleColon};
 use crate::parser::{CommaRecoveryMode, RecoverColon, RecoverComma};
 use crate::{errors, maybe_whole};
 
@@ -210,7 +210,7 @@ impl<'a> Parser<'a> {
         let lo = self.token.span;
         let mut segments = ThinVec::new();
         let mod_sep_ctxt = self.token.span.ctxt();
-        if self.eat(&token::PathSep) {
+        if self.eat_path_sep() {
             segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
         }
         self.parse_path_segments(&mut segments, style, ty_generics)?;
@@ -246,7 +246,7 @@ impl<'a> Parser<'a> {
             }
             segments.push(segment);
 
-            if self.is_import_coupler() || !self.eat(&token::PathSep) {
+            if self.is_import_coupler() || !self.eat_path_sep() {
                 if style == PathStyle::Expr
                     && self.may_recover()
                     && self.token == token::Colon
@@ -272,6 +272,18 @@ impl<'a> Parser<'a> {
         }
     }
 
+    /// Eat `::` or, potentially, `:::`.
+    #[must_use]
+    pub(super) fn eat_path_sep(&mut self) -> bool {
+        let result = self.eat(&token::PathSep);
+        if result && self.may_recover() {
+            if self.eat_noexpect(&token::Colon) {
+                self.dcx().emit_err(PathTripleColon { span: self.prev_token.span });
+            }
+        }
+        result
+    }
+
     pub(super) fn parse_path_segment(
         &mut self,
         style: PathStyle,
@@ -297,9 +309,7 @@ impl<'a> Parser<'a> {
 
         Ok(
             if style == PathStyle::Type && check_args_start(self)
-                || style != PathStyle::Mod
-                    && self.check(&token::PathSep)
-                    && self.look_ahead(1, |t| is_args_start(t))
+                || style != PathStyle::Mod && self.check_path_sep_and_look_ahead(is_args_start)
             {
                 // We use `style == PathStyle::Expr` to check if this is in a recursion or not. If
                 // it isn't, then we reset the unmatched angle bracket count as we're about to start
@@ -310,7 +320,8 @@ impl<'a> Parser<'a> {
 
                 // Generic arguments are found - `<`, `(`, `::<` or `::(`.
                 // First, eat `::` if it exists.
-                let _ = self.eat(&token::PathSep);
+                let _ = self.eat_path_sep();
+
                 let lo = self.token.span;
                 let args = if self.eat_lt() {
                     // `<'a, T, A = U>`
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index 26ad39e06cd..92fba89d28a 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -29,6 +29,9 @@ use crate::{errors, maybe_whole};
 impl<'a> Parser<'a> {
     /// Parses a statement. This stops just before trailing semicolons on everything but items.
     /// e.g., a `StmtKind::Semi` parses to a `StmtKind::Expr`, leaving the trailing `;` unconsumed.
+    ///
+    /// If `force_collect` is [`ForceCollect::Yes`], forces collection of tokens regardless of
+    /// whether or not we have attributes.
     // Public for rustfmt usage.
     pub(super) fn parse_stmt(&mut self, force_collect: ForceCollect) -> PResult<'a, Option<Stmt>> {
         Ok(self.parse_stmt_without_recovery(false, force_collect).unwrap_or_else(|e| {
@@ -66,7 +69,7 @@ impl<'a> Parser<'a> {
             });
         }
 
-        Ok(Some(if self.token.is_keyword(kw::Let) {
+        let stmt = if self.token.is_keyword(kw::Let) {
             self.collect_tokens(None, attrs, force_collect, |this, attrs| {
                 this.expect_keyword(kw::Let)?;
                 let local = this.parse_local(attrs)?;
@@ -163,7 +166,10 @@ impl<'a> Parser<'a> {
         } else {
             self.error_outer_attrs(attrs);
             return Ok(None);
-        }))
+        };
+
+        self.maybe_augment_stashed_expr_in_pats_with_suggestions(&stmt);
+        Ok(Some(stmt))
     }
 
     fn parse_stmt_path_start(&mut self, lo: Span, attrs: AttrWrapper) -> PResult<'a, Stmt> {
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index ee892c17376..841f255dc3a 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -188,9 +188,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                 | [sym::rustc_must_implement_one_of, ..]
                 | [sym::rustc_deny_explicit_impl, ..]
                 | [sym::const_trait, ..] => self.check_must_be_applied_to_trait(attr, span, target),
-                [sym::cmse_nonsecure_entry, ..] => {
-                    self.check_cmse_nonsecure_entry(hir_id, attr, span, target)
-                }
                 [sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target),
                 [sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target),
                 [sym::must_use, ..] => self.check_must_use(hir_id, attr, target),
@@ -563,27 +560,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         }
     }
 
-    /// Checks if `#[cmse_nonsecure_entry]` is applied to a function definition.
-    fn check_cmse_nonsecure_entry(
-        &self,
-        hir_id: HirId,
-        attr: &Attribute,
-        span: Span,
-        target: Target,
-    ) {
-        match target {
-            Target::Fn
-            | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => {}
-            _ => {
-                self.dcx().emit_err(errors::AttrShouldBeAppliedToFn {
-                    attr_span: attr.span,
-                    defn_span: span,
-                    on_crate: hir_id == CRATE_HIR_ID,
-                });
-            }
-        }
-    }
-
     /// Debugging aid for `object_lifetime_default` query.
     fn check_object_lifetime_default(&self, hir_id: HirId) {
         let tcx = self.tcx;
@@ -1779,6 +1755,15 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             match hint.name_or_empty() {
                 sym::Rust => {
                     is_explicit_rust = true;
+                    match target {
+                        Target::Struct | Target::Union | Target::Enum => continue,
+                        _ => {
+                            self.dcx().emit_err(errors::AttrApplication::StructEnumUnion {
+                                hint_span: hint.span(),
+                                span,
+                            });
+                        }
+                    }
                 }
                 sym::C => {
                     is_c = true;
diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs
index 312cc3a26ef..4fe11589907 100644
--- a/compiler/rustc_passes/src/layout_test.rs
+++ b/compiler/rustc_passes/src/layout_test.rs
@@ -2,7 +2,7 @@ use rustc_ast::Attribute;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
 use rustc_middle::span_bug;
-use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers, TyAndLayout};
+use rustc_middle::ty::layout::{HasParamEnv, HasTyCtxt, LayoutError, LayoutOfHelpers};
 use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt};
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::sym;
@@ -139,8 +139,6 @@ struct UnwrapLayoutCx<'tcx> {
 }
 
 impl<'tcx> LayoutOfHelpers<'tcx> for UnwrapLayoutCx<'tcx> {
-    type LayoutOfResult = TyAndLayout<'tcx>;
-
     fn handle_layout_err(&self, err: LayoutError<'tcx>, span: Span, ty: Ty<'tcx>) -> ! {
         span_bug!(span, "`#[rustc_layout(..)]` test resulted in `layout_of({ty}) = Err({err})`",);
     }
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index 6458c888431..fc9d8f998dc 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -138,6 +138,61 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> {
         );
         assert!(old_parent.is_none(), "parent `LocalDefId` is reset for an invocation");
     }
+
+    /// Determines whether the const argument `AnonConst` is a simple macro call, optionally
+    /// surrounded with braces.
+    ///
+    /// If this const argument *is* a trivial macro call then the id for the macro call is
+    /// returned along with the information required to build the anon const's def if
+    /// the macro call expands to a non-trivial expression.
+    fn is_const_arg_trivial_macro_expansion(
+        &self,
+        anon_const: &'a AnonConst,
+    ) -> Option<(PendingAnonConstInfo, NodeId)> {
+        let (block_was_stripped, expr) = anon_const.value.maybe_unwrap_block();
+        match expr {
+            Expr { kind: ExprKind::MacCall(..), id, .. } => Some((
+                PendingAnonConstInfo {
+                    id: anon_const.id,
+                    span: anon_const.value.span,
+                    block_was_stripped,
+                },
+                *id,
+            )),
+            _ => None,
+        }
+    }
+
+    /// Determines whether the expression `const_arg_sub_expr` is a simple macro call, sometimes
+    /// surrounded with braces if a set of braces has not already been entered. This is required
+    /// as `{ N }` is treated as equivalent to a bare parameter `N` whereas `{{ N }}` is treated as
+    /// a real block expression and is lowered to an anonymous constant which is not allowed to use
+    /// generic parameters.
+    ///
+    /// If this expression is a trivial macro call then the id for the macro call is
+    /// returned along with the information required to build the anon const's def if
+    /// the macro call expands to a non-trivial expression.
+    fn is_const_arg_sub_expr_trivial_macro_expansion(
+        &self,
+        const_arg_sub_expr: &'a Expr,
+    ) -> Option<(PendingAnonConstInfo, NodeId)> {
+        let pending_anon = self.pending_anon_const_info.unwrap_or_else(||
+            panic!("Checking expr is trivial macro call without having entered anon const: `{const_arg_sub_expr:?}`"),
+        );
+
+        let (block_was_stripped, expr) = if pending_anon.block_was_stripped {
+            (true, const_arg_sub_expr)
+        } else {
+            const_arg_sub_expr.maybe_unwrap_block()
+        };
+
+        match expr {
+            Expr { kind: ExprKind::MacCall(..), id, .. } => {
+                Some((PendingAnonConstInfo { block_was_stripped, ..pending_anon }, *id))
+            }
+            _ => None,
+        }
+    }
 }
 
 impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
@@ -354,12 +409,12 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
         // items will be messed up, but that's ok because there can't be any if we're just looking
         // for bare idents.
 
-        if matches!(constant.value.maybe_unwrap_block().kind, ExprKind::MacCall(..)) {
-            // See self.pending_anon_const_info for explanation
-            self.pending_anon_const_info =
-                Some(PendingAnonConstInfo { id: constant.id, span: constant.value.span });
-            return visit::walk_anon_const(self, constant);
-        } else if constant.value.is_potential_trivial_const_arg() {
+        if let Some((pending_anon, macro_invoc)) =
+            self.is_const_arg_trivial_macro_expansion(constant)
+        {
+            self.pending_anon_const_info = Some(pending_anon);
+            return self.visit_macro_invoc(macro_invoc);
+        } else if constant.value.is_potential_trivial_const_arg(true) {
             return visit::walk_anon_const(self, constant);
         }
 
@@ -368,23 +423,36 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
     }
 
     fn visit_expr(&mut self, expr: &'a Expr) {
-        if matches!(expr.kind, ExprKind::MacCall(..)) {
-            return self.visit_macro_invoc(expr.id);
+        // If we're visiting the expression of a const argument that was a macro call then
+        // check if it is *still* unknown whether it is a trivial const arg or not. If so
+        // recurse into the macro call and delay creating the anon const def until expansion.
+        if self.pending_anon_const_info.is_some()
+            && let Some((pending_anon, macro_invoc)) =
+                self.is_const_arg_sub_expr_trivial_macro_expansion(expr)
+        {
+            self.pending_anon_const_info = Some(pending_anon);
+            return self.visit_macro_invoc(macro_invoc);
         }
 
-        let grandparent_def = if let Some(pending_anon) = self.pending_anon_const_info.take() {
-            // See self.pending_anon_const_info for explanation
-            if !expr.is_potential_trivial_const_arg() {
+        // See self.pending_anon_const_info for explanation
+        let parent_def = self
+            .pending_anon_const_info
+            .take()
+            // If we already stripped away a set of braces then do not do it again when determining
+            // if the macro expanded to a trivial const arg. This arises in cases such as:
+            // `Foo<{ bar!() }>` where `bar!()` expands to `{ N }`. This should not be considered a
+            // trivial const argument even though `{ N }` by itself *is*.
+            .filter(|pending_anon| {
+                !expr.is_potential_trivial_const_arg(!pending_anon.block_was_stripped)
+            })
+            .map(|pending_anon| {
                 self.create_def(pending_anon.id, kw::Empty, DefKind::AnonConst, pending_anon.span)
-            } else {
-                self.parent_def
-            }
-        } else {
-            self.parent_def
-        };
+            })
+            .unwrap_or(self.parent_def);
 
-        self.with_parent(grandparent_def, |this| {
+        self.with_parent(parent_def, |this| {
             let parent_def = match expr.kind {
+                ExprKind::MacCall(..) => return this.visit_macro_invoc(expr.id),
                 ExprKind::Closure(..) | ExprKind::Gen(..) => {
                     this.create_def(expr.id, kw::Empty, DefKind::Closure, expr.span)
                 }
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index ac03a3ac42c..4c84e3621dc 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -404,6 +404,8 @@ pub(crate) enum PathSource<'a> {
     Delegation,
     /// An arg in a `use<'a, N>` precise-capturing bound.
     PreciseCapturingArg(Namespace),
+    // Paths that end with `(..)`, for return type notation.
+    ReturnTypeNotation,
 }
 
 impl<'a> PathSource<'a> {
@@ -413,7 +415,8 @@ impl<'a> PathSource<'a> {
             PathSource::Expr(..)
             | PathSource::Pat
             | PathSource::TupleStruct(..)
-            | PathSource::Delegation => ValueNS,
+            | PathSource::Delegation
+            | PathSource::ReturnTypeNotation => ValueNS,
             PathSource::TraitItem(ns) => ns,
             PathSource::PreciseCapturingArg(ns) => ns,
         }
@@ -425,7 +428,8 @@ impl<'a> PathSource<'a> {
             | PathSource::Expr(..)
             | PathSource::Pat
             | PathSource::Struct
-            | PathSource::TupleStruct(..) => true,
+            | PathSource::TupleStruct(..)
+            | PathSource::ReturnTypeNotation => true,
             PathSource::Trait(_)
             | PathSource::TraitItem(..)
             | PathSource::Delegation
@@ -471,7 +475,7 @@ impl<'a> PathSource<'a> {
                 },
                 _ => "value",
             },
-            PathSource::Delegation => "function",
+            PathSource::ReturnTypeNotation | PathSource::Delegation => "function",
             PathSource::PreciseCapturingArg(..) => "type or const parameter",
         }
     }
@@ -540,6 +544,10 @@ impl<'a> PathSource<'a> {
                 Res::Def(DefKind::AssocTy, _) if ns == TypeNS => true,
                 _ => false,
             },
+            PathSource::ReturnTypeNotation => match res {
+                Res::Def(DefKind::AssocFn, _) => true,
+                _ => false,
+            },
             PathSource::Delegation => matches!(res, Res::Def(DefKind::Fn | DefKind::AssocFn, _)),
             PathSource::PreciseCapturingArg(ValueNS) => {
                 matches!(res, Res::Def(DefKind::ConstParam, _))
@@ -565,8 +573,8 @@ impl<'a> PathSource<'a> {
             (PathSource::Expr(..), false) | (PathSource::Delegation, false) => E0425,
             (PathSource::Pat | PathSource::TupleStruct(..), true) => E0532,
             (PathSource::Pat | PathSource::TupleStruct(..), false) => E0531,
-            (PathSource::TraitItem(..), true) => E0575,
-            (PathSource::TraitItem(..), false) => E0576,
+            (PathSource::TraitItem(..), true) | (PathSource::ReturnTypeNotation, true) => E0575,
+            (PathSource::TraitItem(..), false) | (PathSource::ReturnTypeNotation, false) => E0576,
             (PathSource::PreciseCapturingArg(..), true) => E0799,
             (PathSource::PreciseCapturingArg(..), false) => E0800,
         }
@@ -781,7 +789,20 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
             }
             TyKind::Path(qself, path) => {
                 self.diag_metadata.current_type_path = Some(ty);
-                self.smart_resolve_path(ty.id, qself, path, PathSource::Type);
+
+                // If we have a path that ends with `(..)`, then it must be
+                // return type notation. Resolve that path in the *value*
+                // namespace.
+                let source = if let Some(seg) = path.segments.last()
+                    && let Some(args) = &seg.args
+                    && matches!(**args, GenericArgs::ParenthesizedElided(..))
+                {
+                    PathSource::ReturnTypeNotation
+                } else {
+                    PathSource::Type
+                };
+
+                self.smart_resolve_path(ty.id, qself, path, source);
 
                 // Check whether we should interpret this as a bare trait object.
                 if qself.is_none()
@@ -1920,7 +1941,8 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                 PathSource::Trait(..)
                 | PathSource::TraitItem(..)
                 | PathSource::Type
-                | PathSource::PreciseCapturingArg(..) => false,
+                | PathSource::PreciseCapturingArg(..)
+                | PathSource::ReturnTypeNotation => false,
                 PathSource::Expr(..)
                 | PathSource::Pat
                 | PathSource::Struct
@@ -4524,7 +4546,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
         );
 
         self.resolve_anon_const_manual(
-            constant.value.is_potential_trivial_const_arg(),
+            constant.value.is_potential_trivial_const_arg(true),
             anon_const_kind,
             |this| this.resolve_expr(&constant.value, None),
         )
@@ -4688,7 +4710,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                     // that is how they will be later lowered to HIR.
                     if const_args.contains(&idx) {
                         self.resolve_anon_const_manual(
-                            argument.is_potential_trivial_const_arg(),
+                            argument.is_potential_trivial_const_arg(true),
                             AnonConstKind::ConstArg(IsRepeatExpr::No),
                             |this| this.resolve_expr(argument, None),
                         );
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index c05bd9e72ea..3bb1f6b52a7 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -190,6 +190,11 @@ impl InvocationParent {
 
 #[derive(Copy, Debug, Clone)]
 struct PendingAnonConstInfo {
+    // A const arg is only a "trivial" const arg if it has at *most* one set of braces
+    // around the argument. We track whether we have stripped an outter brace so that
+    // if a macro expands to a braced expression *and* the macro was itself inside of
+    // some braces then we can consider it to be a non-trivial const argument.
+    block_was_stripped: bool,
     id: NodeId,
     span: Span,
 }
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
index a0a0dd058ff..9c2f869f357 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs
@@ -145,7 +145,7 @@ fn encode_const<'tcx>(
                     let _ = write!(s, "{val}");
                 }
                 ty::Bool => {
-                    let val = c.try_eval_bool(tcx, ty::ParamEnv::reveal_all()).unwrap();
+                    let val = c.try_to_bool().expect("expected monomorphic const in cfi");
                     let _ = write!(s, "{val}");
                 }
                 _ => {
@@ -411,7 +411,7 @@ pub fn encode_ty<'tcx>(
 
         ty::Array(ty0, len) => {
             // A<array-length><element-type>
-            let len = len.eval_target_usize(tcx, ty::ParamEnv::reveal_all());
+            let len = len.try_to_target_usize(tcx).expect("expected monomorphic const in cfi");
             let mut s = String::from("A");
             let _ = write!(s, "{len}");
             s.push_str(&encode_ty(tcx, *ty0, dict, options));
diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
index 34763adde4f..e4231d75506 100644
--- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
+++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs
@@ -146,7 +146,10 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for TransformTy<'tcx> {
                         !is_zst
                     });
                     if let Some(field) = field {
-                        let ty0 = self.tcx.erase_regions(field.ty(self.tcx, args));
+                        let ty0 = self.tcx.normalize_erasing_regions(
+                            ty::ParamEnv::reveal_all(),
+                            field.ty(self.tcx, args),
+                        );
                         // Generalize any repr(transparent) user-defined type that is either a
                         // pointer or reference, and either references itself or any other type that
                         // contains or references itself, to avoid a reference cycle.
diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs
index f52cb010a87..e9c3b3ffc1d 100644
--- a/compiler/rustc_smir/src/rustc_internal/internal.rs
+++ b/compiler/rustc_smir/src/rustc_internal/internal.rs
@@ -470,6 +470,7 @@ impl RustcInternal for Abi {
             Abi::AvrInterrupt => rustc_target::spec::abi::Abi::AvrInterrupt,
             Abi::AvrNonBlockingInterrupt => rustc_target::spec::abi::Abi::AvrNonBlockingInterrupt,
             Abi::CCmseNonSecureCall => rustc_target::spec::abi::Abi::CCmseNonSecureCall,
+            Abi::CCmseNonSecureEntry => rustc_target::spec::abi::Abi::CCmseNonSecureEntry,
             Abi::System { unwind } => rustc_target::spec::abi::Abi::System { unwind },
             Abi::RustIntrinsic => rustc_target::spec::abi::Abi::RustIntrinsic,
             Abi::RustCall => rustc_target::spec::abi::Abi::RustCall,
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
index 9f554ec6c35..06f01aebf9b 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
@@ -105,6 +105,7 @@ impl<'tcx> Stable<'tcx> for rustc_target::abi::call::Conv {
             Conv::PreserveAll => CallConvention::PreserveAll,
             Conv::ArmAapcs => CallConvention::ArmAapcs,
             Conv::CCmseNonSecureCall => CallConvention::CCmseNonSecureCall,
+            Conv::CCmseNonSecureEntry => CallConvention::CCmseNonSecureEntry,
             Conv::Msp430Intr => CallConvention::Msp430Intr,
             Conv::PtxKernel => CallConvention::PtxKernel,
             Conv::X86Fastcall => CallConvention::X86Fastcall,
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
index efbb0f244fc..74bdf97ac44 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
@@ -910,6 +910,7 @@ impl<'tcx> Stable<'tcx> for rustc_target::spec::abi::Abi {
             abi::Abi::AvrInterrupt => Abi::AvrInterrupt,
             abi::Abi::AvrNonBlockingInterrupt => Abi::AvrNonBlockingInterrupt,
             abi::Abi::CCmseNonSecureCall => Abi::CCmseNonSecureCall,
+            abi::Abi::CCmseNonSecureEntry => Abi::CCmseNonSecureEntry,
             abi::Abi::System { unwind } => Abi::System { unwind },
             abi::Abi::RustIntrinsic => Abi::RustIntrinsic,
             abi::Abi::RustCall => Abi::RustCall,
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index cbe2bafef21..de4532bcb99 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -309,6 +309,7 @@ symbols! {
         RwLockReadGuard,
         RwLockWriteGuard,
         Saturating,
+        SeekFrom,
         Send,
         SeqCst,
         Sized,
@@ -342,6 +343,7 @@ symbols! {
         Upvars,
         Vec,
         VecDeque,
+        Waker,
         Wrapper,
         Wrapping,
         Yield,
@@ -488,6 +490,7 @@ symbols! {
         begin_panic,
         bench,
         bin,
+        binaryheap_iter,
         bind_by_move_pattern_guards,
         bindings_after_at,
         bitand,
@@ -500,6 +503,7 @@ symbols! {
         black_box,
         block,
         bool,
+        bool_then,
         borrowck_graphviz_format,
         borrowck_graphviz_postflow,
         box_new,
@@ -511,6 +515,9 @@ symbols! {
         breakpoint,
         bridge,
         bswap,
+        btreemap_contains_key,
+        btreemap_insert,
+        btreeset_iter,
         builtin_syntax,
         c,
         c_str,
@@ -678,6 +685,7 @@ symbols! {
         crt_dash_static: "crt-static",
         csky_target_feature,
         cstr_type,
+        cstring_as_c_str,
         cstring_type,
         ctlz,
         ctlz_nonzero,
@@ -833,6 +841,7 @@ symbols! {
         f16_nan,
         f16c_target_feature,
         f32,
+        f32_epsilon,
         f32_legacy_const_digits,
         f32_legacy_const_epsilon,
         f32_legacy_const_infinity,
@@ -849,6 +858,7 @@ symbols! {
         f32_legacy_const_radix,
         f32_nan,
         f64,
+        f64_epsilon,
         f64_legacy_const_digits,
         f64_legacy_const_epsilon,
         f64_legacy_const_infinity,
@@ -886,6 +896,7 @@ symbols! {
         field,
         field_init_shorthand,
         file,
+        file_options,
         float,
         float_to_int_unchecked,
         floorf128,
@@ -971,6 +982,17 @@ symbols! {
         half_open_range_patterns,
         half_open_range_patterns_in_slices,
         hash,
+        hashmap_contains_key,
+        hashmap_drain_ty,
+        hashmap_insert,
+        hashmap_iter_mut_ty,
+        hashmap_iter_ty,
+        hashmap_keys_ty,
+        hashmap_values_mut_ty,
+        hashmap_values_ty,
+        hashset_drain_ty,
+        hashset_iter,
+        hashset_iter_ty,
         hexagon_target_feature,
         hidden,
         homogeneous_aggregate,
@@ -1049,6 +1071,7 @@ symbols! {
         inline_const,
         inline_const_pat,
         inout,
+        instant_now,
         instruction_set,
         integer_: "integer", // underscore to avoid clashing with the function `sym::integer` below
         integral,
@@ -1077,6 +1100,9 @@ symbols! {
         item,
         item_like_imports,
         iter,
+        iter_cloned,
+        iter_copied,
+        iter_filter,
         iter_mut,
         iter_repeat,
         iterator,
@@ -1346,6 +1372,7 @@ symbols! {
         on,
         on_unimplemented,
         opaque,
+        open_options_new,
         ops,
         opt_out_copy,
         optimize,
@@ -1353,10 +1380,14 @@ symbols! {
         optin_builtin_traits,
         option,
         option_env,
+        option_expect,
+        option_unwrap,
         options,
         or,
         or_patterns,
         ord_cmp_method,
+        os_str_to_os_string,
+        os_string_as_os_str,
         other,
         out,
         overflow_checks,
@@ -1410,14 +1441,19 @@ symbols! {
         pat_param,
         patchable_function_entry,
         path,
+        path_main_separator,
+        path_to_pathbuf,
+        pathbuf_as_path,
         pattern_complexity,
         pattern_parentheses,
         pattern_type,
         pattern_types,
+        permissions_from_mode,
         phantom_data,
         pic,
         pie,
         pin,
+        pin_ergonomics,
         platform_intrinsics,
         plugin,
         plugin_registrar,
@@ -1565,6 +1601,7 @@ symbols! {
         residual,
         result,
         result_ffi_guarantees,
+        result_ok_method,
         resume,
         return_position_impl_trait_in_trait,
         return_type_notation,
@@ -1817,6 +1854,8 @@ symbols! {
         slice,
         slice_from_raw_parts,
         slice_from_raw_parts_mut,
+        slice_into_vec,
+        slice_iter,
         slice_len_fn,
         slice_patterns,
         slicing_syntax,
@@ -1849,16 +1888,26 @@ symbols! {
         stop_after_dataflow,
         store,
         str,
+        str_chars,
+        str_ends_with,
         str_from_utf8,
         str_from_utf8_mut,
         str_from_utf8_unchecked,
         str_from_utf8_unchecked_mut,
+        str_len,
         str_split_whitespace,
+        str_starts_with,
         str_trim,
         str_trim_end,
         str_trim_start,
         strict_provenance,
+        string_as_mut_str,
+        string_as_str,
         string_deref_patterns,
+        string_from_utf8,
+        string_insert_str,
+        string_new,
+        string_push_str,
         stringify,
         struct_field_attributes,
         struct_inherit,
@@ -2063,7 +2112,15 @@ symbols! {
         var,
         variant_count,
         vec,
+        vec_as_mut_slice,
+        vec_as_slice,
+        vec_from_elem,
+        vec_is_empty,
         vec_macro,
+        vec_new,
+        vec_pop,
+        vec_with_capacity,
+        vecdeque_iter,
         version,
         vfp2,
         vis,
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index ba35a37c32c..79de9bbb351 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -330,8 +330,12 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
             ty::Float(FloatTy::F128) => "C4f128",
             ty::Never => "z",
 
-            // Placeholders (should be demangled as `_`).
-            ty::Param(_) | ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) | ty::Error(_) => "p",
+            // Should only be encountered with polymorphization,
+            // or within the identity-substituted impl header of an
+            // item nested within an impl item.
+            ty::Param(_) => "p",
+
+            ty::Bound(..) | ty::Placeholder(_) | ty::Infer(_) | ty::Error(_) => bug!(),
 
             _ => "",
         };
@@ -416,12 +420,18 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
             // Mangle all nominal types as paths.
             ty::Adt(ty::AdtDef(Interned(&ty::AdtDefData { did: def_id, .. }, _)), args)
             | ty::FnDef(def_id, args)
-            | ty::Alias(ty::Projection | ty::Opaque, ty::AliasTy { def_id, args, .. })
             | ty::Closure(def_id, args)
             | ty::CoroutineClosure(def_id, args)
             | ty::Coroutine(def_id, args) => {
                 self.print_def_path(def_id, args)?;
             }
+
+            // We may still encounter projections here due to the printing
+            // logic sometimes passing identity-substituted impl headers.
+            ty::Alias(ty::Projection, ty::AliasTy { def_id, args, .. }) => {
+                self.print_def_path(def_id, args)?;
+            }
+
             ty::Foreign(def_id) => {
                 self.print_def_path(def_id, &[])?;
             }
@@ -467,8 +477,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
                 r.print(self)?;
             }
 
-            ty::Alias(ty::Inherent, _) => bug!("symbol_names: unexpected inherent projection"),
-            ty::Alias(ty::Weak, _) => bug!("symbol_names: unexpected weak projection"),
+            ty::Alias(..) => bug!("symbol_names: unexpected alias"),
             ty::CoroutineWitness(..) => bug!("symbol_names: unexpected `CoroutineWitness`"),
         }
 
@@ -550,21 +559,26 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
         let (ct_ty, valtree) = match ct.kind() {
             ty::ConstKind::Value(ty, val) => (ty, val),
 
-            // Placeholders (should be demangled as `_`).
-            // NOTE(eddyb) despite `Unevaluated` having a `DefId` (and therefore
-            // a path), even for it we still need to encode a placeholder, as
-            // the path could refer back to e.g. an `impl` using the constant.
-            ty::ConstKind::Unevaluated(_)
-            | ty::ConstKind::Expr(_)
-            | ty::ConstKind::Param(_)
-            | ty::ConstKind::Infer(_)
-            | ty::ConstKind::Bound(..)
-            | ty::ConstKind::Placeholder(_)
-            | ty::ConstKind::Error(_) => {
+            // Should only be encountered with polymorphization,
+            // or within the identity-substituted impl header of an
+            // item nested within an impl item.
+            ty::ConstKind::Param(_) => {
                 // Never cached (single-character).
                 self.push("p");
                 return Ok(());
             }
+
+            // We may still encounter unevaluated consts due to the printing
+            // logic sometimes passing identity-substituted impl headers.
+            ty::Unevaluated(ty::UnevaluatedConst { def, args, .. }) => {
+                return self.print_def_path(def, args);
+            }
+
+            ty::ConstKind::Expr(_)
+            | ty::ConstKind::Infer(_)
+            | ty::ConstKind::Bound(..)
+            | ty::ConstKind::Placeholder(_)
+            | ty::ConstKind::Error(_) => bug!(),
         };
 
         if let Some(&i) = self.consts.get(&ct) {
diff --git a/compiler/rustc_target/src/abi/call/m68k.rs b/compiler/rustc_target/src/abi/call/m68k.rs
index b6bd68b66fc..82fe81f8c52 100644
--- a/compiler/rustc_target/src/abi/call/m68k.rs
+++ b/compiler/rustc_target/src/abi/call/m68k.rs
@@ -14,7 +14,7 @@ fn classify_arg<Ty>(arg: &mut ArgAbi<'_, Ty>) {
         return;
     }
     if arg.layout.is_aggregate() {
-        arg.make_indirect_byval(None);
+        arg.pass_by_stack_offset(None);
     } else {
         arg.extend_integer_width_to(32);
     }
diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs
index c2826b55dc5..f4469467249 100644
--- a/compiler/rustc_target/src/abi/call/mod.rs
+++ b/compiler/rustc_target/src/abi/call/mod.rs
@@ -64,7 +64,7 @@ pub enum PassMode {
     /// (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.
+    /// match the Rust type's alignment; see documentation of `pass_by_stack_offset` 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 },
@@ -681,7 +681,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
     /// 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.
-    pub fn make_indirect_byval(&mut self, byval_align: Option<Align>) {
+    pub fn pass_by_stack_offset(&mut self, byval_align: Option<Align>) {
         assert!(!self.layout.is_unsized(), "used byval ABI for unsized layout");
         self.make_indirect();
         match self.mode {
@@ -779,6 +779,7 @@ pub enum Conv {
     // Target-specific calling conventions.
     ArmAapcs,
     CCmseNonSecureCall,
+    CCmseNonSecureEntry,
 
     Msp430Intr,
 
@@ -879,8 +880,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
     {
         if abi == spec::abi::Abi::X86Interrupt {
             if let Some(arg) = self.args.first_mut() {
-                // FIXME(pcwalton): This probably should use the x86 `byval` ABI...
-                arg.make_indirect_byval(None);
+                arg.pass_by_stack_offset(None);
             }
             return Ok(());
         }
@@ -973,6 +973,7 @@ impl FromStr for Conv {
             "RustCold" => Ok(Conv::Rust),
             "ArmAapcs" => Ok(Conv::ArmAapcs),
             "CCmseNonSecureCall" => Ok(Conv::CCmseNonSecureCall),
+            "CCmseNonSecureEntry" => Ok(Conv::CCmseNonSecureEntry),
             "Msp430Intr" => Ok(Conv::Msp430Intr),
             "PtxKernel" => Ok(Conv::PtxKernel),
             "X86Fastcall" => Ok(Conv::X86Fastcall),
diff --git a/compiler/rustc_target/src/abi/call/wasm.rs b/compiler/rustc_target/src/abi/call/wasm.rs
index 4ae8b9490dd..3c4cd76a754 100644
--- a/compiler/rustc_target/src/abi/call/wasm.rs
+++ b/compiler/rustc_target/src/abi/call/wasm.rs
@@ -40,7 +40,7 @@ where
     }
     arg.extend_integer_width_to(32);
     if arg.layout.is_aggregate() && !unwrap_trivial_aggregate(cx, arg) {
-        arg.make_indirect_byval(None);
+        arg.make_indirect();
     }
 }
 
diff --git a/compiler/rustc_target/src/abi/call/x86.rs b/compiler/rustc_target/src/abi/call/x86.rs
index bdb14350ded..d9af83d3205 100644
--- a/compiler/rustc_target/src/abi/call/x86.rs
+++ b/compiler/rustc_target/src/abi/call/x86.rs
@@ -122,7 +122,7 @@ where
                 align_4
             };
 
-            arg.make_indirect_byval(Some(byval_align));
+            arg.pass_by_stack_offset(Some(byval_align));
         } else {
             arg.extend_integer_width_to(32);
         }
diff --git a/compiler/rustc_target/src/abi/call/x86_64.rs b/compiler/rustc_target/src/abi/call/x86_64.rs
index 1209204debf..9910e623ac9 100644
--- a/compiler/rustc_target/src/abi/call/x86_64.rs
+++ b/compiler/rustc_target/src/abi/call/x86_64.rs
@@ -219,7 +219,7 @@ where
                 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);
+                    arg.pass_by_stack_offset(None);
                 } else {
                     // `sret` parameter thus one less integer register available
                     arg.make_indirect();
diff --git a/compiler/rustc_target/src/abi/call/xtensa.rs b/compiler/rustc_target/src/abi/call/xtensa.rs
index d7b5fe9d4cc..e1728b08a39 100644
--- a/compiler/rustc_target/src/abi/call/xtensa.rs
+++ b/compiler/rustc_target/src/abi/call/xtensa.rs
@@ -68,7 +68,7 @@ where
     *arg_gprs_left -= needed_arg_gprs;
 
     if must_use_stack {
-        arg.make_indirect_byval(None);
+        arg.pass_by_stack_offset(None);
     } else if is_xtensa_aggregate(arg) {
         // Aggregates which are <= max_size will be passed in
         // registers if possible, so coerce to integers.
diff --git a/compiler/rustc_target/src/json.rs b/compiler/rustc_target/src/json.rs
index 9436e34d380..5fcf5be101f 100644
--- a/compiler/rustc_target/src/json.rs
+++ b/compiler/rustc_target/src/json.rs
@@ -103,6 +103,7 @@ impl ToJson for crate::abi::call::Conv {
             Self::PreserveAll => "PreserveAll",
             Self::ArmAapcs => "ArmAapcs",
             Self::CCmseNonSecureCall => "CCmseNonSecureCall",
+            Self::CCmseNonSecureEntry => "CCmseNonSecureEntry",
             Self::Msp430Intr => "Msp430Intr",
             Self::PtxKernel => "PtxKernel",
             Self::X86Fastcall => "X86Fastcall",
diff --git a/compiler/rustc_target/src/spec/abi/mod.rs b/compiler/rustc_target/src/spec/abi/mod.rs
index cc383f88fbc..cac0cf9959d 100644
--- a/compiler/rustc_target/src/spec/abi/mod.rs
+++ b/compiler/rustc_target/src/spec/abi/mod.rs
@@ -48,6 +48,7 @@ pub enum Abi {
     AvrInterrupt,
     AvrNonBlockingInterrupt,
     CCmseNonSecureCall,
+    CCmseNonSecureEntry,
     System {
         unwind: bool,
     },
@@ -124,6 +125,7 @@ const AbiDatas: &[AbiData] = &[
     AbiData { abi: Abi::AvrInterrupt, name: "avr-interrupt" },
     AbiData { abi: Abi::AvrNonBlockingInterrupt, name: "avr-non-blocking-interrupt" },
     AbiData { abi: Abi::CCmseNonSecureCall, name: "C-cmse-nonsecure-call" },
+    AbiData { abi: Abi::CCmseNonSecureEntry, name: "C-cmse-nonsecure-entry" },
     AbiData { abi: Abi::System { unwind: false }, name: "system" },
     AbiData { abi: Abi::System { unwind: true }, name: "system-unwind" },
     AbiData { abi: Abi::RustIntrinsic, name: "rust-intrinsic" },
@@ -244,6 +246,10 @@ pub fn is_stable(name: &str) -> Result<(), AbiDisabled> {
             feature: sym::abi_c_cmse_nonsecure_call,
             explain: "C-cmse-nonsecure-call ABI is experimental and subject to change",
         }),
+        "C-cmse-nonsecure-entry" => Err(AbiDisabled::Unstable {
+            feature: sym::cmse_nonsecure_entry,
+            explain: "C-cmse-nonsecure-entry ABI is experimental and subject to change",
+        }),
         _ => Err(AbiDisabled::Unrecognized),
     }
 }
@@ -286,15 +292,16 @@ impl Abi {
             AvrInterrupt => 23,
             AvrNonBlockingInterrupt => 24,
             CCmseNonSecureCall => 25,
+            CCmseNonSecureEntry => 26,
             // Cross-platform ABIs
-            System { unwind: false } => 26,
-            System { unwind: true } => 27,
-            RustIntrinsic => 28,
-            RustCall => 29,
-            Unadjusted => 30,
-            RustCold => 31,
-            RiscvInterruptM => 32,
-            RiscvInterruptS => 33,
+            System { unwind: false } => 27,
+            System { unwind: true } => 28,
+            RustIntrinsic => 29,
+            RustCall => 30,
+            Unadjusted => 31,
+            RustCold => 32,
+            RiscvInterruptM => 33,
+            RiscvInterruptS => 34,
         };
         debug_assert!(
             AbiDatas
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index f12e3e595ad..ec4f5ef79d1 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1714,8 +1714,10 @@ supported_targets! {
     ("x86_64-apple-ios-macabi", x86_64_apple_ios_macabi),
     ("aarch64-apple-ios-macabi", aarch64_apple_ios_macabi),
     ("aarch64-apple-ios-sim", aarch64_apple_ios_sim),
+
     ("aarch64-apple-tvos", aarch64_apple_tvos),
     ("aarch64-apple-tvos-sim", aarch64_apple_tvos_sim),
+    ("arm64e-apple-tvos", arm64e_apple_tvos),
     ("x86_64-apple-tvos", x86_64_apple_tvos),
 
     ("armv7k-apple-watchos", armv7k_apple_watchos),
@@ -2722,7 +2724,10 @@ impl Target {
             }
             X86Interrupt => ["x86", "x86_64"].contains(&&self.arch[..]),
             Aapcs { .. } => "arm" == self.arch,
-            CCmseNonSecureCall => ["arm", "aarch64"].contains(&&self.arch[..]),
+            CCmseNonSecureCall | CCmseNonSecureEntry => {
+                ["thumbv8m.main-none-eabi", "thumbv8m.main-none-eabihf", "thumbv8m.base-none-eabi"]
+                    .contains(&&self.llvm_target[..])
+            }
             Win64 { .. } | SysV64 { .. } => self.arch == "x86_64",
             PtxKernel => self.arch == "nvptx64",
             Msp430Interrupt => self.arch == "msp430",
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 1061633be17..7af7de60fcb 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
@@ -6,7 +6,7 @@ pub(crate) fn target() -> Target {
     Target {
         llvm_target,
         metadata: crate::spec::TargetMetadata {
-            description: Some("ARM64 macOS (11.0+, Big Sur+)".into()),
+            description: Some("ARM64 Apple macOS (11.0+, Big Sur+)".into()),
             tier: Some(1),
             host_tools: Some(true),
             std: Some(true),
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 caeb9a121e4..499f05d9ee6 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
@@ -6,7 +6,7 @@ pub(crate) fn target() -> Target {
     Target {
         llvm_target,
         metadata: crate::spec::TargetMetadata {
-            description: Some("ARM64 iOS".into()),
+            description: Some("ARM64 Apple iOS".into()),
             tier: Some(2),
             host_tools: Some(false),
             std: Some(true),
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 eee9eca3bcb..0fd5d0f83d2 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
@@ -6,7 +6,7 @@ pub(crate) fn target() -> Target {
     Target {
         llvm_target,
         metadata: crate::spec::TargetMetadata {
-            description: Some("Apple Catalyst on ARM64".into()),
+            description: Some("ARM64 Apple Mac Catalyst".into()),
             tier: Some(2),
             host_tools: Some(false),
             std: Some(true),
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 ee58038301d..0f58d4e2730 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
@@ -6,7 +6,7 @@ pub(crate) fn target() -> Target {
     Target {
         llvm_target,
         metadata: crate::spec::TargetMetadata {
-            description: Some("Apple iOS Simulator on ARM64".into()),
+            description: Some("ARM64 Apple iOS Simulator".into()),
             tier: Some(2),
             host_tools: Some(false),
             std: Some(true),
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 baca863d442..49c7b30817d 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
@@ -6,7 +6,7 @@ pub(crate) fn target() -> Target {
     Target {
         llvm_target,
         metadata: crate::spec::TargetMetadata {
-            description: Some("ARM64 tvOS".into()),
+            description: Some("ARM64 Apple tvOS".into()),
             tier: Some(3),
             host_tools: Some(false),
             std: Some(true),
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 1a48f8c5acf..2cb2d0b3fff 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
@@ -6,7 +6,7 @@ pub(crate) fn target() -> Target {
     Target {
         llvm_target,
         metadata: crate::spec::TargetMetadata {
-            description: Some("ARM64 tvOS Simulator".into()),
+            description: Some("ARM64 Apple tvOS Simulator".into()),
             tier: Some(3),
             host_tools: Some(false),
             std: Some(true),
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 1940a568b39..6233febd8c5 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
@@ -6,7 +6,7 @@ pub(crate) fn target() -> Target {
     Target {
         llvm_target,
         metadata: crate::spec::TargetMetadata {
-            description: Some("ARM64 Apple WatchOS".into()),
+            description: Some("ARM64 Apple watchOS".into()),
             tier: Some(3),
             host_tools: Some(false),
             std: Some(true),
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 6beef11c504..64d24b8a075 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
@@ -6,7 +6,7 @@ pub(crate) fn target() -> Target {
     Target {
         llvm_target,
         metadata: crate::spec::TargetMetadata {
-            description: Some("ARM64 Apple WatchOS Simulator".into()),
+            description: Some("ARM64 Apple watchOS Simulator".into()),
             tier: Some(3),
             host_tools: Some(false),
             std: Some(true),
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 e9f4d9330d5..60b1c1db63a 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
@@ -6,7 +6,7 @@ pub(crate) fn target() -> Target {
     Target {
         llvm_target,
         metadata: crate::spec::TargetMetadata {
-            description: Some("Arm Apple WatchOS 64-bit with 32-bit pointers".into()),
+            description: Some("ARM64 Apple watchOS with 32-bit pointers".into()),
             tier: Some(3),
             host_tools: Some(false),
             std: Some(true),
diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs
new file mode 100644
index 00000000000..d4d66c92857
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs
@@ -0,0 +1,24 @@
+use crate::spec::base::apple::{base, Arch, TargetAbi};
+use crate::spec::{FramePointer, Target, TargetOptions};
+
+pub(crate) fn target() -> Target {
+    let (opts, llvm_target, arch) = base("tvos", Arch::Arm64e, TargetAbi::Normal);
+    Target {
+        llvm_target,
+        metadata: crate::spec::TargetMetadata {
+            description: Some("ARM64e Apple tvOS".into()),
+            tier: Some(3),
+            host_tools: Some(false),
+            std: Some(true),
+        },
+        pointer_width: 64,
+        data_layout: "e-m:o-i64:64-i128:128-n32:64-S128-Fn32".into(),
+        arch,
+        options: TargetOptions {
+            features: "+neon,+fp-armv8,+apple-a12,+v8.3a,+pauth".into(),
+            max_atomic_width: Some(128),
+            frame_pointer: FramePointer::NonLeaf,
+            ..opts
+        },
+    }
+}
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 deee6985f1a..5af760f68ef 100644
--- a/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
@@ -6,7 +6,7 @@ pub(crate) fn target() -> Target {
     Target {
         llvm_target,
         metadata: crate::spec::TargetMetadata {
-            description: Some("Armv7-A Apple-A6 Apple iOS".into()),
+            description: Some("ARMv7-A Apple-A6 Apple iOS".into()),
             tier: Some(3),
             host_tools: Some(false),
             std: Some(true),
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 dc14cb3ec76..7078b57e98b 100644
--- a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
@@ -8,7 +8,7 @@ pub(crate) fn target() -> Target {
     Target {
         llvm_target,
         metadata: crate::spec::TargetMetadata {
-            description: Some("32-bit x86 iOS".into()),
+            description: Some("x86 Apple iOS Simulator".into()),
             tier: Some(3),
             host_tools: Some(false),
             std: Some(true),
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 3e27f1f899b..9d9a8fc6305 100644
--- a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
@@ -6,7 +6,7 @@ pub(crate) fn target() -> Target {
     Target {
         llvm_target,
         metadata: crate::spec::TargetMetadata {
-            description: Some("32-bit macOS (10.12+, Sierra+)".into()),
+            description: Some("x86 Apple macOS (10.12+, Sierra+)".into()),
             tier: Some(3),
             host_tools: Some(true),
             std: Some(true),
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 e0a6c230fd6..71086daaf2c 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
@@ -10,7 +10,7 @@ pub(crate) fn target() -> Target {
     // ABI. Pass the -vector feature string to LLVM to respect this assumption. On LLVM < 16, we
     // also strip v128 from the data_layout below to match the older LLVM's expectation.
     base.features = "-vector".into();
-    base.max_atomic_width = Some(64);
+    base.max_atomic_width = Some(128);
     base.min_global_align = Some(16);
     base.stack_probes = StackProbeType::Inline;
     base.supported_sanitizers =
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 6aabe9ca519..016ff5abe4c 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
@@ -10,7 +10,7 @@ pub(crate) fn target() -> Target {
     // ABI. Pass the -vector feature string to LLVM to respect this assumption. On LLVM < 16, we
     // also strip v128 from the data_layout below to match the older LLVM's expectation.
     base.features = "-vector".into();
-    base.max_atomic_width = Some(64);
+    base.max_atomic_width = Some(128);
     base.min_global_align = Some(16);
     base.static_position_independent_executables = true;
     base.stack_probes = StackProbeType::Inline;
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 4304dfc3f68..70211722fa2 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
@@ -6,7 +6,7 @@ pub(crate) fn target() -> Target {
     Target {
         llvm_target,
         metadata: crate::spec::TargetMetadata {
-            description: Some("64-bit macOS (10.12+, Sierra+)".into()),
+            description: Some("x86_64 Apple macOS (10.12+, Sierra+)".into()),
             tier: Some(1),
             host_tools: Some(true),
             std: Some(true),
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 847c4f011f9..c021762aed0 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
@@ -8,7 +8,7 @@ pub(crate) fn target() -> Target {
     Target {
         llvm_target,
         metadata: crate::spec::TargetMetadata {
-            description: Some("64-bit x86 iOS".into()),
+            description: Some("x86_64 Apple iOS Simulator".into()),
             tier: Some(2),
             host_tools: Some(false),
             std: Some(true),
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 042079f800b..a7ba81303cf 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
@@ -6,7 +6,7 @@ pub(crate) fn target() -> Target {
     Target {
         llvm_target,
         metadata: crate::spec::TargetMetadata {
-            description: Some("Apple Catalyst on x86_64".into()),
+            description: Some("x86_64 Apple Mac Catalyst".into()),
             tier: Some(2),
             host_tools: Some(false),
             std: Some(true),
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 94708609790..d81220b6b31 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
@@ -8,7 +8,7 @@ pub(crate) fn target() -> Target {
     Target {
         llvm_target,
         metadata: crate::spec::TargetMetadata {
-            description: Some("x86 64-bit tvOS".into()),
+            description: Some("x86_64 Apple tvOS Simulator".into()),
             tier: Some(3),
             host_tools: Some(false),
             std: Some(true),
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 1dab9598860..c7333a0bbcc 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
@@ -6,7 +6,7 @@ pub(crate) fn target() -> Target {
     Target {
         llvm_target,
         metadata: crate::spec::TargetMetadata {
-            description: Some("x86 64-bit Apple WatchOS simulator".into()),
+            description: Some("x86_64 Apple watchOS Simulator".into()),
             tier: Some(3),
             host_tools: Some(false),
             std: Some(true),
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 9fb5a46187a..e3550b6e11f 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
@@ -29,7 +29,7 @@ pub(crate) fn target() -> Target {
     Target {
         llvm_target,
         metadata: crate::spec::TargetMetadata {
-            description: Some("macOS with late-gen Intel (at least Haswell)".into()),
+            description: Some("x86_64 Apple macOS with Intel Haswell+".into()),
             tier: Some(3),
             host_tools: Some(true),
             std: Some(true),
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index 2de6ee9cf91..1f11ee3f939 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -2269,12 +2269,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     }
                     rustc_transmute::Reason::SrcSizeOverflow => {
                         format!(
-                            "values of the type `{src}` are too big for the current architecture"
+                            "values of the type `{src}` are too big for the target architecture"
                         )
                     }
                     rustc_transmute::Reason::DstSizeOverflow => {
                         format!(
-                            "values of the type `{dst}` are too big for the current architecture"
+                            "values of the type `{dst}` are too big for the target architecture"
                         )
                     }
                     rustc_transmute::Reason::DstHasStricterAlignment {
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index c82eaa5143d..538e23f4449 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -409,6 +409,9 @@ pub fn normalize_param_env_or_error<'tcx>(
     debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates);
 
     let elaborated_env = ty::ParamEnv::new(tcx.mk_clauses(&predicates), unnormalized_env.reveal());
+    if !normalize::needs_normalization(&elaborated_env, unnormalized_env.reveal()) {
+        return elaborated_env;
+    }
 
     // HACK: we are trying to normalize the param-env inside *itself*. The problem is that
     // normalization expects its param-env to be already normalized, which means we have
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 2d0c2e83690..00d38350b20 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -312,6 +312,7 @@ fn conv_from_spec_abi(tcx: TyCtxt<'_>, abi: SpecAbi, c_variadic: bool) -> Conv {
         SysV64 { .. } => Conv::X86_64SysV,
         Aapcs { .. } => Conv::ArmAapcs,
         CCmseNonSecureCall => Conv::CCmseNonSecureCall,
+        CCmseNonSecureEntry => Conv::CCmseNonSecureEntry,
         PtxKernel => Conv::PtxKernel,
         Msp430Interrupt => Conv::Msp430Intr,
         X86Interrupt => Conv::X86Intr,
diff --git a/compiler/stable_mir/src/abi.rs b/compiler/stable_mir/src/abi.rs
index 317bec3050c..dc73d9c2188 100644
--- a/compiler/stable_mir/src/abi.rs
+++ b/compiler/stable_mir/src/abi.rs
@@ -433,6 +433,7 @@ pub enum CallConvention {
     // Target-specific calling conventions.
     ArmAapcs,
     CCmseNonSecureCall,
+    CCmseNonSecureEntry,
 
     Msp430Intr,
 
diff --git a/compiler/stable_mir/src/ty.rs b/compiler/stable_mir/src/ty.rs
index 5bad3d5ae7a..011d19f6143 100644
--- a/compiler/stable_mir/src/ty.rs
+++ b/compiler/stable_mir/src/ty.rs
@@ -1062,6 +1062,7 @@ pub enum Abi {
     AvrInterrupt,
     AvrNonBlockingInterrupt,
     CCmseNonSecureCall,
+    CCmseNonSecureEntry,
     System { unwind: bool },
     RustIntrinsic,
     RustCall,
diff --git a/config.example.toml b/config.example.toml
index c66d65e639a..47ebb20d8fa 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -53,7 +53,7 @@
 #
 # Note that many of the LLVM options are not currently supported for
 # downloading. Currently only the "assertions" option can be toggled.
-#download-ci-llvm = if rust.channel == "dev" || rust.download-rustc != false { "if-unchanged" } else { false }
+#download-ci-llvm = true
 
 # Indicates whether the LLVM build is a Release or Debug build
 #optimize = true
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs
index de58b06545b..a91659b6de5 100644
--- a/library/alloc/src/alloc.rs
+++ b/library/alloc/src/alloc.rs
@@ -171,7 +171,13 @@ pub unsafe fn realloc(ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8
 #[inline]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
 pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
-    unsafe { __rust_alloc_zeroed(layout.size(), layout.align()) }
+    unsafe {
+        // Make sure we don't accidentally allow omitting the allocator shim in
+        // stable code until it is actually stabilized.
+        core::ptr::read_volatile(&__rust_no_alloc_shim_is_unstable);
+
+        __rust_alloc_zeroed(layout.size(), layout.align())
+    }
 }
 
 #[cfg(not(test))]
diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs
index fe9f1010d32..a19a044fc7e 100644
--- a/library/alloc/src/collections/binary_heap/mod.rs
+++ b/library/alloc/src/collections/binary_heap/mod.rs
@@ -959,6 +959,7 @@ impl<T, A: Allocator> BinaryHeap<T, A> {
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "binaryheap_iter")]
     pub fn iter(&self) -> Iter<'_, T> {
         Iter { iter: self.data.iter() }
     }
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index 60e08b47e3d..0eadc9ecac8 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -916,6 +916,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
     /// assert_eq!(map.contains_key(&2), false);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "btreemap_contains_key")]
     pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool
     where
         K: Borrow<Q> + Ord,
@@ -981,6 +982,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_confusables("push", "put", "set")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "btreemap_insert")]
     pub fn insert(&mut self, key: K, value: V) -> Option<V>
     where
         K: Ord,
diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs
index 2b5bebcd8cd..770cd80ea9c 100644
--- a/library/alloc/src/collections/btree/set.rs
+++ b/library/alloc/src/collections/btree/set.rs
@@ -1132,6 +1132,7 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
     /// assert_eq!(set_iter.next(), None);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "btreeset_iter")]
     pub fn iter(&self) -> Iter<'_, T> {
         Iter { iter: self.map.keys() }
     }
diff --git a/library/alloc/src/collections/linked_list/tests.rs b/library/alloc/src/collections/linked_list/tests.rs
index 9b3c9ac5ce5..c93e5813b11 100644
--- a/library/alloc/src/collections/linked_list/tests.rs
+++ b/library/alloc/src/collections/linked_list/tests.rs
@@ -1,3 +1,6 @@
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
 use std::panic::{catch_unwind, AssertUnwindSafe};
 use std::thread;
 
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index 8c9db063105..a438517b75b 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -1201,6 +1201,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
     /// assert_eq!(&c[..], b);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "vecdeque_iter")]
     pub fn iter(&self) -> Iter<'_, T> {
         let (a, b) = self.as_slices();
         Iter::new(a.iter(), b.iter())
diff --git a/library/alloc/src/collections/vec_deque/tests.rs b/library/alloc/src/collections/vec_deque/tests.rs
index f8ce4ca9788..c90679f1797 100644
--- a/library/alloc/src/collections/vec_deque/tests.rs
+++ b/library/alloc/src/collections/vec_deque/tests.rs
@@ -1,3 +1,6 @@
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
 use core::iter::TrustedLen;
 
 use super::*;
diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs
index e32676a6543..45037aa1615 100644
--- a/library/alloc/src/ffi/c_str.rs
+++ b/library/alloc/src/ffi/c_str.rs
@@ -576,6 +576,7 @@ impl CString {
     #[inline]
     #[must_use]
     #[stable(feature = "as_c_str", since = "1.20.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "cstring_as_c_str")]
     pub fn as_c_str(&self) -> &CStr {
         &*self
     }
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index f98c0cca1db..f0597f295b3 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -110,7 +110,6 @@
 #![feature(const_cow_is_borrowed)]
 #![feature(const_eval_select)]
 #![feature(const_heap)]
-#![feature(const_maybe_uninit_as_mut_ptr)]
 #![feature(const_maybe_uninit_write)]
 #![feature(const_option)]
 #![feature(const_pin)]
diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs
index 8cdba166c9d..45fb88969c6 100644
--- a/library/alloc/src/slice.rs
+++ b/library/alloc/src/slice.rs
@@ -496,6 +496,7 @@ impl<T> [T] {
     #[rustc_allow_incoherent_impl]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "slice_into_vec")]
     pub fn into_vec<A: Allocator>(self: Box<Self, A>) -> Vec<T, A> {
         // N.B., see the `hack` module in this file for more details.
         hack::into_vec(self)
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index 6daab5bc73a..83977350832 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -440,6 +440,7 @@ impl String {
     /// ```
     #[inline]
     #[rustc_const_stable(feature = "const_string_new", since = "1.39.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "string_new")]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use]
     pub const fn new() -> String {
@@ -571,6 +572,7 @@ impl String {
     /// [`into_bytes`]: String::into_bytes
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "string_from_utf8")]
     pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error> {
         match str::from_utf8(&vec) {
             Ok(..) => Ok(String { vec }),
@@ -1073,6 +1075,7 @@ impl String {
     #[inline]
     #[must_use]
     #[stable(feature = "string_as_str", since = "1.7.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "string_as_str")]
     pub fn as_str(&self) -> &str {
         self
     }
@@ -1092,6 +1095,7 @@ impl String {
     #[inline]
     #[must_use]
     #[stable(feature = "string_as_str", since = "1.7.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "string_as_mut_str")]
     pub fn as_mut_str(&mut self) -> &mut str {
         self
     }
@@ -1111,6 +1115,7 @@ impl String {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_confusables("append", "push")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "string_push_str")]
     pub fn push_str(&mut self, string: &str) {
         self.vec.extend_from_slice(string.as_bytes())
     }
@@ -1745,6 +1750,7 @@ impl String {
     #[cfg(not(no_global_oom_handling))]
     #[inline]
     #[stable(feature = "insert_str", since = "1.16.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "string_insert_str")]
     pub fn insert_str(&mut self, idx: usize, string: &str) {
         assert!(self.is_char_boundary(idx));
 
@@ -2081,7 +2087,31 @@ impl FromUtf8Error {
     #[cfg(not(no_global_oom_handling))]
     #[unstable(feature = "string_from_utf8_lossy_owned", issue = "129436")]
     pub fn into_utf8_lossy(self) -> String {
-        String::from_utf8_lossy_owned(self.bytes)
+        const REPLACEMENT: &str = "\u{FFFD}";
+
+        let mut res = {
+            let mut v = Vec::with_capacity(self.bytes.len());
+
+            // `Utf8Error::valid_up_to` returns the maximum index of validated
+            // UTF-8 bytes. Copy the valid bytes into the output buffer.
+            v.extend_from_slice(&self.bytes[..self.error.valid_up_to()]);
+
+            // SAFETY: This is safe because the only bytes present in the buffer
+            // were validated as UTF-8 by the call to `String::from_utf8` which
+            // produced this `FromUtf8Error`.
+            unsafe { String::from_utf8_unchecked(v) }
+        };
+
+        let iter = self.bytes[self.error.valid_up_to()..].utf8_chunks();
+
+        for chunk in iter {
+            res.push_str(chunk.valid());
+            if !chunk.invalid().is_empty() {
+                res.push_str(REPLACEMENT);
+            }
+        }
+
+        res
     }
 
     /// Returns the bytes that were attempted to convert to a `String`.
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 2afb5dd0d1a..1984cfeefc1 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -416,6 +416,7 @@ impl<T> Vec<T> {
     /// ```
     #[inline]
     #[rustc_const_stable(feature = "const_vec_new", since = "1.39.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "vec_new")]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use]
     pub const fn new() -> Self {
@@ -476,6 +477,7 @@ impl<T> Vec<T> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "vec_with_capacity")]
     pub fn with_capacity(capacity: usize) -> Self {
         Self::with_capacity_in(capacity, Global)
     }
@@ -1545,6 +1547,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// ```
     #[inline]
     #[stable(feature = "vec_as_slice", since = "1.7.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "vec_as_slice")]
     pub fn as_slice(&self) -> &[T] {
         self
     }
@@ -1562,6 +1565,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// ```
     #[inline]
     #[stable(feature = "vec_as_slice", since = "1.7.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "vec_as_mut_slice")]
     pub fn as_mut_slice(&mut self) -> &mut [T] {
         self
     }
@@ -1580,7 +1584,8 @@ impl<T, A: Allocator> Vec<T, A> {
     ///
     /// This method guarantees that for the purpose of the aliasing model, this method
     /// does not materialize a reference to the underlying slice, and thus the returned pointer
-    /// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`].
+    /// will remain valid when mixed with other calls to [`as_ptr`], [`as_mut_ptr`],
+    /// and [`as_non_null`].
     /// Note that calling other methods that materialize mutable references to the slice,
     /// or mutable references to specific elements you are planning on accessing through this pointer,
     /// as well as writing to those elements, may still invalidate this pointer.
@@ -1617,6 +1622,7 @@ impl<T, A: Allocator> Vec<T, A> {
     ///
     /// [`as_mut_ptr`]: Vec::as_mut_ptr
     /// [`as_ptr`]: Vec::as_ptr
+    /// [`as_non_null`]: Vec::as_non_null
     #[stable(feature = "vec_as_ptr", since = "1.37.0")]
     #[rustc_never_returns_null_ptr]
     #[inline]
@@ -1636,7 +1642,8 @@ impl<T, A: Allocator> Vec<T, A> {
     ///
     /// This method guarantees that for the purpose of the aliasing model, this method
     /// does not materialize a reference to the underlying slice, and thus the returned pointer
-    /// will remain valid when mixed with other calls to [`as_ptr`] and [`as_mut_ptr`].
+    /// will remain valid when mixed with other calls to [`as_ptr`], [`as_mut_ptr`],
+    /// and [`as_non_null`].
     /// Note that calling other methods that materialize references to the slice,
     /// or references to specific elements you are planning on accessing through this pointer,
     /// may still invalidate this pointer.
@@ -1676,6 +1683,7 @@ impl<T, A: Allocator> Vec<T, A> {
     ///
     /// [`as_mut_ptr`]: Vec::as_mut_ptr
     /// [`as_ptr`]: Vec::as_ptr
+    /// [`as_non_null`]: Vec::as_non_null
     #[stable(feature = "vec_as_ptr", since = "1.37.0")]
     #[rustc_never_returns_null_ptr]
     #[inline]
@@ -1685,6 +1693,69 @@ impl<T, A: Allocator> Vec<T, A> {
         self.buf.ptr()
     }
 
+    /// Returns a `NonNull` pointer to the vector's buffer, or a dangling
+    /// `NonNull` pointer valid for zero sized reads if the vector didn't allocate.
+    ///
+    /// The caller must ensure that the vector outlives the pointer this
+    /// function returns, or else it will end up dangling.
+    /// Modifying the vector may cause its buffer to be reallocated,
+    /// which would also make any pointers to it invalid.
+    ///
+    /// This method guarantees that for the purpose of the aliasing model, this method
+    /// does not materialize a reference to the underlying slice, and thus the returned pointer
+    /// will remain valid when mixed with other calls to [`as_ptr`], [`as_mut_ptr`],
+    /// and [`as_non_null`].
+    /// Note that calling other methods that materialize references to the slice,
+    /// or references to specific elements you are planning on accessing through this pointer,
+    /// may still invalidate this pointer.
+    /// See the second example below for how this guarantee can be used.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(box_vec_non_null)]
+    ///
+    /// // Allocate vector big enough for 4 elements.
+    /// let size = 4;
+    /// let mut x: Vec<i32> = Vec::with_capacity(size);
+    /// let x_ptr = x.as_non_null();
+    ///
+    /// // Initialize elements via raw pointer writes, then set length.
+    /// unsafe {
+    ///     for i in 0..size {
+    ///         x_ptr.add(i).write(i as i32);
+    ///     }
+    ///     x.set_len(size);
+    /// }
+    /// assert_eq!(&*x, &[0, 1, 2, 3]);
+    /// ```
+    ///
+    /// Due to the aliasing guarantee, the following code is legal:
+    ///
+    /// ```rust
+    /// #![feature(box_vec_non_null)]
+    ///
+    /// unsafe {
+    ///     let mut v = vec![0];
+    ///     let ptr1 = v.as_non_null();
+    ///     ptr1.write(1);
+    ///     let ptr2 = v.as_non_null();
+    ///     ptr2.write(2);
+    ///     // Notably, the write to `ptr2` did *not* invalidate `ptr1`:
+    ///     ptr1.write(3);
+    /// }
+    /// ```
+    ///
+    /// [`as_mut_ptr`]: Vec::as_mut_ptr
+    /// [`as_ptr`]: Vec::as_ptr
+    /// [`as_non_null`]: Vec::as_non_null
+    #[unstable(feature = "box_vec_non_null", reason = "new API", issue = "130364")]
+    #[inline]
+    pub fn as_non_null(&mut self) -> NonNull<T> {
+        // SAFETY: A `Vec` always has a non-null pointer.
+        unsafe { NonNull::new_unchecked(self.as_mut_ptr()) }
+    }
+
     /// Returns a reference to the underlying allocator.
     #[unstable(feature = "allocator_api", issue = "32838")]
     #[inline]
@@ -2380,6 +2451,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// Takes *O*(1) time.
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "vec_pop")]
     pub fn pop(&mut self) -> Option<T> {
         if self.len == 0 {
             None
@@ -2573,6 +2645,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// assert!(!v.is_empty());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "vec_is_empty")]
     pub fn is_empty(&self) -> bool {
         self.len() == 0
     }
@@ -3044,6 +3117,7 @@ impl<T: PartialEq, A: Allocator> Vec<T, A> {
 #[doc(hidden)]
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "vec_from_elem")]
 pub fn from_elem<T: Clone>(elem: T, n: usize) -> Vec<T> {
     <T as SpecFromElem>::from_elem(elem, n, Global)
 }
diff --git a/library/alloc/tests/fmt.rs b/library/alloc/tests/fmt.rs
index ce24a40f4c0..c13074c53b7 100644
--- a/library/alloc/tests/fmt.rs
+++ b/library/alloc/tests/fmt.rs
@@ -1,4 +1,6 @@
 #![deny(warnings)]
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
 
 use std::cell::RefCell;
 use std::fmt::{self, Write};
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index ffc9a233b66..1d07a7690da 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -28,6 +28,7 @@
 #![feature(iter_next_chunk)]
 #![feature(round_char_boundary)]
 #![feature(slice_partition_dedup)]
+#![feature(string_from_utf8_lossy_owned)]
 #![feature(string_remove_matches)]
 #![feature(const_btree_len)]
 #![feature(const_trait_impl)]
diff --git a/library/alloc/tests/string.rs b/library/alloc/tests/string.rs
index dc03c4860e8..d996c55f946 100644
--- a/library/alloc/tests/string.rs
+++ b/library/alloc/tests/string.rs
@@ -115,6 +115,43 @@ fn test_from_utf8_lossy() {
 }
 
 #[test]
+fn test_fromutf8error_into_lossy() {
+    fn func(input: &[u8]) -> String {
+        String::from_utf8(input.to_owned()).unwrap_or_else(|e| e.into_utf8_lossy())
+    }
+
+    let xs = b"hello";
+    let ys = "hello".to_owned();
+    assert_eq!(func(xs), ys);
+
+    let xs = "ศไทย中华Việt Nam".as_bytes();
+    let ys = "ศไทย中华Việt Nam".to_owned();
+    assert_eq!(func(xs), ys);
+
+    let xs = b"Hello\xC2 There\xFF Goodbye";
+    assert_eq!(func(xs), "Hello\u{FFFD} There\u{FFFD} Goodbye".to_owned());
+
+    let xs = b"Hello\xC0\x80 There\xE6\x83 Goodbye";
+    assert_eq!(func(xs), "Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye".to_owned());
+
+    let xs = b"\xF5foo\xF5\x80bar";
+    assert_eq!(func(xs), "\u{FFFD}foo\u{FFFD}\u{FFFD}bar".to_owned());
+
+    let xs = b"\xF1foo\xF1\x80bar\xF1\x80\x80baz";
+    assert_eq!(func(xs), "\u{FFFD}foo\u{FFFD}bar\u{FFFD}baz".to_owned());
+
+    let xs = b"\xF4foo\xF4\x80bar\xF4\xBFbaz";
+    assert_eq!(func(xs), "\u{FFFD}foo\u{FFFD}bar\u{FFFD}\u{FFFD}baz".to_owned());
+
+    let xs = b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar";
+    assert_eq!(func(xs), "\u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}foo\u{10000}bar".to_owned());
+
+    // surrogates
+    let xs = b"\xED\xA0\x80foo\xED\xBF\xBFbar";
+    assert_eq!(func(xs), "\u{FFFD}\u{FFFD}\u{FFFD}foo\u{FFFD}\u{FFFD}\u{FFFD}bar".to_owned());
+}
+
+#[test]
 fn test_from_utf16() {
     let pairs = [
         (
diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs
index 3722fb06a6a..cf2ca4f0d65 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloc/tests/vec.rs
@@ -1,3 +1,6 @@
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
 use core::alloc::{Allocator, Layout};
 use core::num::NonZero;
 use core::ptr::NonNull;
@@ -1284,6 +1287,8 @@ fn test_from_iter_specialization_panic_during_iteration_drops() {
 
 #[test]
 #[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#[cfg_attr(not(bootstrap), allow(static_mut_refs))]
 fn test_from_iter_specialization_panic_during_drop_doesnt_leak() {
     static mut DROP_COUNTER_OLD: [usize; 5] = [0; 5];
     static mut DROP_COUNTER_NEW: [usize; 2] = [0; 2];
diff --git a/library/alloc/tests/vec_deque.rs b/library/alloc/tests/vec_deque.rs
index f32ba8d5aa4..0891d99fe66 100644
--- a/library/alloc/tests/vec_deque.rs
+++ b/library/alloc/tests/vec_deque.rs
@@ -1,3 +1,6 @@
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
 use core::num::NonZero;
 use std::assert_matches::assert_matches;
 use std::collections::vec_deque::Drain;
diff --git a/library/core/src/bool.rs b/library/core/src/bool.rs
index 03cdff9b13b..58a870d2e07 100644
--- a/library/core/src/bool.rs
+++ b/library/core/src/bool.rs
@@ -55,6 +55,7 @@ impl bool {
     /// assert_eq!(a, 1);
     /// ```
     #[stable(feature = "lazy_bool_to_option", since = "1.50.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "bool_then")]
     #[inline]
     pub fn then<T, F: FnOnce() -> T>(self, f: F) -> Option<T> {
         if self { Some(f()) } else { None }
diff --git a/library/core/src/cell/lazy.rs b/library/core/src/cell/lazy.rs
index 6ec1d2a33be..5bc13779af9 100644
--- a/library/core/src/cell/lazy.rs
+++ b/library/core/src/cell/lazy.rs
@@ -1,4 +1,5 @@
 use super::UnsafeCell;
+use crate::hint::unreachable_unchecked;
 use crate::ops::Deref;
 use crate::{fmt, mem};
 
@@ -82,7 +83,7 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
         match this.state.into_inner() {
             State::Init(data) => Ok(data),
             State::Uninit(f) => Err(f),
-            State::Poisoned => panic!("LazyCell instance has previously been poisoned"),
+            State::Poisoned => panic_poisoned(),
         }
     }
 
@@ -114,7 +115,72 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
             State::Init(data) => data,
             // SAFETY: The state is uninitialized.
             State::Uninit(_) => unsafe { LazyCell::really_init(this) },
-            State::Poisoned => panic!("LazyCell has previously been poisoned"),
+            State::Poisoned => panic_poisoned(),
+        }
+    }
+
+    /// Forces the evaluation of this lazy value and returns a mutable reference to
+    /// the result.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(lazy_get)]
+    /// use std::cell::LazyCell;
+    ///
+    /// let mut lazy = LazyCell::new(|| 92);
+    ///
+    /// let p = LazyCell::force_mut(&mut lazy);
+    /// assert_eq!(*p, 92);
+    /// *p = 44;
+    /// assert_eq!(*lazy, 44);
+    /// ```
+    #[inline]
+    #[unstable(feature = "lazy_get", issue = "129333")]
+    pub fn force_mut(this: &mut LazyCell<T, F>) -> &mut T {
+        #[cold]
+        /// # Safety
+        /// May only be called when the state is `Uninit`.
+        unsafe fn really_init_mut<T, F: FnOnce() -> T>(state: &mut State<T, F>) -> &mut T {
+            // INVARIANT: Always valid, but the value may not be dropped.
+            struct PoisonOnPanic<T, F>(*mut State<T, F>);
+            impl<T, F> Drop for PoisonOnPanic<T, F> {
+                #[inline]
+                fn drop(&mut self) {
+                    // SAFETY: Invariant states it is valid, and we don't drop the old value.
+                    unsafe {
+                        self.0.write(State::Poisoned);
+                    }
+                }
+            }
+
+            let State::Uninit(f) = state else {
+                // `unreachable!()` here won't optimize out because the function is cold.
+                // SAFETY: Precondition.
+                unsafe { unreachable_unchecked() };
+            };
+            // SAFETY: We never drop the state after we read `f`, and we write a valid value back
+            // in any case, panic or success. `f` can't access the `LazyCell` because it is mutably
+            // borrowed.
+            let f = unsafe { core::ptr::read(f) };
+            // INVARIANT: Initiated from mutable reference, don't drop because we read it.
+            let guard = PoisonOnPanic(state);
+            let data = f();
+            // SAFETY: `PoisonOnPanic` invariant, and we don't drop the old value.
+            unsafe {
+                core::ptr::write(guard.0, State::Init(data));
+            }
+            core::mem::forget(guard);
+            let State::Init(data) = state else { unreachable!() };
+            data
+        }
+
+        let state = this.state.get_mut();
+        match state {
+            State::Init(data) => data,
+            // SAFETY: `state` is `Uninit`.
+            State::Uninit(_) => unsafe { really_init_mut(state) },
+            State::Poisoned => panic_poisoned(),
         }
     }
 
@@ -152,13 +218,55 @@ impl<T, F: FnOnce() -> T> LazyCell<T, F> {
 }
 
 impl<T, F> LazyCell<T, F> {
+    /// Returns a reference to the value if initialized, or `None` if not.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(lazy_get)]
+    ///
+    /// use std::cell::LazyCell;
+    ///
+    /// let mut lazy = LazyCell::new(|| 92);
+    ///
+    /// assert_eq!(LazyCell::get_mut(&mut lazy), None);
+    /// let _ = LazyCell::force(&lazy);
+    /// *LazyCell::get_mut(&mut lazy).unwrap() = 44;
+    /// assert_eq!(*lazy, 44);
+    /// ```
     #[inline]
-    fn get(&self) -> Option<&T> {
+    #[unstable(feature = "lazy_get", issue = "129333")]
+    pub fn get_mut(this: &mut LazyCell<T, F>) -> Option<&mut T> {
+        let state = this.state.get_mut();
+        match state {
+            State::Init(data) => Some(data),
+            _ => None,
+        }
+    }
+
+    /// Returns a mutable reference to the value if initialized, or `None` if not.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(lazy_get)]
+    ///
+    /// use std::cell::LazyCell;
+    ///
+    /// let lazy = LazyCell::new(|| 92);
+    ///
+    /// assert_eq!(LazyCell::get(&lazy), None);
+    /// let _ = LazyCell::force(&lazy);
+    /// assert_eq!(LazyCell::get(&lazy), Some(&92));
+    /// ```
+    #[inline]
+    #[unstable(feature = "lazy_get", issue = "129333")]
+    pub fn get(this: &LazyCell<T, F>) -> Option<&T> {
         // SAFETY:
         // This is sound for the same reason as in `force`: once the state is
         // initialized, it will not be mutably accessed again, so this reference
         // will stay valid for the duration of the borrow to `self`.
-        let state = unsafe { &*self.state.get() };
+        let state = unsafe { &*this.state.get() };
         match state {
             State::Init(data) => Some(data),
             _ => None,
@@ -188,10 +296,16 @@ impl<T: Default> Default for LazyCell<T> {
 impl<T: fmt::Debug, F> fmt::Debug for LazyCell<T, F> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let mut d = f.debug_tuple("LazyCell");
-        match self.get() {
+        match LazyCell::get(self) {
             Some(data) => d.field(data),
             None => d.field(&format_args!("<uninit>")),
         };
         d.finish()
     }
 }
+
+#[cold]
+#[inline(never)]
+fn panic_poisoned() -> ! {
+    panic!("LazyCell instance has previously been poisoned")
+}
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 9d9a3b5132c..7d64b382501 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -1,6 +1,7 @@
 //! impl char {}
 
 use super::*;
+use crate::intrinsics::const_eval_select;
 use crate::slice;
 use crate::str::from_utf8_unchecked_mut;
 use crate::unicode::printable::is_printable;
@@ -672,8 +673,9 @@ impl char {
     /// 'ß'.encode_utf8(&mut b);
     /// ```
     #[stable(feature = "unicode_encode_char", since = "1.15.0")]
+    #[rustc_const_unstable(feature = "const_char_encode_utf8", issue = "130512")]
     #[inline]
-    pub fn encode_utf8(self, dst: &mut [u8]) -> &mut str {
+    pub const fn encode_utf8(self, dst: &mut [u8]) -> &mut str {
         // SAFETY: `char` is not a surrogate, so this is valid UTF-8.
         unsafe { from_utf8_unchecked_mut(encode_utf8_raw(self as u32, dst)) }
     }
@@ -1737,14 +1739,11 @@ impl EscapeDebugExtArgs {
 
 #[inline]
 const fn len_utf8(code: u32) -> usize {
-    if code < MAX_ONE_B {
-        1
-    } else if code < MAX_TWO_B {
-        2
-    } else if code < MAX_THREE_B {
-        3
-    } else {
-        4
+    match code {
+        ..MAX_ONE_B => 1,
+        ..MAX_TWO_B => 2,
+        ..MAX_THREE_B => 3,
+        _ => 4,
     }
 }
 
@@ -1762,11 +1761,21 @@ const fn len_utf8(code: u32) -> usize {
 /// Panics if the buffer is not large enough.
 /// A buffer of length four is large enough to encode any `char`.
 #[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")]
+#[rustc_const_unstable(feature = "const_char_encode_utf8", issue = "130512")]
 #[doc(hidden)]
 #[inline]
-pub fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] {
+pub const fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] {
+    const fn panic_at_const(_code: u32, _len: usize, _dst_len: usize) {
+        // Note that we cannot format in constant expressions.
+        panic!("encode_utf8: buffer does not have enough bytes to encode code point");
+    }
+    fn panic_at_rt(code: u32, len: usize, dst_len: usize) {
+        panic!(
+            "encode_utf8: need {len} bytes to encode U+{code:04X} but buffer has just {dst_len}",
+        );
+    }
     let len = len_utf8(code);
-    match (len, &mut dst[..]) {
+    match (len, &mut *dst) {
         (1, [a, ..]) => {
             *a = code as u8;
         }
@@ -1785,14 +1794,11 @@ pub fn encode_utf8_raw(code: u32, dst: &mut [u8]) -> &mut [u8] {
             *c = (code >> 6 & 0x3F) as u8 | TAG_CONT;
             *d = (code & 0x3F) as u8 | TAG_CONT;
         }
-        _ => panic!(
-            "encode_utf8: need {} bytes to encode U+{:X}, but the buffer has {}",
-            len,
-            code,
-            dst.len(),
-        ),
+        // FIXME(const-hack): We would prefer to have streamlined panics when formatters become const-friendly.
+        _ => const_eval_select((code, len, dst.len()), panic_at_const, panic_at_rt),
     };
-    &mut dst[..len]
+    // SAFETY: `<&mut [u8]>::as_mut_ptr` is guaranteed to return a valid pointer and `len` has been tested to be within bounds.
+    unsafe { slice::from_raw_parts_mut(dst.as_mut_ptr(), len) }
 }
 
 /// Encodes a raw u32 value as UTF-16 into the provided `u16` buffer,
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index 8352486ad41..f53beeb007d 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -876,6 +876,7 @@ pub trait Iterator {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_do_not_const_check]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "iter_filter")]
     fn filter<P>(self, predicate: P) -> Filter<Self, P>
     where
         Self: Sized,
@@ -3412,6 +3413,7 @@ pub trait Iterator {
     /// ```
     #[stable(feature = "iter_copied", since = "1.36.0")]
     #[rustc_do_not_const_check]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "iter_copied")]
     fn copied<'a, T: 'a>(self) -> Copied<Self>
     where
         Self: Sized + Iterator<Item = &'a T>,
@@ -3460,6 +3462,7 @@ pub trait Iterator {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_do_not_const_check]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "iter_cloned")]
     fn cloned<'a, T: 'a>(self) -> Cloned<Self>
     where
         Self: Sized + Iterator<Item = &'a T>,
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 058dcf34532..8826bf52b41 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -119,6 +119,7 @@
 #![feature(const_bigint_helper_methods)]
 #![feature(const_black_box)]
 #![feature(const_cell_into_inner)]
+#![feature(const_char_encode_utf8)]
 #![feature(const_eval_select)]
 #![feature(const_exact_div)]
 #![feature(const_float_classify)]
@@ -131,7 +132,6 @@
 #![feature(const_ipv4)]
 #![feature(const_ipv6)]
 #![feature(const_likely)]
-#![feature(const_maybe_uninit_as_mut_ptr)]
 #![feature(const_maybe_uninit_assume_init)]
 #![feature(const_nonnull_new)]
 #![feature(const_num_midpoint)]
@@ -170,6 +170,7 @@
 #![feature(is_ascii_octdigit)]
 #![feature(is_val_statically_known)]
 #![feature(isqrt)]
+#![feature(lazy_get)]
 #![feature(link_cfg)]
 #![feature(offset_of_enum)]
 #![feature(panic_internals)]
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index 0154caa7c24..c67796ad3db 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -393,7 +393,6 @@ impl<T> MaybeUninit<T> {
     // These are OK to allow since we do not leak &mut to user-visible API
     #[rustc_allow_const_fn_unstable(const_mut_refs)]
     #[rustc_allow_const_fn_unstable(const_ptr_write)]
-    #[rustc_allow_const_fn_unstable(const_maybe_uninit_as_mut_ptr)]
     #[rustc_const_stable(feature = "const_maybe_uninit_zeroed", since = "1.75.0")]
     pub const fn zeroed() -> MaybeUninit<T> {
         let mut u = MaybeUninit::<T>::uninit();
@@ -570,7 +569,11 @@ impl<T> MaybeUninit<T> {
     /// (Notice that the rules around references to uninitialized data are not finalized yet, but
     /// until they are, it is advisable to avoid them.)
     #[stable(feature = "maybe_uninit", since = "1.36.0")]
-    #[rustc_const_unstable(feature = "const_maybe_uninit_as_mut_ptr", issue = "75251")]
+    #[rustc_const_stable(
+        feature = "const_maybe_uninit_as_mut_ptr",
+        since = "CURRENT_RUSTC_VERSION"
+    )]
+    #[cfg_attr(bootstrap, rustc_allow_const_fn_unstable(const_mut_refs))]
     #[inline(always)]
     pub const fn as_mut_ptr(&mut self) -> *mut T {
         // `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer.
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index 4c2a4ee3b32..d0eb6bb3f28 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -415,6 +415,7 @@ impl f32 {
     /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
     /// [`MANTISSA_DIGITS`]: f32::MANTISSA_DIGITS
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "f32_epsilon")]
     pub const EPSILON: f32 = 1.19209290e-07_f32;
 
     /// Smallest finite `f32` value.
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index 87fb5fe7ebe..4bc275ad147 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -414,6 +414,7 @@ impl f64 {
     /// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
     /// [`MANTISSA_DIGITS`]: f64::MANTISSA_DIGITS
     #[stable(feature = "assoc_int_consts", since = "1.43.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "f64_epsilon")]
     pub const EPSILON: f64 = 2.2204460492503131e-16_f64;
 
     /// Smallest finite `f64` value.
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index dca644ebef4..15de4fa15c4 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -23,6 +23,16 @@ macro_rules! unlikely {
     };
 }
 
+// Use this when the generated code should differ between signed and unsigned types.
+macro_rules! sign_dependent_expr {
+    (signed ? if signed { $signed_case:expr } if unsigned { $unsigned_case:expr } ) => {
+        $signed_case
+    };
+    (unsigned ? if signed { $signed_case:expr } if unsigned { $unsigned_case:expr } ) => {
+        $unsigned_case
+    };
+}
+
 // All these modules are technically private and only exposed for coretests:
 #[cfg(not(no_fp_fmt_parse))]
 pub mod bignum;
@@ -1410,15 +1420,25 @@ const fn from_str_radix_panic(radix: u32) {
 }
 
 macro_rules! from_str_radix {
-    ($($int_ty:ty)+) => {$(
+    ($signedness:ident $($int_ty:ty)+) => {$(
         impl $int_ty {
             /// Converts a string slice in a given base to an integer.
             ///
-            /// The string is expected to be an optional `+` sign
-            /// followed by digits.
-            /// Leading and trailing whitespace represent an error.
-            /// Digits are a subset of these characters, depending on `radix`:
+            /// The string is expected to be an optional
+            #[doc = sign_dependent_expr!{
+                $signedness ?
+                if signed {
+                    " `+` or `-` "
+                }
+                if unsigned {
+                    " `+` "
+                }
+            }]
+            /// sign followed by only digits. Leading and trailing non-digit characters (including
+            /// whitespace) represent an error. Underscores (which are accepted in rust literals)
+            /// also represent an error.
             ///
+            /// Digits are a subset of these characters, depending on `radix`:
             /// * `0-9`
             /// * `a-z`
             /// * `A-Z`
@@ -1430,10 +1450,13 @@ macro_rules! from_str_radix {
             /// # Examples
             ///
             /// Basic usage:
-            ///
             /// ```
             #[doc = concat!("assert_eq!(", stringify!($int_ty), "::from_str_radix(\"A\", 16), Ok(10));")]
             /// ```
+            /// Trailing space returns error:
+            /// ```
+            #[doc = concat!("assert!(", stringify!($int_ty), "::from_str_radix(\"1 \", 10).is_err());")]
+            /// ```
             #[stable(feature = "rust1", since = "1.0.0")]
             #[rustc_const_stable(feature = "const_int_from_str", since = "1.82.0")]
             pub const fn from_str_radix(src: &str, radix: u32) -> Result<$int_ty, ParseIntError> {
@@ -1535,20 +1558,31 @@ macro_rules! from_str_radix {
     )+}
 }
 
-from_str_radix! { i8 u8 i16 u16 i32 u32 i64 u64 i128 u128 }
+from_str_radix! { unsigned u8 u16 u32 u64 u128 }
+from_str_radix! { signed i8 i16 i32 i64 i128 }
 
 // Re-use the relevant implementation of from_str_radix for isize and usize to avoid outputting two
 // identical functions.
 macro_rules! from_str_radix_size_impl {
-    ($($t:ident $size:ty),*) => {$(
+    ($($signedness:ident $t:ident $size:ty),*) => {$(
     impl $size {
         /// Converts a string slice in a given base to an integer.
         ///
-        /// The string is expected to be an optional `+` sign
-        /// followed by digits.
-        /// Leading and trailing whitespace represent an error.
-        /// Digits are a subset of these characters, depending on `radix`:
+        /// The string is expected to be an optional
+        #[doc = sign_dependent_expr!{
+            $signedness ?
+            if signed {
+                " `+` or `-` "
+            }
+            if unsigned {
+                " `+` "
+            }
+        }]
+        /// sign followed by only digits. Leading and trailing non-digit characters (including
+        /// whitespace) represent an error. Underscores (which are accepted in rust literals)
+        /// also represent an error.
         ///
+        /// Digits are a subset of these characters, depending on `radix`:
         /// * `0-9`
         /// * `a-z`
         /// * `A-Z`
@@ -1560,10 +1594,13 @@ macro_rules! from_str_radix_size_impl {
         /// # Examples
         ///
         /// Basic usage:
-        ///
         /// ```
         #[doc = concat!("assert_eq!(", stringify!($size), "::from_str_radix(\"A\", 16), Ok(10));")]
         /// ```
+        /// Trailing space returns error:
+        /// ```
+        #[doc = concat!("assert!(", stringify!($size), "::from_str_radix(\"1 \", 10).is_err());")]
+        /// ```
         #[stable(feature = "rust1", since = "1.0.0")]
         #[rustc_const_stable(feature = "const_int_from_str", since = "1.82.0")]
         pub const fn from_str_radix(src: &str, radix: u32) -> Result<$size, ParseIntError> {
@@ -1576,8 +1613,8 @@ macro_rules! from_str_radix_size_impl {
 }
 
 #[cfg(target_pointer_width = "16")]
-from_str_radix_size_impl! { i16 isize, u16 usize }
+from_str_radix_size_impl! { signed i16 isize, unsigned u16 usize }
 #[cfg(target_pointer_width = "32")]
-from_str_radix_size_impl! { i32 isize, u32 usize }
+from_str_radix_size_impl! { signed i32 isize, unsigned u32 usize }
 #[cfg(target_pointer_width = "64")]
-from_str_radix_size_impl! { i64 isize, u64 usize }
+from_str_radix_size_impl! { signed i64 isize, unsigned u64 usize }
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 8b888f12da0..e5c9a7e086a 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -1972,16 +1972,6 @@ macro_rules! nonzero_integer_signedness_dependent_methods {
     };
 }
 
-// Use this when the generated code should differ between signed and unsigned types.
-macro_rules! sign_dependent_expr {
-    (signed ? if signed { $signed_case:expr } if unsigned { $unsigned_case:expr } ) => {
-        $signed_case
-    };
-    (unsigned ? if signed { $signed_case:expr } if unsigned { $unsigned_case:expr } ) => {
-        $unsigned_case
-    };
-}
-
 nonzero_integer! {
     Self = NonZeroU8,
     Primitive = unsigned u8,
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 265f056dc87..5ba13969605 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -923,6 +923,7 @@ impl<T> Option<T> {
     #[inline]
     #[track_caller]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "option_expect")]
     #[rustc_const_unstable(feature = "const_option", issue = "67441")]
     pub const fn expect(self, msg: &str) -> T {
         match self {
@@ -960,6 +961,7 @@ impl<T> Option<T> {
     #[inline(always)]
     #[track_caller]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "option_unwrap")]
     #[rustc_const_unstable(feature = "const_option", issue = "67441")]
     pub const fn unwrap(self) -> T {
         match self {
diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs
index e4d0c897b65..af2c83b5460 100644
--- a/library/core/src/panic/panic_info.rs
+++ b/library/core/src/panic/panic_info.rs
@@ -12,7 +12,7 @@ use crate::panic::Location;
 #[stable(feature = "panic_hooks", since = "1.10.0")]
 #[derive(Debug)]
 pub struct PanicInfo<'a> {
-    message: fmt::Arguments<'a>,
+    message: &'a fmt::Arguments<'a>,
     location: &'a Location<'a>,
     can_unwind: bool,
     force_no_backtrace: bool,
@@ -26,13 +26,13 @@ pub struct PanicInfo<'a> {
 /// See [`PanicInfo::message`].
 #[stable(feature = "panic_info_message", since = "1.81.0")]
 pub struct PanicMessage<'a> {
-    message: fmt::Arguments<'a>,
+    message: &'a fmt::Arguments<'a>,
 }
 
 impl<'a> PanicInfo<'a> {
     #[inline]
     pub(crate) fn new(
-        message: fmt::Arguments<'a>,
+        message: &'a fmt::Arguments<'a>,
         location: &'a Location<'a>,
         can_unwind: bool,
         force_no_backtrace: bool,
@@ -146,7 +146,7 @@ impl Display for PanicInfo<'_> {
         formatter.write_str("panicked at ")?;
         self.location.fmt(formatter)?;
         formatter.write_str(":\n")?;
-        formatter.write_fmt(self.message)?;
+        formatter.write_fmt(*self.message)?;
         Ok(())
     }
 }
@@ -177,7 +177,7 @@ impl<'a> PanicMessage<'a> {
 impl Display for PanicMessage<'_> {
     #[inline]
     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        formatter.write_fmt(self.message)
+        formatter.write_fmt(*self.message)
     }
 }
 
@@ -185,6 +185,6 @@ impl Display for PanicMessage<'_> {
 impl fmt::Debug for PanicMessage<'_> {
     #[inline]
     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        formatter.write_fmt(self.message)
+        formatter.write_fmt(*self.message)
     }
 }
diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs
index e4a62304087..7420579e3ce 100644
--- a/library/core/src/panicking.rs
+++ b/library/core/src/panicking.rs
@@ -64,7 +64,7 @@ pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! {
     }
 
     let pi = PanicInfo::new(
-        fmt,
+        &fmt,
         Location::caller(),
         /* can_unwind */ true,
         /* force_no_backtrace */ false,
@@ -102,7 +102,7 @@ pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: boo
 
         // PanicInfo with the `can_unwind` flag set to false forces an abort.
         let pi = PanicInfo::new(
-            fmt,
+            &fmt,
             Location::caller(),
             /* can_unwind */ false,
             force_no_backtrace,
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 5451e45f6c8..962da6643dd 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -1761,6 +1761,8 @@ mod prim_ref {}
 /// - `i32` is ABI-compatible with `NonZero<i32>`, and similar for all other integer types.
 /// - If `T` is guaranteed to be subject to the [null pointer
 ///   optimization](option/index.html#representation), then `T` and `Option<T>` are ABI-compatible.
+///   Furthermore, if `U` satisfies the requirements [outlined here](result/index.html#representation),
+///   then `T` and `Result<T, U>` and `Result<U, T>` are all ABI-compatible.
 ///
 /// Furthermore, ABI compatibility satisfies the following general properties:
 ///
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index 02f6f783b51..9edd58259ba 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -653,6 +653,7 @@ impl<T, E> Result<T, E> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "result_ok_method")]
     pub fn ok(self) -> Option<T> {
         match self {
             Ok(x) => Some(x),
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index b1948ce69c7..cdcca0eee88 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -1010,6 +1010,7 @@ impl<T> [T] {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "slice_iter")]
     pub fn iter(&self) -> Iter<'_, T> {
         Iter::new(self)
     }
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index e947686487e..712bf011c27 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -134,6 +134,7 @@ impl str {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_stable(feature = "const_str_len", since = "1.39.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "str_len")]
     #[must_use]
     #[inline]
     pub const fn len(&self) -> usize {
@@ -832,6 +833,7 @@ impl str {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "str_chars")]
     pub fn chars(&self) -> Chars<'_> {
         Chars { iter: self.as_bytes().iter() }
     }
@@ -1156,6 +1158,7 @@ impl str {
     /// assert!(bananas.starts_with(&['a', 'b', 'c', 'd']));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "str_starts_with")]
     pub fn starts_with<P: Pattern>(&self, pat: P) -> bool {
         pat.is_prefix_of(self)
     }
@@ -1180,6 +1183,7 @@ impl str {
     /// assert!(!bananas.ends_with("nana"));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "str_ends_with")]
     pub fn ends_with<P: Pattern>(&self, pat: P) -> bool
     where
         for<'a> P::Searcher<'a>: ReverseSearcher<'a>,
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index 5e559ad8d2c..a5103499c8a 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -414,6 +414,7 @@ impl<'a> ContextBuilder<'a> {
 /// [`Wake`]: ../../alloc/task/trait.Wake.html
 #[repr(transparent)]
 #[stable(feature = "futures_api", since = "1.36.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "Waker")]
 pub struct Waker {
     waker: RawWaker,
 }
diff --git a/library/core/tests/atomic.rs b/library/core/tests/atomic.rs
index 0d1c72a6892..2bdaeb3845a 100644
--- a/library/core/tests/atomic.rs
+++ b/library/core/tests/atomic.rs
@@ -228,6 +228,8 @@ fn static_init() {
 }
 
 #[test]
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#[cfg_attr(not(bootstrap), allow(static_mut_refs))]
 fn atomic_access_bool() {
     static mut ATOMIC: AtomicBool = AtomicBool::new(false);
 
diff --git a/library/core/tests/lazy.rs b/library/core/tests/lazy.rs
index a3b89f15b3f..711511eaf4a 100644
--- a/library/core/tests/lazy.rs
+++ b/library/core/tests/lazy.rs
@@ -114,6 +114,27 @@ fn lazy_type_inference() {
 }
 
 #[test]
+#[should_panic = "LazyCell instance has previously been poisoned"]
+fn lazy_force_mut_panic() {
+    let mut lazy = LazyCell::<String>::new(|| panic!());
+    std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
+        let _ = LazyCell::force_mut(&mut lazy);
+    }))
+    .unwrap_err();
+    let _ = &*lazy;
+}
+
+#[test]
+fn lazy_force_mut() {
+    let s = "abc".to_owned();
+    let mut lazy = LazyCell::new(move || s);
+    LazyCell::force_mut(&mut lazy);
+    let p = LazyCell::force_mut(&mut lazy);
+    p.clear();
+    LazyCell::force_mut(&mut lazy);
+}
+
+#[test]
 fn aliasing_in_get() {
     let x = OnceCell::new();
     x.set(42).unwrap();
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 948ea9bc098..5315ac856f6 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -26,7 +26,6 @@
 #![feature(const_ipv4)]
 #![feature(const_ipv6)]
 #![feature(const_likely)]
-#![feature(const_maybe_uninit_as_mut_ptr)]
 #![feature(const_nonnull_new)]
 #![feature(const_option)]
 #![feature(const_option_ext)]
@@ -76,6 +75,7 @@
 #![feature(iterator_try_collect)]
 #![feature(iterator_try_reduce)]
 #![feature(layout_for_ptr)]
+#![feature(lazy_get)]
 #![feature(maybe_uninit_fill)]
 #![feature(maybe_uninit_uninit_array_transpose)]
 #![feature(maybe_uninit_write_slice)]
diff --git a/library/core/tests/num/int_macros.rs b/library/core/tests/num/int_macros.rs
index 830a96204ca..6a26bd15a66 100644
--- a/library/core/tests/num/int_macros.rs
+++ b/library/core/tests/num/int_macros.rs
@@ -244,6 +244,8 @@ macro_rules! int_module {
 
             assert_eq!($T::from_str_radix("Z", 35).ok(), None::<$T>);
             assert_eq!($T::from_str_radix("-9", 2).ok(), None::<$T>);
+            assert_eq!($T::from_str_radix("10_0", 10).ok(), None::<$T>);
+            assert_eq!(u32::from_str_radix("-9", 10).ok(), None::<u32>);
         }
 
         #[test]
diff --git a/library/panic_unwind/src/seh.rs b/library/panic_unwind/src/seh.rs
index 070c11926f6..9e74a45a0e2 100644
--- a/library/panic_unwind/src/seh.rs
+++ b/library/panic_unwind/src/seh.rs
@@ -291,6 +291,8 @@ cfg_if::cfg_if! {
    }
 }
 
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#[allow(static_mut_refs)]
 pub unsafe fn panic(data: Box<dyn Any + Send>) -> u32 {
     use core::intrinsics::atomic_store_seqcst;
 
diff --git a/library/proc_macro/src/bridge/buffer.rs b/library/proc_macro/src/bridge/buffer.rs
index 78fcd1999b2..3760749d83a 100644
--- a/library/proc_macro/src/bridge/buffer.rs
+++ b/library/proc_macro/src/bridge/buffer.rs
@@ -119,9 +119,7 @@ impl Write for Buffer {
 }
 
 impl Drop for Buffer {
-    // HACK(nbdd0121): Hack to prevent LLVM < 17.0.4 from misoptimising,
-    // change to `#[inline]` if fixed.
-    #[inline(never)]
+    #[inline]
     fn drop(&mut self) {
         let b = self.take();
         (b.drop)(b);
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 7d21d37f40d..1a18721b15e 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -1037,6 +1037,7 @@ where
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "hashmap_contains_key")]
     pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
     where
         K: Borrow<Q>,
@@ -1100,6 +1101,7 @@ where
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_confusables("push", "append", "put")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "hashmap_insert")]
     pub fn insert(&mut self, k: K, v: V) -> Option<V> {
         self.base.insert(k, v)
     }
@@ -1391,6 +1393,7 @@ where
 /// let iter = map.iter();
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "hashmap_iter_ty")]
 pub struct Iter<'a, K: 'a, V: 'a> {
     base: base::Iter<'a, K, V>,
 }
@@ -1429,6 +1432,7 @@ impl<K: Debug, V: Debug> fmt::Debug for Iter<'_, K, V> {
 /// let iter = map.iter_mut();
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "hashmap_iter_mut_ty")]
 pub struct IterMut<'a, K: 'a, V: 'a> {
     base: base::IterMut<'a, K, V>,
 }
@@ -1489,6 +1493,7 @@ impl<K, V> IntoIter<K, V> {
 /// let iter_keys = map.keys();
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "hashmap_keys_ty")]
 pub struct Keys<'a, K: 'a, V: 'a> {
     inner: Iter<'a, K, V>,
 }
@@ -1527,6 +1532,7 @@ impl<K: Debug, V> fmt::Debug for Keys<'_, K, V> {
 /// let iter_values = map.values();
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "hashmap_values_ty")]
 pub struct Values<'a, K: 'a, V: 'a> {
     inner: Iter<'a, K, V>,
 }
@@ -1565,6 +1571,7 @@ impl<K, V: Debug> fmt::Debug for Values<'_, K, V> {
 /// let iter = map.drain();
 /// ```
 #[stable(feature = "drain", since = "1.6.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "hashmap_drain_ty")]
 pub struct Drain<'a, K: 'a, V: 'a> {
     base: base::Drain<'a, K, V>,
 }
@@ -1622,6 +1629,7 @@ where
 /// let iter_values = map.values_mut();
 /// ```
 #[stable(feature = "map_values_mut", since = "1.10.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "hashmap_values_mut_ty")]
 pub struct ValuesMut<'a, K: 'a, V: 'a> {
     inner: IterMut<'a, K, V>,
 }
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index d611353b0d3..4a113ddea3a 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -187,6 +187,7 @@ impl<T, S> HashSet<T, S> {
     #[inline]
     #[rustc_lint_query_instability]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "hashset_iter")]
     pub fn iter(&self) -> Iter<'_, T> {
         Iter { base: self.base.iter() }
     }
@@ -1270,6 +1271,7 @@ where
 /// let mut iter = a.iter();
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "hashset_iter_ty")]
 pub struct Iter<'a, K: 'a> {
     base: base::Iter<'a, K>,
 }
@@ -1312,6 +1314,7 @@ pub struct IntoIter<K> {
 /// let mut drain = a.drain();
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "hashset_drain_ty")]
 pub struct Drain<'a, K: 'a> {
     base: base::Drain<'a, K>,
 }
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index 99bea676e12..0f905803bb8 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -196,6 +196,7 @@ impl OsString {
     /// let os_str = OsStr::new("foo");
     /// assert_eq!(os_string.as_os_str(), os_str);
     /// ```
+    #[cfg_attr(not(test), rustc_diagnostic_item = "os_string_as_os_str")]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use]
     #[inline]
@@ -918,6 +919,7 @@ impl OsStr {
     #[must_use = "this returns the result of the operation, \
                   without modifying the original"]
     #[inline]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "os_str_to_os_string")]
     pub fn to_os_string(&self) -> OsString {
         OsString { inner: self.inner.to_owned() }
     }
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 6a0d9f47960..55f3b628ce8 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -466,6 +466,7 @@ impl File {
     /// ```
     #[must_use]
     #[stable(feature = "with_options", since = "1.58.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "file_options")]
     pub fn options() -> OpenOptions {
         OpenOptions::new()
     }
@@ -835,7 +836,7 @@ impl Read for &File {
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Write for &File {
-    /// Writes some bytes from the file.
+    /// Writes some bytes to the file.
     ///
     /// See [`Write::write`] docs for more info.
     ///
@@ -1009,6 +1010,7 @@ impl OpenOptions {
     /// let mut options = OpenOptions::new();
     /// let file = options.read(true).open("foo.txt");
     /// ```
+    #[cfg_attr(not(test), rustc_diagnostic_item = "open_options_new")]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use]
     pub fn new() -> Self {
@@ -1989,6 +1991,11 @@ impl AsInner<fs_imp::DirEntry> for DirEntry {
 /// * The file doesn't exist.
 /// * The user lacks permissions to remove the file.
 ///
+/// This function will only ever return an error of kind `NotFound` if the given
+/// path does not exist. Note that the inverse is not true,
+/// ie. if a path does not exist, its removal may fail for a number of reasons,
+/// such as insufficient permissions.
+///
 /// # Examples
 ///
 /// ```no_run
@@ -2446,6 +2453,11 @@ pub fn create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
 /// * The user lacks permissions to remove the directory at the provided `path`.
 /// * The directory isn't empty.
 ///
+/// This function will only ever return an error of kind `NotFound` if the given
+/// path does not exist. Note that the inverse is not true,
+/// ie. if a path does not exist, its removal may fail for a number of reasons,
+/// such as insufficient permissions.
+///
 /// # Examples
 ///
 /// ```no_run
@@ -2471,16 +2483,15 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
 /// # Platform-specific behavior
 ///
 /// This function currently corresponds to `openat`, `fdopendir`, `unlinkat` and `lstat` functions
-/// on Unix (except for macOS before version 10.10 and REDOX) and the `CreateFileW`,
-/// `GetFileInformationByHandleEx`, `SetFileInformationByHandle`, and `NtCreateFile` functions on
-/// Windows. Note that, this [may change in the future][changes].
+/// on Unix (except for REDOX) and the `CreateFileW`, `GetFileInformationByHandleEx`,
+/// `SetFileInformationByHandle`, and `NtCreateFile` functions on Windows. Note that, this
+/// [may change in the future][changes].
 ///
 /// [changes]: io#platform-specific-behavior
 ///
-/// On macOS before version 10.10 and REDOX, as well as when running in Miri for any target, this
-/// function is not protected against time-of-check to time-of-use (TOCTOU) race conditions, and
-/// should not be used in security-sensitive code on those platforms. All other platforms are
-/// protected.
+/// On REDOX, as well as when running in Miri for any target, this function is not protected against
+/// time-of-check to time-of-use (TOCTOU) race conditions, and should not be used in
+/// security-sensitive code on those platforms. All other platforms are protected.
 ///
 /// # Errors
 ///
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 644b294db8d..2a4262b2367 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -2058,6 +2058,7 @@ pub trait Seek {
 /// It is used by the [`Seek`] trait.
 #[derive(Copy, PartialEq, Eq, Clone, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "SeekFrom")]
 pub enum SeekFrom {
     /// Sets the offset to the provided number of bytes.
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index bc5369ddc3d..e4ba5e47613 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -337,6 +337,7 @@
 #![feature(hasher_prefixfree_extras)]
 #![feature(hashmap_internals)]
 #![feature(ip)]
+#![feature(lazy_get)]
 #![feature(maybe_uninit_slice)]
 #![feature(maybe_uninit_write_slice)]
 #![feature(panic_can_unwind)]
diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs
index caf6980afd9..a964db2e0ac 100644
--- a/library/std/src/os/unix/fs.rs
+++ b/library/std/src/os/unix/fs.rs
@@ -334,6 +334,7 @@ pub trait PermissionsExt {
     /// assert_eq!(permissions.mode(), 0o644);
     /// ```
     #[stable(feature = "fs_ext", since = "1.1.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "permissions_from_mode")]
     fn from_mode(mode: u32) -> Self;
 }
 
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index c94df9b5366..aa9f63d915a 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -263,6 +263,7 @@ pub fn is_separator(c: char) -> bool {
 ///
 /// For example, `/` on Unix and `\` on Windows.
 #[stable(feature = "rust1", since = "1.0.0")]
+#[cfg_attr(not(test), rustc_diagnostic_item = "path_main_separator")]
 pub const MAIN_SEPARATOR: char = crate::sys::path::MAIN_SEP;
 
 /// The primary separator of path components for the current platform.
@@ -1226,6 +1227,7 @@ impl PathBuf {
     /// let p = PathBuf::from("/test");
     /// assert_eq!(Path::new("/test"), p.as_path());
     /// ```
+    #[cfg_attr(not(test), rustc_diagnostic_item = "pathbuf_as_path")]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use]
     #[inline]
@@ -2264,6 +2266,7 @@ impl Path {
     #[must_use = "this returns the result of the operation, \
                   without modifying the original"]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "path_to_pathbuf")]
     pub fn to_path_buf(&self) -> PathBuf {
         PathBuf::from(self.inner.to_os_string())
     }
diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs
index 1dfe1dc538b..b05615035d7 100644
--- a/library/std/src/sync/lazy_lock.rs
+++ b/library/std/src/sync/lazy_lock.rs
@@ -119,7 +119,7 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
     pub fn into_inner(mut this: Self) -> Result<T, F> {
         let state = this.once.state();
         match state {
-            ExclusiveState::Poisoned => panic!("LazyLock instance has previously been poisoned"),
+            ExclusiveState::Poisoned => panic_poisoned(),
             state => {
                 let this = ManuallyDrop::new(this);
                 let data = unsafe { ptr::read(&this.data) }.into_inner();
@@ -132,6 +132,60 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
         }
     }
 
+    /// Forces the evaluation of this lazy value and returns a mutable reference to
+    /// the result.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(lazy_get)]
+    /// use std::sync::LazyLock;
+    ///
+    /// let mut lazy = LazyLock::new(|| 92);
+    ///
+    /// let p = LazyLock::force_mut(&mut lazy);
+    /// assert_eq!(*p, 92);
+    /// *p = 44;
+    /// assert_eq!(*lazy, 44);
+    /// ```
+    #[inline]
+    #[unstable(feature = "lazy_get", issue = "129333")]
+    pub fn force_mut(this: &mut LazyLock<T, F>) -> &mut T {
+        #[cold]
+        /// # Safety
+        /// May only be called when the state is `Incomplete`.
+        unsafe fn really_init_mut<T, F: FnOnce() -> T>(this: &mut LazyLock<T, F>) -> &mut T {
+            struct PoisonOnPanic<'a, T, F>(&'a mut LazyLock<T, F>);
+            impl<T, F> Drop for PoisonOnPanic<'_, T, F> {
+                #[inline]
+                fn drop(&mut self) {
+                    self.0.once.set_state(ExclusiveState::Poisoned);
+                }
+            }
+
+            // SAFETY: We always poison if the initializer panics (then we never check the data),
+            // or set the data on success.
+            let f = unsafe { ManuallyDrop::take(&mut this.data.get_mut().f) };
+            // INVARIANT: Initiated from mutable reference, don't drop because we read it.
+            let guard = PoisonOnPanic(this);
+            let data = f();
+            guard.0.data.get_mut().value = ManuallyDrop::new(data);
+            guard.0.once.set_state(ExclusiveState::Complete);
+            core::mem::forget(guard);
+            // SAFETY: We put the value there above.
+            unsafe { &mut this.data.get_mut().value }
+        }
+
+        let state = this.once.state();
+        match state {
+            ExclusiveState::Poisoned => panic_poisoned(),
+            // SAFETY: The `Once` states we completed the initialization.
+            ExclusiveState::Complete => unsafe { &mut this.data.get_mut().value },
+            // SAFETY: The state is `Incomplete`.
+            ExclusiveState::Incomplete => unsafe { really_init_mut(this) },
+        }
+    }
+
     /// Forces the evaluation of this lazy value and returns a reference to
     /// result. This is equivalent to the `Deref` impl, but is explicit.
     ///
@@ -172,13 +226,58 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
 }
 
 impl<T, F> LazyLock<T, F> {
-    /// Gets the inner value if it has already been initialized.
-    fn get(&self) -> Option<&T> {
-        if self.once.is_completed() {
+    /// Returns a reference to the value if initialized, or `None` if not.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(lazy_get)]
+    ///
+    /// use std::sync::LazyLock;
+    ///
+    /// let mut lazy = LazyLock::new(|| 92);
+    ///
+    /// assert_eq!(LazyLock::get_mut(&mut lazy), None);
+    /// let _ = LazyLock::force(&lazy);
+    /// *LazyLock::get_mut(&mut lazy).unwrap() = 44;
+    /// assert_eq!(*lazy, 44);
+    /// ```
+    #[inline]
+    #[unstable(feature = "lazy_get", issue = "129333")]
+    pub fn get_mut(this: &mut LazyLock<T, F>) -> Option<&mut T> {
+        // `state()` does not perform an atomic load, so prefer it over `is_complete()`.
+        let state = this.once.state();
+        match state {
+            // SAFETY:
+            // The closure has been run successfully, so `value` has been initialized.
+            ExclusiveState::Complete => Some(unsafe { &mut this.data.get_mut().value }),
+            _ => None,
+        }
+    }
+
+    /// Returns a mutable reference to the value if initialized, or `None` if not.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(lazy_get)]
+    ///
+    /// use std::sync::LazyLock;
+    ///
+    /// let lazy = LazyLock::new(|| 92);
+    ///
+    /// assert_eq!(LazyLock::get(&lazy), None);
+    /// let _ = LazyLock::force(&lazy);
+    /// assert_eq!(LazyLock::get(&lazy), Some(&92));
+    /// ```
+    #[inline]
+    #[unstable(feature = "lazy_get", issue = "129333")]
+    pub fn get(this: &LazyLock<T, F>) -> Option<&T> {
+        if this.once.is_completed() {
             // SAFETY:
             // The closure has been run successfully, so `value` has been initialized
             // and will not be modified again.
-            Some(unsafe { &*(*self.data.get()).value })
+            Some(unsafe { &(*this.data.get()).value })
         } else {
             None
         }
@@ -226,7 +325,7 @@ impl<T: Default> Default for LazyLock<T> {
 impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let mut d = f.debug_tuple("LazyLock");
-        match self.get() {
+        match LazyLock::get(self) {
             Some(v) => d.field(v),
             None => d.field(&format_args!("<uninit>")),
         };
@@ -234,6 +333,12 @@ impl<T: fmt::Debug, F> fmt::Debug for LazyLock<T, F> {
     }
 }
 
+#[cold]
+#[inline(never)]
+fn panic_poisoned() -> ! {
+    panic!("LazyLock instance has previously been poisoned")
+}
+
 // We never create a `&F` from a `&LazyLock<T, F>` so it is fine
 // to not impl `Sync` for `F`.
 #[stable(feature = "lazy_cell", since = "1.80.0")]
diff --git a/library/std/src/sync/lazy_lock/tests.rs b/library/std/src/sync/lazy_lock/tests.rs
index 8a6ab4ac4fd..94044368305 100644
--- a/library/std/src/sync/lazy_lock/tests.rs
+++ b/library/std/src/sync/lazy_lock/tests.rs
@@ -142,3 +142,24 @@ fn is_sync_send() {
     fn assert_traits<T: Send + Sync>() {}
     assert_traits::<LazyLock<String>>();
 }
+
+#[test]
+#[should_panic = "has previously been poisoned"]
+fn lazy_force_mut_panic() {
+    let mut lazy = LazyLock::<String>::new(|| panic!());
+    crate::panic::catch_unwind(crate::panic::AssertUnwindSafe(|| {
+        let _ = LazyLock::force_mut(&mut lazy);
+    }))
+    .unwrap_err();
+    let _ = &*lazy;
+}
+
+#[test]
+fn lazy_force_mut() {
+    let s = "abc".to_owned();
+    let mut lazy = LazyLock::new(move || s);
+    LazyLock::force_mut(&mut lazy);
+    let p = LazyLock::force_mut(&mut lazy);
+    p.clear();
+    LazyLock::force_mut(&mut lazy);
+}
diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs
index d0ba8cc3b47..70b419a1e33 100644
--- a/library/std/src/sync/mod.rs
+++ b/library/std/src/sync/mod.rs
@@ -9,6 +9,9 @@
 //! Consider the following code, operating on some global static variables:
 //!
 //! ```rust
+//! // FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+//! #![allow(static_mut_refs)]
+//!
 //! static mut A: u32 = 0;
 //! static mut B: u32 = 0;
 //! static mut C: u32 = 0;
diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs
index bf595fdea2d..5a1cd7d0b8b 100644
--- a/library/std/src/sync/once.rs
+++ b/library/std/src/sync/once.rs
@@ -314,6 +314,16 @@ impl Once {
     pub(crate) fn state(&mut self) -> ExclusiveState {
         self.inner.state()
     }
+
+    /// Sets current state of the `Once` instance.
+    ///
+    /// Since this takes a mutable reference, no initialization can currently
+    /// be running, so the state must be either "incomplete", "poisoned" or
+    /// "complete".
+    #[inline]
+    pub(crate) fn set_state(&mut self, new_state: ExclusiveState) {
+        self.inner.set_state(new_state);
+    }
 }
 
 #[stable(feature = "std_debug", since = "1.16.0")]
diff --git a/library/std/src/sys/alloc/wasm.rs b/library/std/src/sys/alloc/wasm.rs
index ef9d753d7f8..a308fafc68b 100644
--- a/library/std/src/sys/alloc/wasm.rs
+++ b/library/std/src/sys/alloc/wasm.rs
@@ -16,6 +16,9 @@
 //! The crate itself provides a global allocator which on wasm has no
 //! synchronization as there are no threads!
 
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
 use crate::alloc::{GlobalAlloc, Layout, System};
 
 static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::Dlmalloc::new();
diff --git a/library/std/src/sys/pal/unsupported/process.rs b/library/std/src/sys/pal/unsupported/process.rs
index 40231bfc90b..fee81744f09 100644
--- a/library/std/src/sys/pal/unsupported/process.rs
+++ b/library/std/src/sys/pal/unsupported/process.rs
@@ -255,11 +255,11 @@ impl ExitStatusError {
 }
 
 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
-pub struct ExitCode(bool);
+pub struct ExitCode(u8);
 
 impl ExitCode {
-    pub const SUCCESS: ExitCode = ExitCode(false);
-    pub const FAILURE: ExitCode = ExitCode(true);
+    pub const SUCCESS: ExitCode = ExitCode(0);
+    pub const FAILURE: ExitCode = ExitCode(1);
 
     pub fn as_i32(&self) -> i32 {
         self.0 as i32
@@ -268,10 +268,7 @@ impl ExitCode {
 
 impl From<u8> for ExitCode {
     fn from(code: u8) -> Self {
-        match code {
-            0 => Self::SUCCESS,
-            1..=255 => Self::FAILURE,
-        }
+        Self(code)
     }
 }
 
diff --git a/library/std/src/sys/pal/windows/fs/remove_dir_all.rs b/library/std/src/sys/pal/windows/fs/remove_dir_all.rs
index e7234ed8e5f..9416049da78 100644
--- a/library/std/src/sys/pal/windows/fs/remove_dir_all.rs
+++ b/library/std/src/sys/pal/windows/fs/remove_dir_all.rs
@@ -71,10 +71,12 @@ unsafe fn nt_open_file(
 }
 
 /// Open the file `path` in the directory `parent`, requesting the given `access` rights.
+/// `options` will be OR'd with `FILE_OPEN_REPARSE_POINT`.
 fn open_link_no_reparse(
     parent: &File,
     path: &[u16],
     access: u32,
+    options: u32,
 ) -> Result<Option<File>, WinError> {
     // This is implemented using the lower level `NtOpenFile` function as
     // unfortunately opening a file relative to a parent is not supported by
@@ -96,7 +98,7 @@ fn open_link_no_reparse(
             ..c::OBJECT_ATTRIBUTES::default()
         };
         let share = c::FILE_SHARE_DELETE | c::FILE_SHARE_READ | c::FILE_SHARE_WRITE;
-        let options = c::FILE_OPEN_REPARSE_POINT;
+        let options = c::FILE_OPEN_REPARSE_POINT | options;
         let result = nt_open_file(access, &object, share, options);
 
         // Retry without OBJ_DONT_REPARSE if it's not supported.
@@ -128,13 +130,20 @@ fn open_link_no_reparse(
 }
 
 fn open_dir(parent: &File, name: &[u16]) -> Result<Option<File>, WinError> {
-    open_link_no_reparse(parent, name, c::SYNCHRONIZE | c::FILE_LIST_DIRECTORY)
+    // Open the directory for synchronous directory listing.
+    open_link_no_reparse(
+        parent,
+        name,
+        c::SYNCHRONIZE | c::FILE_LIST_DIRECTORY,
+        // "_IO_NONALERT" means that a synchronous call won't be interrupted.
+        c::FILE_SYNCHRONOUS_IO_NONALERT,
+    )
 }
 
 fn delete(parent: &File, name: &[u16]) -> Result<(), WinError> {
     // Note that the `delete` function consumes the opened file to ensure it's
     // dropped immediately. See module comments for why this is important.
-    match open_link_no_reparse(parent, name, c::SYNCHRONIZE | c::DELETE) {
+    match open_link_no_reparse(parent, name, c::DELETE, 0) {
         Ok(Some(f)) => f.delete(),
         Ok(None) => Ok(()),
         Err(e) => Err(e),
diff --git a/library/std/src/sys/sync/once/futex.rs b/library/std/src/sys/sync/once/futex.rs
index 2c8a054282b..25588a4217b 100644
--- a/library/std/src/sys/sync/once/futex.rs
+++ b/library/std/src/sys/sync/once/futex.rs
@@ -91,6 +91,15 @@ impl Once {
         }
     }
 
+    #[inline]
+    pub(crate) fn set_state(&mut self, new_state: ExclusiveState) {
+        *self.state_and_queued.get_mut() = match new_state {
+            ExclusiveState::Incomplete => INCOMPLETE,
+            ExclusiveState::Poisoned => POISONED,
+            ExclusiveState::Complete => COMPLETE,
+        };
+    }
+
     #[cold]
     #[track_caller]
     pub fn wait(&self, ignore_poisoning: bool) {
diff --git a/library/std/src/sys/sync/once/no_threads.rs b/library/std/src/sys/sync/once/no_threads.rs
index 12c1d9f5a6c..cdcffe790f5 100644
--- a/library/std/src/sys/sync/once/no_threads.rs
+++ b/library/std/src/sys/sync/once/no_threads.rs
@@ -55,6 +55,15 @@ impl Once {
         }
     }
 
+    #[inline]
+    pub(crate) fn set_state(&mut self, new_state: ExclusiveState) {
+        self.state.set(match new_state {
+            ExclusiveState::Incomplete => State::Incomplete,
+            ExclusiveState::Poisoned => State::Poisoned,
+            ExclusiveState::Complete => State::Complete,
+        });
+    }
+
     #[cold]
     #[track_caller]
     pub fn wait(&self, _ignore_poisoning: bool) {
diff --git a/library/std/src/sys/sync/once/queue.rs b/library/std/src/sys/sync/once/queue.rs
index 86f72c82008..17abaf0bf26 100644
--- a/library/std/src/sys/sync/once/queue.rs
+++ b/library/std/src/sys/sync/once/queue.rs
@@ -140,6 +140,15 @@ impl Once {
         }
     }
 
+    #[inline]
+    pub(crate) fn set_state(&mut self, new_state: ExclusiveState) {
+        *self.state_and_queue.get_mut() = match new_state {
+            ExclusiveState::Incomplete => ptr::without_provenance_mut(INCOMPLETE),
+            ExclusiveState::Poisoned => ptr::without_provenance_mut(POISONED),
+            ExclusiveState::Complete => ptr::without_provenance_mut(COMPLETE),
+        };
+    }
+
     #[cold]
     #[track_caller]
     pub fn wait(&self, ignore_poisoning: bool) {
diff --git a/library/std/src/thread/local/tests.rs b/library/std/src/thread/local/tests.rs
index 25019b554bb..6abb9b85a2e 100644
--- a/library/std/src/thread/local/tests.rs
+++ b/library/std/src/thread/local/tests.rs
@@ -103,6 +103,9 @@ fn smoke_dtor() {
 
 #[test]
 fn circular() {
+    // FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+    #![allow(static_mut_refs)]
+
     struct S1(&'static LocalKey<UnsafeCell<Option<S1>>>, &'static LocalKey<UnsafeCell<Option<S2>>>);
     struct S2(&'static LocalKey<UnsafeCell<Option<S1>>>, &'static LocalKey<UnsafeCell<Option<S2>>>);
     thread_local!(static K1: UnsafeCell<Option<S1>> = UnsafeCell::new(None));
diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs
index 0fc63c5081b..33cb7e0bcca 100644
--- a/library/std/src/thread/mod.rs
+++ b/library/std/src/thread/mod.rs
@@ -1503,6 +1503,54 @@ impl Thread {
         self.inner.name.as_str()
     }
 
+    /// Consumes the `Thread`, returning a raw pointer.
+    ///
+    /// To avoid a memory leak the pointer must be converted
+    /// back into a `Thread` using [`Thread::from_raw`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(thread_raw)]
+    ///
+    /// use std::thread::{self, Thread};
+    ///
+    /// let thread = thread::current();
+    /// let id = thread.id();
+    /// let ptr = Thread::into_raw(thread);
+    /// unsafe {
+    ///     assert_eq!(Thread::from_raw(ptr).id(), id);
+    /// }
+    /// ```
+    #[unstable(feature = "thread_raw", issue = "97523")]
+    pub fn into_raw(self) -> *const () {
+        // Safety: We only expose an opaque pointer, which maintains the `Pin` invariant.
+        let inner = unsafe { Pin::into_inner_unchecked(self.inner) };
+        Arc::into_raw(inner) as *const ()
+    }
+
+    /// Constructs a `Thread` from a raw pointer.
+    ///
+    /// The raw pointer must have been previously returned
+    /// by a call to [`Thread::into_raw`].
+    ///
+    /// # Safety
+    ///
+    /// This function is unsafe because improper use may lead
+    /// to memory unsafety, even if the returned `Thread` is never
+    /// accessed.
+    ///
+    /// Creating a `Thread` from a pointer other than one returned
+    /// from [`Thread::into_raw`] is **undefined behavior**.
+    ///
+    /// Calling this function twice on the same raw pointer can lead
+    /// to a double-free if both `Thread` instances are dropped.
+    #[unstable(feature = "thread_raw", issue = "97523")]
+    pub unsafe fn from_raw(ptr: *const ()) -> Thread {
+        // Safety: Upheld by caller.
+        unsafe { Thread { inner: Pin::new_unchecked(Arc::from_raw(ptr as *const Inner)) } }
+    }
+
     fn cname(&self) -> Option<&CStr> {
         self.inner.name.as_cstr()
     }
diff --git a/library/std/src/time.rs b/library/std/src/time.rs
index ae46670c25e..f28a0568a3c 100644
--- a/library/std/src/time.rs
+++ b/library/std/src/time.rs
@@ -280,6 +280,7 @@ impl Instant {
     /// ```
     #[must_use]
     #[stable(feature = "time2", since = "1.8.0")]
+    #[cfg_attr(not(test), rustc_diagnostic_item = "instant_now")]
     pub fn now() -> Instant {
         Instant(time::Instant::now())
     }
diff --git a/src/bootstrap/Cargo.lock b/src/bootstrap/Cargo.lock
index 357c6175152..952db063636 100644
--- a/src/bootstrap/Cargo.lock
+++ b/src/bootstrap/Cargo.lock
@@ -84,9 +84,12 @@ dependencies = [
 
 [[package]]
 name = "cc"
-version = "1.0.97"
+version = "1.1.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4"
+checksum = "2d74707dde2ba56f86ae90effb3b43ddd369504387e718014de010cec7959800"
+dependencies = [
+ "shlex",
+]
 
 [[package]]
 name = "cfg-if"
@@ -537,6 +540,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "shlex"
+version = "1.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+
+[[package]]
 name = "syn"
 version = "2.0.75"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 07f7444aaff..1959d0a9662 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -37,7 +37,7 @@ test = false
 # Most of the time updating these dependencies requires modifications to the
 # bootstrap codebase(e.g., https://github.com/rust-lang/rust/issues/124565);
 # otherwise, some targets will fail. That's why these dependencies are explicitly pinned.
-cc = "=1.0.97"
+cc = "=1.1.19"
 cmake = "=0.1.48"
 
 build_helper = { path = "../tools/build_helper" }
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index e1ab1e7599e..db7b239c0ae 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -1057,6 +1057,10 @@ pub fn rustc_cargo(
     // killed, rather than having an error bubble up and cause a panic.
     cargo.rustflag("-Zon-broken-pipe=kill");
 
+    if builder.config.llvm_enzyme {
+        cargo.rustflag("-l").rustflag("Enzyme-19");
+    }
+
     // We currently don't support cross-crate LTO in stage0. This also isn't hugely necessary
     // and may just be a time sink.
     if compiler.stage != 0 {
diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs
index 3755f4a33cb..979671cfa9d 100644
--- a/src/bootstrap/src/core/build_steps/doc.rs
+++ b/src/bootstrap/src/core/build_steps/doc.rs
@@ -1058,6 +1058,13 @@ tool_doc!(
     is_library = true,
     crates = ["run_make_support"]
 );
+tool_doc!(
+    Compiletest,
+    "src/tools/compiletest",
+    rustc_tool = false,
+    is_library = true,
+    crates = ["compiletest"]
+);
 
 #[derive(Ord, PartialOrd, Debug, Clone, Hash, PartialEq, Eq)]
 pub struct ErrorIndex {
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index 08e24ecc340..d8752d03761 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -580,11 +580,11 @@ fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) {
     let version = command(llvm_config).arg("--version").run_capture_stdout(builder).stdout();
     let mut parts = version.split('.').take(2).filter_map(|s| s.parse::<u32>().ok());
     if let (Some(major), Some(_minor)) = (parts.next(), parts.next()) {
-        if major >= 17 {
+        if major >= 18 {
             return;
         }
     }
-    panic!("\n\nbad LLVM version: {version}, need >=17.0\n\n")
+    panic!("\n\nbad LLVM version: {version}, need >=18\n\n")
 }
 
 fn configure_cmake(
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index a7e9352bb1c..2047345d78a 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -1733,6 +1733,11 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
 
         let is_rustdoc = suite.ends_with("rustdoc-ui") || suite.ends_with("rustdoc-js");
 
+        if mode == "run-make" {
+            let cargo = builder.ensure(tool::Cargo { compiler, target: compiler.host });
+            cmd.arg("--cargo-path").arg(cargo);
+        }
+
         // Avoid depending on rustdoc when we don't need it.
         if mode == "rustdoc"
             || mode == "run-make"
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index 003b11ec7cf..d2c23ee8432 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -945,6 +945,7 @@ impl<'a> Builder<'a> {
                 doc::Releases,
                 doc::RunMakeSupport,
                 doc::BuildHelper,
+                doc::Compiletest,
             ),
             Kind::Dist => describe!(
                 dist::Docs,
@@ -1591,12 +1592,6 @@ impl<'a> Builder<'a> {
             rustflags.arg(sysroot_str);
         }
 
-        // https://rust-lang.zulipchat.com/#narrow/stream/182449-t-compiler.2Fhelp/topic/.E2.9C.94.20link.20new.20library.20into.20stage1.2Frustc
-        if self.config.llvm_enzyme {
-            rustflags.arg("-l");
-            rustflags.arg("Enzyme-19");
-        }
-
         let use_new_symbol_mangling = match self.config.rust_new_symbol_mangling {
             Some(setting) => {
                 // If an explicit setting is given, use that
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index 555a6a7f8bd..dcecd7f8084 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -2738,6 +2738,8 @@ impl Config {
         download_ci_llvm: Option<StringOrBool>,
         asserts: bool,
     ) -> bool {
+        let download_ci_llvm = download_ci_llvm.unwrap_or(StringOrBool::Bool(true));
+
         let if_unchanged = || {
             if self.rust_info.is_from_tarball() {
                 // Git is needed for running "if-unchanged" logic.
@@ -2761,10 +2763,7 @@ impl Config {
         };
 
         match download_ci_llvm {
-            None => {
-                (self.channel == "dev" || self.download_rustc_commit.is_some()) && if_unchanged()
-            }
-            Some(StringOrBool::Bool(b)) => {
+            StringOrBool::Bool(b) => {
                 if !b && self.download_rustc_commit.is_some() {
                     panic!(
                         "`llvm.download-ci-llvm` cannot be set to `false` if `rust.download-rustc` is set to `true` or `if-unchanged`."
@@ -2774,8 +2773,8 @@ impl Config {
                 // If download-ci-llvm=true we also want to check that CI llvm is available
                 b && llvm::is_ci_llvm_available(self, asserts)
             }
-            Some(StringOrBool::String(s)) if s == "if-unchanged" => if_unchanged(),
-            Some(StringOrBool::String(other)) => {
+            StringOrBool::String(s) if s == "if-unchanged" => if_unchanged(),
+            StringOrBool::String(other) => {
                 panic!("unrecognized option for download-ci-llvm: {:?}", other)
             }
         }
diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs
index f54a5d3b512..a45e73b5d95 100644
--- a/src/bootstrap/src/core/config/tests.rs
+++ b/src/bootstrap/src/core/config/tests.rs
@@ -32,7 +32,7 @@ fn download_ci_llvm() {
     assert!(!parse_llvm("llvm.download-ci-llvm = false"));
     assert_eq!(parse_llvm(""), if_unchanged);
     assert_eq!(parse_llvm("rust.channel = \"dev\""), if_unchanged);
-    assert!(!parse_llvm("rust.channel = \"stable\""));
+    assert!(parse_llvm("rust.channel = \"stable\""));
     assert_eq!(parse_llvm("build.build = \"x86_64-unknown-linux-gnu\""), if_unchanged);
     assert_eq!(
         parse_llvm(
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index 379cd568647..e6f7f105fa2 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -265,4 +265,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Info,
         summary: "New option `dist.vendor` added to control whether bootstrap should vendor dependencies for dist tarball.",
     },
+    ChangeInfo {
+        change_id: 130529,
+        severity: ChangeSeverity::Info,
+        summary: "If `llvm.download-ci-llvm` is not defined, it defaults to `true`.",
+    },
 ];
diff --git a/src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile
index 855465aa38e..475542b3356 100644
--- a/src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile
@@ -25,5 +25,5 @@ ENV CC_arm_unknown_linux_gnueabihf=arm-unknown-linux-gnueabihf-gcc \
 
 ENV HOSTS=arm-unknown-linux-gnueabihf
 
-ENV RUST_CONFIGURE_ARGS --enable-full-tools --disable-docs
+ENV RUST_CONFIGURE_ARGS --enable-full-tools --enable-profiler --disable-docs
 ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile
index c9a6a2dd069..32b5058bce7 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-musl/Dockerfile
@@ -19,6 +19,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   patch \
   libssl-dev \
   pkg-config \
+  zlib1g-dev \
   && rm -rf /var/lib/apt/lists/*
 
 WORKDIR /build/
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
deleted file mode 100644
index 3acc2ceb135..00000000000
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-17/Dockerfile
+++ /dev/null
@@ -1,62 +0,0 @@
-FROM ubuntu:23.10
-
-ARG DEBIAN_FRONTEND=noninteractive
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
-  g++ \
-  gcc-multilib \
-  make \
-  ninja-build \
-  file \
-  curl \
-  ca-certificates \
-  python3 \
-  git \
-  cmake \
-  sudo \
-  gdb \
-  llvm-17-tools \
-  llvm-17-dev \
-  libedit-dev \
-  libssl-dev \
-  pkg-config \
-  zlib1g-dev \
-  xz-utils \
-  nodejs \
-  mingw-w64 \
-  # libgccjit dependencies
-  flex \
-  libmpfr-dev \
-  libgmp-dev \
-  libmpc3 \
-  libmpc-dev \
-  && rm -rf /var/lib/apt/lists/*
-
-# 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 && \
-    rm -f powershell.deb
-
-COPY scripts/sccache.sh /scripts/
-RUN sh /scripts/sccache.sh
-
-# We are disabling CI LLVM since this builder is intentionally using a host
-# LLVM, rather than the typical src/llvm-project LLVM.
-ENV NO_DOWNLOAD_CI_LLVM 1
-ENV EXTERNAL_LLVM 1
-
-# Using llvm-link-shared due to libffi issues -- see #34486
-ENV RUST_CONFIGURE_ARGS \
-      --build=x86_64-unknown-linux-gnu \
-      --llvm-root=/usr/lib/llvm-17 \
-      --enable-llvm-link-shared \
-      --set rust.randomize-layout=true \
-      --set rust.thin-lto-import-instr-limit=10
-
-COPY host-x86_64/dist-x86_64-linux/shared.sh /scripts/
-COPY host-x86_64/dist-x86_64-linux/build-gccjit.sh /scripts/
-
-RUN /scripts/build-gccjit.sh /scripts
-
-COPY scripts/x86_64-gnu-llvm.sh /tmp/script.sh
-ENV SCRIPT /tmp/script.sh
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-18/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-18/Dockerfile
index 3476b10a3ad..487da580152 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-18/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-18/Dockerfile
@@ -51,6 +51,7 @@ ENV RUST_CONFIGURE_ARGS \
       --build=x86_64-unknown-linux-gnu \
       --llvm-root=/usr/lib/llvm-18 \
       --enable-llvm-link-shared \
+      --set rust.randomize-layout=true \
       --set rust.thin-lto-import-instr-limit=10
 
 COPY host-x86_64/dist-x86_64-linux/shared.sh /scripts/
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile
index 44328b078ad..4991908fe77 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-19/Dockerfile
@@ -51,6 +51,7 @@ ENV RUST_CONFIGURE_ARGS \
       --build=x86_64-unknown-linux-gnu \
       --llvm-root=/usr/lib/llvm-19 \
       --enable-llvm-link-shared \
+      --set rust.randomize-layout=true \
       --set rust.thin-lto-import-instr-limit=10
 
 COPY host-x86_64/dist-x86_64-linux/shared.sh /scripts/
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index f65083eec47..6379f1ade1c 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -89,7 +89,7 @@ pr:
   - image: mingw-check-tidy
     continue_on_error: true
     <<: *job-linux-4c
-  - image: x86_64-gnu-llvm-17
+  - image: x86_64-gnu-llvm-18
     env:
       ENABLE_GCC_CODEGEN: "1"
     <<: *job-linux-16c
@@ -261,11 +261,6 @@ auto:
       RUST_BACKTRACE: 1
     <<: *job-linux-8c
 
-  - image: x86_64-gnu-llvm-17
-    env:
-      RUST_BACKTRACE: 1
-    <<: *job-linux-8c
-
   - image: x86_64-gnu-nopt
     <<: *job-linux-4c
 
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index 3e199539694..b1a5bd604eb 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -25,6 +25,7 @@
         - [\*-apple-ios-macabi](platform-support/apple-ios-macabi.md)
         - [arm64e-apple-ios](platform-support/arm64e-apple-ios.md)
     - [\*-apple-tvos](platform-support/apple-tvos.md)
+        - [arm64e-apple-tvos](platform-support/arm64e-apple-tvos.md)
     - [\*-apple-watchos](platform-support/apple-watchos.md)
     - [\*-apple-visionos](platform-support/apple-visionos.md)
     - [aarch64-nintendo-switch-freestanding](platform-support/aarch64-nintendo-switch-freestanding.md)
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 9a35b35af71..827a7065f3e 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -245,8 +245,9 @@ host tools.
 
 target | std | host | notes
 -------|:---:|:----:|-------
-[`arm64e-apple-ios`](platform-support/arm64e-apple-ios.md) | ✓ | | ARM64e Apple iOS
 [`arm64e-apple-darwin`](platform-support/arm64e-apple-darwin.md)  | ✓ | ✓ | ARM64e Apple Darwin
+[`arm64e-apple-ios`](platform-support/arm64e-apple-ios.md) | ✓ | | ARM64e Apple iOS
+[`arm64e-apple-tvos`](platform-support/arm64e-apple-tvos.md)  | ✓ | | ARM64e Apple tvOS
 [`aarch64-apple-tvos`](platform-support/apple-tvos.md) | ✓ |  | ARM64 tvOS
 [`aarch64-apple-tvos-sim`](platform-support/apple-tvos.md) | ✓ |  | ARM64 tvOS Simulator
 [`aarch64-apple-watchos`](platform-support/apple-watchos.md) | ✓ |  | ARM64 Apple WatchOS
diff --git a/src/doc/rustc/src/platform-support/arm64e-apple-tvos.md b/src/doc/rustc/src/platform-support/arm64e-apple-tvos.md
new file mode 100644
index 00000000000..d49383fb853
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/arm64e-apple-tvos.md
@@ -0,0 +1,37 @@
+# `arm64e-apple-tvos`
+
+**Tier: 3**
+
+ARM64e tvOS (10.0+)
+
+## Target maintainers
+
+- Artyom Tetyukhin ([@arttet](https://github.com/https://github.com/arttet))
+
+## Requirements
+
+This target is cross-compiled and supports `std`.
+To build this target Xcode 12 or higher on macOS is required.
+
+## Building the target
+
+You can build Rust with support for the targets by adding it to the `target` list in `config.toml`:
+
+```toml
+[build]
+target = [ "arm64e-apple-tvos" ]
+```
+
+## Building Rust programs
+
+Rust does not yet ship pre-compiled artifacts for this target.
+To compile for this target, you will need to build Rust with the target enabled (see [Building the target](#building-the-target) above).
+
+## Testing
+
+The target does support running binaries on tvOS platforms with `arm64e` architecture.
+
+## Cross-compilation toolchains and C code
+
+The targets do support `C` code.
+To build compatible `C` code, you have to use XCode with the same compiler and flags.
diff --git a/src/doc/unstable-book/src/language-features/cmse-nonsecure-entry.md b/src/doc/unstable-book/src/language-features/cmse-nonsecure-entry.md
index 338fbc4b2bf..ca95ccf33ac 100644
--- a/src/doc/unstable-book/src/language-features/cmse-nonsecure-entry.md
+++ b/src/doc/unstable-book/src/language-features/cmse-nonsecure-entry.md
@@ -15,10 +15,10 @@ LLVM, the Rust compiler and the linker are providing
 TrustZone-M feature.
 
 One of the things provided, with this unstable feature, is the
-`cmse_nonsecure_entry` attribute.  This attribute marks a Secure function as an
+`C-cmse-nonsecure-entry` ABI. This ABI marks a Secure function as an
 entry function (see [section
 5.4](https://developer.arm.com/documentation/ecm0359818/latest/) for details).
-With this attribute, the compiler will do the following:
+With this ABI, the compiler will do the following:
 * add a special symbol on the function which is the `__acle_se_` prefix and the
   standard function name
 * constrain the number of parameters to avoid using the Non-Secure stack
@@ -38,11 +38,11 @@ gateway veneer.
 <!-- NOTE(ignore) this example is specific to thumbv8m targets -->
 
 ``` rust,ignore
+#![no_std]
 #![feature(cmse_nonsecure_entry)]
 
 #[no_mangle]
-#[cmse_nonsecure_entry]
-pub extern "C" fn entry_function(input: u32) -> u32 {
+pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 {
     input + 6
 }
 ```
diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs
index 5c0898f28fc..71a0e3d72de 100644
--- a/src/librustdoc/doctest/rust.rs
+++ b/src/librustdoc/doctest/rust.rs
@@ -122,23 +122,14 @@ impl<'a, 'tcx> HirCollector<'a, 'tcx> {
         // anything else, this will combine them for us.
         let attrs = Attributes::from_ast(ast_attrs);
         if let Some(doc) = attrs.opt_doc_value() {
-            // Use the outermost invocation, so that doctest names come from where the docs were written.
-            let span = ast_attrs
-                .iter()
-                .find(|attr| attr.doc_str().is_some())
-                .map(|attr| attr.span.ctxt().outer_expn().expansion_cause().unwrap_or(attr.span))
-                .unwrap_or(DUMMY_SP);
+            let span = span_of_fragments(&attrs.doc_strings).unwrap_or(sp);
             self.collector.position = span;
             markdown::find_testable_code(
                 &doc,
                 &mut self.collector,
                 self.codes,
                 self.enable_per_target_ignores,
-                Some(&crate::html::markdown::ExtraInfo::new(
-                    self.tcx,
-                    def_id,
-                    span_of_fragments(&attrs.doc_strings).unwrap_or(sp),
-                )),
+                Some(&crate::html::markdown::ExtraInfo::new(self.tcx, def_id, span)),
             );
         }
 
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 6f4665db6f1..050ba60318e 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -261,7 +261,9 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
                                  </pre>\
                              </div>",
                                 added_classes = added_classes.join(" "),
-                                text = Escape(&original_text),
+                                text = Escape(
+                                    original_text.strip_suffix('\n').unwrap_or(&original_text)
+                                ),
                             )
                             .into(),
                         ));
diff --git a/src/librustdoc/html/markdown/tests.rs b/src/librustdoc/html/markdown/tests.rs
index e490099a92e..3ec60c0efd2 100644
--- a/src/librustdoc/html/markdown/tests.rs
+++ b/src/librustdoc/html/markdown/tests.rs
@@ -524,15 +524,13 @@ fn test_ascii_with_prepending_hashtag() {
 ####.###..#....#....#..#.
 #..#.#....#....#....#..#.
 #..#.#....#....#....#..#.
-#..#.####.####.####..##..
-</code></pre></div>",
+#..#.####.####.####..##..</code></pre></div>",
     );
     t(
         r#"```markdown
 # hello
 ```"#,
         "<div class=\"example-wrap\"><pre class=\"language-markdown\"><code>\
-# hello
-</code></pre></div>",
+# hello</code></pre></div>",
     );
 }
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index a402d799504..668bd391348 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -2538,7 +2538,6 @@ fn render_call_locations<W: fmt::Write>(mut w: W, cx: &mut Context<'_>, item: &c
             &cx.root_path(),
             highlight::DecorationInfo(decoration_info),
             sources::SourceContext::Embedded(sources::ScrapedInfo {
-                needs_prev_next_buttons: line_ranges.len() > 1,
                 needs_expansion,
                 offset: line_min,
                 name: &call_data.display_name,
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index 551bb56685c..0d6a4603cd2 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -292,7 +292,6 @@ where
 
 pub(crate) struct ScrapedInfo<'a> {
     pub(crate) offset: usize,
-    pub(crate) needs_prev_next_buttons: bool,
     pub(crate) name: &'a str,
     pub(crate) url: &'a str,
     pub(crate) title: &'a str,
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 38154dee3e2..04b0eba7450 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -801,6 +801,9 @@ both the code example and the line numbers, so we need to remove the radius in t
 	 * and we include additional 10px for padding. */
 	max-height: calc(1.5em * 5 + 10px);
 }
+.more-scraped-examples .scraped-example:not(.expanded) .example-wrap {
+	max-height: calc(1.5em * 10 + 10px);
+}
 
 .rustdoc:not(.src) .scraped-example:not(.expanded) .src-line-numbers,
 .rustdoc:not(.src) .scraped-example:not(.expanded) .src-line-numbers > pre,
@@ -828,10 +831,14 @@ both the code example and the line numbers, so we need to remove the radius in t
 	-webkit-user-select: none;
 	user-select: none;
 	padding: 14px 8px;
+	padding-right: 2px;
 	color: var(--src-line-numbers-span-color);
 }
 
-.rustdoc .scraped-example .src-line-numbers {
+.rustdoc .scraped-example .example-wrap .src-line-numbers {
+	padding: 0;
+}
+.rustdoc .src-line-numbers pre {
 	padding: 14px 0;
 }
 .src-line-numbers a, .src-line-numbers span {
@@ -890,7 +897,7 @@ both the code example and the line numbers, so we need to remove the radius in t
 }
 
 .docblock code, .docblock-short code,
-pre, .rustdoc.src .example-wrap {
+pre, .rustdoc.src .example-wrap, .example-wrap .src-line-numbers {
 	background-color: var(--code-block-background-color);
 }
 
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index 858753a1917..0eba80133df 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -986,7 +986,13 @@ function preLoadCss(cssUrl) {
     }());
 
     window.rustdoc_add_line_numbers_to_examples = () => {
-        onEachLazy(document.getElementsByClassName("rust-example-rendered"), x => {
+        if (document.querySelector(".rustdoc.src")) {
+            // We are in the source code page, nothing to be done here!
+            return;
+        }
+        onEachLazy(document.querySelectorAll(
+            ":not(.scraped-example) > .example-wrap > pre:not(.example-line-numbers)",
+        ), x => {
             const parent = x.parentNode;
             const line_numbers = parent.querySelectorAll(".example-line-numbers");
             if (line_numbers.length > 0) {
@@ -1005,12 +1011,8 @@ function preLoadCss(cssUrl) {
     };
 
     window.rustdoc_remove_line_numbers_from_examples = () => {
-        onEachLazy(document.getElementsByClassName("rust-example-rendered"), x => {
-            const parent = x.parentNode;
-            const line_numbers = parent.querySelectorAll(".example-line-numbers");
-            for (const node of line_numbers) {
-                parent.removeChild(node);
-            }
+        onEachLazy(document.querySelectorAll(".example-wrap > .example-line-numbers"), x => {
+            x.parentNode.removeChild(x);
         });
     };
 
@@ -1855,12 +1857,8 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm
         // Since the button will be added, no need to keep this listener around.
         elem.removeEventListener("mouseover", addCopyButton);
 
-        // If this is a scrapped example, there will already be a "button-holder" element.
-        let parent = elem.querySelector(".button-holder");
-        if (!parent) {
-            parent = document.createElement("div");
-            parent.className = "button-holder";
-        }
+        const parent = document.createElement("div");
+        parent.className = "button-holder";
 
         const runButton = elem.querySelector(".test-arrow");
         if (runButton !== null) {
@@ -1876,6 +1874,12 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm
             copyButtonAnimation(copyButton);
         });
         parent.appendChild(copyButton);
+
+        if (!elem.parentElement.classList.contains("scraped-example")) {
+            return;
+        }
+        const scrapedWrapped = elem.parentElement;
+        window.updateScrapedExample(scrapedWrapped, parent);
     }
 
     function showHideCodeExampleButtons(event) {
diff --git a/src/librustdoc/html/static/js/scrape-examples.js b/src/librustdoc/html/static/js/scrape-examples.js
index 06e42814d33..98c53b8656f 100644
--- a/src/librustdoc/html/static/js/scrape-examples.js
+++ b/src/librustdoc/html/static/js/scrape-examples.js
@@ -36,13 +36,30 @@
         elt.querySelector(".rust").scrollTo(0, scrollOffset);
     }
 
-    function updateScrapedExample(example, isHidden) {
-        const locs = JSON.parse(example.attributes.getNamedItem("data-locs").textContent);
+    function createScrapeButton(parent, className, content) {
+        const button = document.createElement("button");
+        button.className = className;
+        button.innerText = content;
+        parent.insertBefore(button, parent.firstChild);
+        return button;
+    }
+
+    window.updateScrapedExample = (example, buttonHolder) => {
         let locIndex = 0;
         const highlights = Array.prototype.slice.call(example.querySelectorAll(".highlight"));
         const link = example.querySelector(".scraped-example-title a");
+        let expandButton = null;
+
+        if (!example.classList.contains("expanded")) {
+            expandButton = createScrapeButton(buttonHolder, "expand", "↕");
+        }
+        const isHidden = example.parentElement.classList.contains("more-scraped-examples");
 
+        const locs = example.locs;
         if (locs.length > 1) {
+            const next = createScrapeButton(buttonHolder, "next", "≻");
+            const prev = createScrapeButton(buttonHolder, "prev", "≺");
+
             // Toggle through list of examples in a given file
             const onChangeLoc = changeIndex => {
                 removeClass(highlights[locIndex], "focus");
@@ -57,22 +74,19 @@
                 link.innerHTML = title;
             };
 
-            example.querySelector(".prev")
-                .addEventListener("click", () => {
-                    onChangeLoc(() => {
-                        locIndex = (locIndex - 1 + locs.length) % locs.length;
-                    });
+            prev.addEventListener("click", () => {
+                onChangeLoc(() => {
+                    locIndex = (locIndex - 1 + locs.length) % locs.length;
                 });
+            });
 
-            example.querySelector(".next")
-                .addEventListener("click", () => {
-                    onChangeLoc(() => {
-                        locIndex = (locIndex + 1) % locs.length;
-                    });
+            next.addEventListener("click", () => {
+                onChangeLoc(() => {
+                    locIndex = (locIndex + 1) % locs.length;
                 });
+            });
         }
 
-        const expandButton = example.querySelector(".expand");
         if (expandButton) {
             expandButton.addEventListener("click", () => {
                 if (hasClass(example, "expanded")) {
@@ -83,13 +97,16 @@
                 }
             });
         }
+    };
 
+    function setupLoc(example, isHidden) {
+        example.locs = JSON.parse(example.attributes.getNamedItem("data-locs").textContent);
         // Start with the first example in view
-        scrollToLoc(example, locs[0][0], isHidden);
+        scrollToLoc(example, example.locs[0][0], isHidden);
     }
 
     const firstExamples = document.querySelectorAll(".scraped-example-list > .scraped-example");
-    onEachLazy(firstExamples, el => updateScrapedExample(el, false));
+    onEachLazy(firstExamples, el => setupLoc(el, false));
     onEachLazy(document.querySelectorAll(".more-examples-toggle"), toggle => {
         // Allow users to click the left border of the <details> section to close it,
         // since the section can be large and finding the [+] button is annoying.
@@ -102,11 +119,11 @@
         const moreExamples = toggle.querySelectorAll(".scraped-example");
         toggle.querySelector("summary").addEventListener("click", () => {
             // Wrapping in setTimeout ensures the update happens after the elements are actually
-            // visible. This is necessary since updateScrapedExample calls scrollToLoc which
+            // visible. This is necessary since setupLoc calls scrollToLoc which
             // depends on offsetHeight, a property that requires an element to be visible to
             // compute correctly.
             setTimeout(() => {
-                onEachLazy(moreExamples, el => updateScrapedExample(el, true));
+                onEachLazy(moreExamples, el => setupLoc(el, true));
             });
         }, {once: true});
     });
diff --git a/src/librustdoc/html/templates/scraped_source.html b/src/librustdoc/html/templates/scraped_source.html
index e1fc2e69378..bd54bbf58d5 100644
--- a/src/librustdoc/html/templates/scraped_source.html
+++ b/src/librustdoc/html/templates/scraped_source.html
@@ -1,8 +1,8 @@
 <div class="scraped-example{% if !info.needs_expansion +%} expanded{% endif %}" data-locs="{{info.locations}}"> {# #}
     <div class="scraped-example-title">
        {{info.name +}} (<a href="{{info.url}}">{{info.title}}</a>) {# #}
-    </div>
-    <div class="example-wrap"> {# #}
+    </div> {# #}
+    <div class="example-wrap">
         {# https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag#data-nosnippet-attr
            Do not show "1 2 3 4 5 ..." in web search results. #}
         <div class="src-line-numbers" data-nosnippet> {# #}
@@ -18,16 +18,5 @@
                 {{code_html|safe}}
             </code> {# #}
         </pre> {# #}
-        {% if info.needs_prev_next_buttons || info.needs_expansion %}
-            <div class="button-holder">
-                {% if info.needs_prev_next_buttons %}
-                    <button class="prev">&pr;</button> {# #}
-                    <button class="next">&sc;</button>
-                {% endif %}
-                {% if info.needs_expansion %}
-                    <button class="expand">&varr;</button>
-                {% endif %}
-            </div>
-        {% endif %}
     </div> {# #}
 </div> {# #}
diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs
index 92b21f7dbaa..eb5faeeaf9a 100644
--- a/src/tools/build-manifest/src/main.rs
+++ b/src/tools/build-manifest/src/main.rs
@@ -51,9 +51,7 @@ static HOSTS: &[&str] = &[
 
 static TARGETS: &[&str] = &[
     "aarch64-apple-darwin",
-    "arm64e-apple-darwin",
     "aarch64-apple-ios",
-    "arm64e-apple-ios",
     "aarch64-apple-ios-macabi",
     "aarch64-apple-ios-sim",
     "aarch64-unknown-fuchsia",
@@ -68,6 +66,9 @@ static TARGETS: &[&str] = &[
     "aarch64-unknown-none-softfloat",
     "aarch64-unknown-redox",
     "aarch64-unknown-uefi",
+    "arm64e-apple-darwin",
+    "arm64e-apple-ios",
+    "arm64e-apple-tvos",
     "arm-linux-androideabi",
     "arm-unknown-linux-gnueabi",
     "arm-unknown-linux-gnueabihf",
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject a9a418d1a22f29e7dfd034e3b93f15657e608a2
+Subproject eaee77dc1584be45949b75e4c4c9a841605e3a4
diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs
index b7c9d3d0385..9c5100a8c1a 100644
--- a/src/tools/clippy/clippy_lints/src/entry.rs
+++ b/src/tools/clippy/clippy_lints/src/entry.rs
@@ -1,8 +1,8 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{reindent_multiline, snippet_indent, snippet_with_applicability, snippet_with_context};
 use clippy_utils::{
-    can_move_expr_to_closure_no_visit, higher, is_expr_final_block_expr, is_expr_used_or_unified, match_def_path,
-    paths, peel_hir_expr_while, SpanlessEq,
+    can_move_expr_to_closure_no_visit, higher, is_expr_final_block_expr, is_expr_used_or_unified,
+    peel_hir_expr_while, SpanlessEq,
 };
 use core::fmt::{self, Write};
 use rustc_errors::Applicability;
@@ -11,7 +11,7 @@ use rustc_hir::intravisit::{walk_expr, Visitor};
 use rustc_hir::{Block, Expr, ExprKind, HirId, Pat, Stmt, StmtKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
-use rustc_span::{Span, SyntaxContext, DUMMY_SP};
+use rustc_span::{sym, Span, SyntaxContext, DUMMY_SP};
 
 declare_clippy_lint! {
     /// ### What it does
@@ -269,9 +269,9 @@ fn try_parse_contains<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'_>) -> Optio
                 key,
                 call_ctxt: expr.span.ctxt(),
             };
-            if match_def_path(cx, id, &paths::BTREEMAP_CONTAINS_KEY) {
+            if cx.tcx.is_diagnostic_item(sym::btreemap_contains_key, id) {
                 Some((MapType::BTree, expr))
-            } else if match_def_path(cx, id, &paths::HASHMAP_CONTAINS_KEY) {
+            } else if cx.tcx.is_diagnostic_item(sym::hashmap_contains_key, id) {
                 Some((MapType::Hash, expr))
             } else {
                 None
@@ -306,7 +306,7 @@ struct InsertExpr<'tcx> {
 fn try_parse_insert<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<InsertExpr<'tcx>> {
     if let ExprKind::MethodCall(_, map, [key, value], _) = expr.kind {
         let id = cx.typeck_results().type_dependent_def_id(expr.hir_id)?;
-        if match_def_path(cx, id, &paths::BTREEMAP_INSERT) || match_def_path(cx, id, &paths::HASHMAP_INSERT) {
+        if cx.tcx.is_diagnostic_item(sym::btreemap_insert, id) || cx.tcx.is_diagnostic_item(sym::hashmap_insert, id) {
             Some(InsertExpr { map, key, value })
         } else {
             None
diff --git a/src/tools/clippy/clippy_lints/src/format_push_string.rs b/src/tools/clippy/clippy_lints/src/format_push_string.rs
index d05c5a01f41..c6f03c3a7cf 100644
--- a/src/tools/clippy/clippy_lints/src/format_push_string.rs
+++ b/src/tools/clippy/clippy_lints/src/format_push_string.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::ty::is_type_lang_item;
-use clippy_utils::{higher, match_def_path, paths};
+use clippy_utils::higher;
 use rustc_hir::{BinOpKind, Expr, ExprKind, LangItem, MatchSource};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
@@ -70,7 +70,7 @@ impl<'tcx> LateLintPass<'tcx> for FormatPushString {
         let arg = match expr.kind {
             ExprKind::MethodCall(_, _, [arg], _) => {
                 if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
-                    && match_def_path(cx, fn_def_id, &paths::PUSH_STR)
+                    && cx.tcx.is_diagnostic_item(sym::string_push_str, fn_def_id)
                 {
                     arg
                 } else {
diff --git a/src/tools/clippy/clippy_lints/src/instant_subtraction.rs b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
index f41fdf3203c..6d6820311b6 100644
--- a/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
+++ b/src/tools/clippy/clippy_lints/src/instant_subtraction.rs
@@ -112,7 +112,7 @@ impl LateLintPass<'_> for InstantSubtraction {
 fn is_instant_now_call(cx: &LateContext<'_>, expr_block: &'_ Expr<'_>) -> bool {
     if let ExprKind::Call(fn_expr, []) = expr_block.kind
         && let Some(fn_id) = clippy_utils::path_def_id(cx, fn_expr)
-        && clippy_utils::match_def_path(cx, fn_id, &clippy_utils::paths::INSTANT_NOW)
+        && cx.tcx.is_diagnostic_item(sym::instant_now, fn_id)
     {
         true
     } else {
diff --git a/src/tools/clippy/clippy_lints/src/iter_over_hash_type.rs b/src/tools/clippy/clippy_lints/src/iter_over_hash_type.rs
index fb29d982417..f162948bb44 100644
--- a/src/tools/clippy/clippy_lints/src/iter_over_hash_type.rs
+++ b/src/tools/clippy/clippy_lints/src/iter_over_hash_type.rs
@@ -1,10 +1,5 @@
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::higher::ForLoop;
-use clippy_utils::match_any_def_paths;
-use clippy_utils::paths::{
-    HASHMAP_DRAIN, HASHMAP_ITER, HASHMAP_ITER_MUT, HASHMAP_KEYS, HASHMAP_VALUES, HASHMAP_VALUES_MUT, HASHSET_DRAIN,
-    HASHSET_ITER_TY,
-};
 use clippy_utils::ty::is_type_diagnostic_item;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
@@ -44,28 +39,23 @@ declare_lint_pass!(IterOverHashType => [ITER_OVER_HASH_TYPE]);
 
 impl LateLintPass<'_> for IterOverHashType {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &'_ rustc_hir::Expr<'_>) {
+        let hash_iter_tys = [
+            sym::HashMap,
+            sym::HashSet,
+            sym::hashmap_keys_ty,
+            sym::hashmap_values_ty,
+            sym::hashmap_values_mut_ty,
+            sym::hashmap_iter_ty,
+            sym::hashmap_iter_mut_ty,
+            sym::hashmap_drain_ty,
+            sym::hashset_iter_ty,
+            sym::hashset_drain_ty,
+        ];
+
         if let Some(for_loop) = ForLoop::hir(expr)
             && !for_loop.body.span.from_expansion()
             && let ty = cx.typeck_results().expr_ty(for_loop.arg).peel_refs()
-            && let Some(adt) = ty.ty_adt_def()
-            && let did = adt.did()
-            && (match_any_def_paths(
-                cx,
-                did,
-                &[
-                    &HASHMAP_KEYS,
-                    &HASHMAP_VALUES,
-                    &HASHMAP_VALUES_MUT,
-                    &HASHMAP_ITER,
-                    &HASHMAP_ITER_MUT,
-                    &HASHMAP_DRAIN,
-                    &HASHSET_ITER_TY,
-                    &HASHSET_DRAIN,
-                ],
-            )
-            .is_some()
-                || is_type_diagnostic_item(cx, ty, sym::HashMap)
-                || is_type_diagnostic_item(cx, ty, sym::HashSet))
+            && hash_iter_tys.into_iter().any(|sym| is_type_diagnostic_item(cx, ty, sym))
         {
             span_lint(
                 cx,
diff --git a/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs b/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs
index 3d1c666dfea..8206c75927b 100644
--- a/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs
+++ b/src/tools/clippy/clippy_lints/src/lines_filter_map_ok.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{is_diag_item_method, is_trait_method, match_def_path, path_to_local_id, paths};
+use clippy_utils::{is_diag_item_method, is_trait_method, path_to_local_id};
 use rustc_errors::Applicability;
 use rustc_hir::{Body, Closure, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -96,7 +96,7 @@ fn should_lint(cx: &LateContext<'_>, args: &[Expr<'_>], method_str: &str) -> boo
                 ExprKind::Path(qpath) => cx
                     .qpath_res(qpath, fm_arg.hir_id)
                     .opt_def_id()
-                    .is_some_and(|did| match_def_path(cx, did, &paths::CORE_RESULT_OK_METHOD)),
+                    .is_some_and(|did| cx.tcx.is_diagnostic_item(sym::result_ok_method, did)),
                 // Detect `|x| x.ok()`
                 ExprKind::Closure(Closure { body, .. }) => {
                     if let Body {
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs b/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs
index 57434f35544..55d1b9ee676 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs
@@ -1,10 +1,10 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
-use clippy_utils::{match_def_path, paths, SpanlessEq};
+use clippy_utils::SpanlessEq;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, Pat, Stmt, StmtKind, UnOp};
 use rustc_lint::LateContext;
-use rustc_span::Span;
+use rustc_span::{sym, Symbol, Span};
 use std::borrow::Cow;
 
 use super::MANUAL_WHILE_LET_SOME;
@@ -47,20 +47,20 @@ fn report_lint(cx: &LateContext<'_>, pop_span: Span, pop_stmt_kind: PopStmt<'_>,
     );
 }
 
-fn match_method_call(cx: &LateContext<'_>, expr: &Expr<'_>, method: &[&str]) -> bool {
+fn match_method_call(cx: &LateContext<'_>, expr: &Expr<'_>, method: Symbol) -> bool {
     if let ExprKind::MethodCall(..) = expr.kind
         && let Some(id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
     {
-        match_def_path(cx, id, method)
+        cx.tcx.is_diagnostic_item(method, id)
     } else {
         false
     }
 }
 
 fn is_vec_pop_unwrap(cx: &LateContext<'_>, expr: &Expr<'_>, is_empty_recv: &Expr<'_>) -> bool {
-    if (match_method_call(cx, expr, &paths::OPTION_UNWRAP) || match_method_call(cx, expr, &paths::OPTION_EXPECT))
+    if (match_method_call(cx, expr, sym::option_unwrap) || match_method_call(cx, expr, sym::option_expect))
         && let ExprKind::MethodCall(_, unwrap_recv, ..) = expr.kind
-        && match_method_call(cx, unwrap_recv, &paths::VEC_POP)
+        && match_method_call(cx, unwrap_recv, sym::vec_pop)
         && let ExprKind::MethodCall(_, pop_recv, ..) = unwrap_recv.kind
     {
         // make sure they're the same `Vec`
@@ -96,7 +96,7 @@ fn check_call_arguments(cx: &LateContext<'_>, stmt: &Stmt<'_>, is_empty_recv: &E
 pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, full_cond: &'tcx Expr<'_>, body: &'tcx Expr<'_>, loop_span: Span) {
     if let ExprKind::Unary(UnOp::Not, cond) = full_cond.kind
         && let ExprKind::MethodCall(_, is_empty_recv, _, _) = cond.kind
-        && match_method_call(cx, cond, &paths::VEC_IS_EMPTY)
+        && match_method_call(cx, cond, sym::vec_is_empty)
         && let ExprKind::Block(body, _) = body.kind
         && let Some(stmt) = body.stmts.first()
     {
diff --git a/src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs b/src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs
index db491a8c8f6..5198d7838a2 100644
--- a/src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_main_separator_str.rs
@@ -1,7 +1,7 @@
 use clippy_config::msrvs::{self, Msrv};
 use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::{is_trait_method, match_def_path, paths, peel_hir_expr_refs};
+use clippy_utils::{is_trait_method, peel_hir_expr_refs};
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{Expr, ExprKind, Mutability, QPath};
@@ -56,7 +56,7 @@ impl LateLintPass<'_> for ManualMainSeparatorStr {
             && let Res::Def(DefKind::Const, receiver_def_id) = path.res
             && is_trait_method(cx, target, sym::ToString)
             && self.msrv.meets(msrvs::PATH_MAIN_SEPARATOR_STR)
-            && match_def_path(cx, receiver_def_id, &paths::PATH_MAIN_SEPARATOR)
+            && cx.tcx.is_diagnostic_item(sym::path_main_separator, receiver_def_id)
             && let ty::Ref(_, ty, Mutability::Not) = cx.typeck_results().expr_ty_adjusted(expr).kind()
             && ty.is_str()
         {
diff --git a/src/tools/clippy/clippy_lints/src/manual_retain.rs b/src/tools/clippy/clippy_lints/src/manual_retain.rs
index d4e53f8f74b..a35b0f914e0 100644
--- a/src/tools/clippy/clippy_lints/src/manual_retain.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_retain.rs
@@ -3,22 +3,22 @@ use clippy_config::Conf;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::{get_type_diagnostic_name, is_type_lang_item};
-use clippy_utils::{match_def_path, paths, SpanlessEq};
+use clippy_utils::SpanlessEq;
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
 use rustc_hir::ExprKind::Assign;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::impl_lint_pass;
-use rustc_span::symbol::sym;
+use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 
-const ACCEPTABLE_METHODS: [&[&str]; 5] = [
-    &paths::BINARYHEAP_ITER,
-    &paths::HASHSET_ITER,
-    &paths::BTREESET_ITER,
-    &paths::SLICE_INTO,
-    &paths::VEC_DEQUE_ITER,
+const ACCEPTABLE_METHODS: [Symbol; 5] = [
+    sym::binaryheap_iter,
+    sym::hashset_iter,
+    sym::btreeset_iter,
+    sym::slice_iter,
+    sym::vecdeque_iter,
 ];
 
 declare_clippy_lint! {
@@ -84,7 +84,7 @@ fn check_into_iter(
 ) {
     if let hir::ExprKind::MethodCall(_, into_iter_expr, [_], _) = &target_expr.kind
         && let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id)
-        && match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER)
+        && cx.tcx.is_diagnostic_item(sym::iter_filter, filter_def_id)
         && let hir::ExprKind::MethodCall(_, struct_expr, [], _) = &into_iter_expr.kind
         && let Some(into_iter_def_id) = cx.typeck_results().type_dependent_def_id(into_iter_expr.hir_id)
         && Some(into_iter_def_id) == cx.tcx.lang_items().into_iter_fn()
@@ -127,14 +127,14 @@ fn check_iter(
 ) {
     if let hir::ExprKind::MethodCall(_, filter_expr, [], _) = &target_expr.kind
         && let Some(copied_def_id) = cx.typeck_results().type_dependent_def_id(target_expr.hir_id)
-        && (match_def_path(cx, copied_def_id, &paths::CORE_ITER_COPIED)
-            || match_def_path(cx, copied_def_id, &paths::CORE_ITER_CLONED))
+        && (cx.tcx.is_diagnostic_item(sym::iter_copied, copied_def_id)
+            || cx.tcx.is_diagnostic_item(sym::iter_cloned, copied_def_id))
         && let hir::ExprKind::MethodCall(_, iter_expr, [_], _) = &filter_expr.kind
         && let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(filter_expr.hir_id)
-        && match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER)
+        && cx.tcx.is_diagnostic_item(sym::iter_filter, filter_def_id)
         && let hir::ExprKind::MethodCall(_, struct_expr, [], _) = &iter_expr.kind
         && let Some(iter_expr_def_id) = cx.typeck_results().type_dependent_def_id(iter_expr.hir_id)
-        && match_acceptable_def_path(cx, iter_expr_def_id)
+        && match_acceptable_sym(cx, iter_expr_def_id)
         && match_acceptable_type(cx, left_expr, msrv)
         && SpanlessEq::new(cx).eq_expr(left_expr, struct_expr)
         && let hir::ExprKind::MethodCall(_, _, [closure_expr], _) = filter_expr.kind
@@ -189,10 +189,10 @@ fn check_to_owned(
         && cx.tcx.is_diagnostic_item(sym::to_owned_method, to_owned_def_id)
         && let hir::ExprKind::MethodCall(_, chars_expr, [_], _) = &filter_expr.kind
         && let Some(filter_def_id) = cx.typeck_results().type_dependent_def_id(filter_expr.hir_id)
-        && match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER)
+        && cx.tcx.is_diagnostic_item(sym::iter_filter, filter_def_id)
         && let hir::ExprKind::MethodCall(_, str_expr, [], _) = &chars_expr.kind
         && let Some(chars_expr_def_id) = cx.typeck_results().type_dependent_def_id(chars_expr.hir_id)
-        && match_def_path(cx, chars_expr_def_id, &paths::STR_CHARS)
+        && cx.tcx.is_diagnostic_item(sym::str_chars, chars_expr_def_id)
         && let ty = cx.typeck_results().expr_ty(str_expr).peel_refs()
         && is_type_lang_item(cx, ty, hir::LangItem::String)
         && SpanlessEq::new(cx).eq_expr(left_expr, str_expr)
@@ -247,10 +247,10 @@ fn make_sugg(
     }
 }
 
-fn match_acceptable_def_path(cx: &LateContext<'_>, collect_def_id: DefId) -> bool {
+fn match_acceptable_sym(cx: &LateContext<'_>, collect_def_id: DefId) -> bool {
     ACCEPTABLE_METHODS
         .iter()
-        .any(|&method| match_def_path(cx, collect_def_id, method))
+        .any(|&method| cx.tcx.is_diagnostic_item(method, collect_def_id))
 }
 
 fn match_acceptable_type(cx: &LateContext<'_>, expr: &hir::Expr<'_>, msrv: &Msrv) -> bool {
diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs
index 85cabd2800a..02d433ecc5a 100644
--- a/src/tools/clippy/clippy_lints/src/manual_strip.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs
@@ -4,7 +4,7 @@ use clippy_utils::consts::{ConstEvalCtxt, Constant};
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
 use clippy_utils::usage::mutated_variables;
-use clippy_utils::{eq_expr_value, higher, match_def_path, paths};
+use clippy_utils::{eq_expr_value, higher};
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
@@ -14,7 +14,7 @@ use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::impl_lint_pass;
 use rustc_span::source_map::Spanned;
-use rustc_span::Span;
+use rustc_span::{sym, Span};
 use std::iter;
 
 declare_clippy_lint! {
@@ -76,9 +76,9 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
             && self.msrv.meets(msrvs::STR_STRIP_PREFIX)
             && let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(cond.hir_id)
         {
-            let strip_kind = if match_def_path(cx, method_def_id, &paths::STR_STARTS_WITH) {
+            let strip_kind = if cx.tcx.is_diagnostic_item(sym::str_starts_with, method_def_id) {
                 StripKind::Prefix
-            } else if match_def_path(cx, method_def_id, &paths::STR_ENDS_WITH) {
+            } else if cx.tcx.is_diagnostic_item(sym::str_ends_with, method_def_id) {
                 StripKind::Suffix
             } else {
                 return;
@@ -137,7 +137,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualStrip {
 fn len_arg<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
     if let ExprKind::MethodCall(_, arg, [], _) = expr.kind
         && let Some(method_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
-        && match_def_path(cx, method_def_id, &paths::STR_LEN)
+        && cx.tcx.is_diagnostic_item(sym::str_len, method_def_id)
     {
         Some(arg)
     } else {
diff --git a/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs b/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs
index 4fbf661727d..77a62fbb4fb 100644
--- a/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/filter_map_bool_then.rs
@@ -1,9 +1,8 @@
 use super::FILTER_MAP_BOOL_THEN;
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::paths::BOOL_THEN;
 use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::is_copy;
-use clippy_utils::{is_from_proc_macro, is_trait_method, match_def_path, peel_blocks};
+use clippy_utils::{is_from_proc_macro, is_trait_method, peel_blocks};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LintContext};
@@ -35,7 +34,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, arg: &
         && let ExprKind::Closure(then_closure) = then_arg.kind
         && let then_body = peel_blocks(cx.tcx.hir().body(then_closure.body).value)
         && let Some(def_id) = cx.typeck_results().type_dependent_def_id(value.hir_id)
-        && match_def_path(cx, def_id, &BOOL_THEN)
+        && cx.tcx.is_diagnostic_item(sym::bool_then, def_id)
         && !is_from_proc_macro(cx, expr)
         // Count the number of derefs needed to get to the bool because we need those in the suggestion
         && let needed_derefs = cx.typeck_results().expr_adjustments(recv)
diff --git a/src/tools/clippy/clippy_lints/src/methods/open_options.rs b/src/tools/clippy/clippy_lints/src/methods/open_options.rs
index cbeb48b6cc3..f1a3c81cebb 100644
--- a/src/tools/clippy/clippy_lints/src/methods/open_options.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/open_options.rs
@@ -126,17 +126,18 @@ fn get_open_options(
         && let ExprKind::Path(path) = callee.kind
         && let Some(did) = cx.qpath_res(&path, callee.hir_id).opt_def_id()
     {
-        match_any_def_paths(
-            cx,
-            did,
-            &[
-                &paths::TOKIO_IO_OPEN_OPTIONS_NEW,
-                &paths::OPEN_OPTIONS_NEW,
-                &paths::FILE_OPTIONS,
-                &paths::TOKIO_FILE_OPTIONS,
-            ],
-        )
-        .is_some()
+        let std_file_options = [
+            sym::file_options,
+            sym::open_options_new,
+        ];
+
+        let tokio_file_options: &[&[&str]] = &[
+            &paths::TOKIO_IO_OPEN_OPTIONS_NEW,
+            &paths::TOKIO_FILE_OPTIONS,
+        ];
+
+        let is_std_options = std_file_options.into_iter().any(|sym| cx.tcx.is_diagnostic_item(sym, did));
+        is_std_options || match_any_def_paths(cx, did, tokio_file_options).is_some()
     } else {
         false
     }
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
index cb57689b0c4..9a18d8a1421 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_as_ref_deref.rs
@@ -2,12 +2,12 @@ use clippy_config::msrvs::{self, Msrv};
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet;
 use clippy_utils::ty::is_type_diagnostic_item;
-use clippy_utils::{match_def_path, path_to_local_id, paths, peel_blocks};
+use clippy_utils::{path_to_local_id, peel_blocks};
 use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_lint::LateContext;
 use rustc_middle::ty;
-use rustc_span::sym;
+use rustc_span::{sym, Symbol};
 
 use super::OPTION_AS_REF_DEREF;
 
@@ -31,14 +31,14 @@ pub(super) fn check(
         return;
     }
 
-    let deref_aliases: [&[&str]; 7] = [
-        &paths::CSTRING_AS_C_STR,
-        &paths::OS_STRING_AS_OS_STR,
-        &paths::PATH_BUF_AS_PATH,
-        &paths::STRING_AS_STR,
-        &paths::STRING_AS_MUT_STR,
-        &paths::VEC_AS_SLICE,
-        &paths::VEC_AS_MUT_SLICE,
+    let deref_aliases: [Symbol; 7] = [
+        sym::cstring_as_c_str,
+        sym::os_string_as_os_str,
+        sym::pathbuf_as_path,
+        sym::string_as_str,
+        sym::string_as_mut_str,
+        sym::vec_as_slice,
+        sym::vec_as_mut_slice,
     ];
 
     let is_deref = match map_arg.kind {
@@ -48,7 +48,7 @@ pub(super) fn check(
                 .map_or(false, |fun_def_id| {
                     cx.tcx.is_diagnostic_item(sym::deref_method, fun_def_id)
                         || cx.tcx.is_diagnostic_item(sym::deref_mut_method, fun_def_id)
-                        || deref_aliases.iter().any(|path| match_def_path(cx, fun_def_id, path))
+                        || deref_aliases.iter().any(|&sym| cx.tcx.is_diagnostic_item(sym, fun_def_id))
                 })
         },
         hir::ExprKind::Closure(&hir::Closure { body, .. }) => {
@@ -69,7 +69,7 @@ pub(super) fn check(
                         let method_did = cx.typeck_results().type_dependent_def_id(closure_expr.hir_id).unwrap();
                         cx.tcx.is_diagnostic_item(sym::deref_method, method_did)
                             || cx.tcx.is_diagnostic_item(sym::deref_mut_method, method_did)
-                            || deref_aliases.iter().any(|path| match_def_path(cx, method_did, path))
+                            || deref_aliases.iter().any(|&sym| cx.tcx.is_diagnostic_item(sym, method_did))
                     } else {
                         false
                     }
diff --git a/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs b/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs
index e45c7962f13..8bc535ac47a 100644
--- a/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs
@@ -8,7 +8,7 @@ use rustc_span::sym;
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::ty::implements_trait;
-use clippy_utils::{match_def_path, paths};
+use clippy_utils::is_enum_variant_ctor;
 
 use super::SEEK_FROM_CURRENT;
 
@@ -36,8 +36,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'
 fn arg_is_seek_from_current<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> bool {
     if let ExprKind::Call(f, args) = expr.kind
         && let ExprKind::Path(ref path) = f.kind
-        && let Some(def_id) = cx.qpath_res(path, f.hir_id).opt_def_id()
-        && match_def_path(cx, def_id, &paths::STD_IO_SEEK_FROM_CURRENT)
+        && let Some(ctor_call_id) = cx.qpath_res(path, f.hir_id).opt_def_id()
+        && is_enum_variant_ctor(cx, sym::SeekFrom, sym!(Current), ctor_call_id)
     {
         // check if argument of `SeekFrom::Current` is `0`
         if args.len() == 1
diff --git a/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs b/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
index cc4cb47e35c..7c09cc252e1 100644
--- a/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::ty::implements_trait;
-use clippy_utils::{is_expr_used_or_unified, match_def_path, paths};
+use clippy_utils::{is_expr_used_or_unified, is_enum_variant_ctor};
 use rustc_ast::ast::{LitIntType, LitKind};
 use rustc_data_structures::packed::Pu128;
 use rustc_errors::Applicability;
@@ -28,8 +28,8 @@ pub(super) fn check<'tcx>(
         && implements_trait(cx, ty, seek_trait_id, &[])
         && let ExprKind::Call(func, args1) = arg.kind
         && let ExprKind::Path(ref path) = func.kind
-        && let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id()
-        && match_def_path(cx, def_id, &paths::STD_IO_SEEKFROM_START)
+        && let Some(ctor_call_id) = cx.qpath_res(path, func.hir_id).opt_def_id()
+        && is_enum_variant_ctor(cx, sym::SeekFrom, sym!(Start), ctor_call_id)
         && args1.len() == 1
         && let ExprKind::Lit(lit) = args1[0].kind
         && let LitKind::Int(Pu128(0), LitIntType::Unsuffixed) = lit.node
diff --git a/src/tools/clippy/clippy_lints/src/methods/single_char_add_str.rs b/src/tools/clippy/clippy_lints/src/methods/single_char_add_str.rs
index 81450fd8c6c..ccdf5529d53 100644
--- a/src/tools/clippy/clippy_lints/src/methods/single_char_add_str.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/single_char_add_str.rs
@@ -1,13 +1,13 @@
 use crate::methods::{single_char_insert_string, single_char_push_string};
-use clippy_utils::{match_def_path, paths};
 use rustc_hir as hir;
 use rustc_lint::LateContext;
+use rustc_span::sym;
 
 pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, receiver: &hir::Expr<'_>, args: &[hir::Expr<'_>]) {
     if let Some(fn_def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id) {
-        if match_def_path(cx, fn_def_id, &paths::PUSH_STR) {
+        if cx.tcx.is_diagnostic_item(sym::string_push_str, fn_def_id) {
             single_char_push_string::check(cx, expr, receiver, args);
-        } else if match_def_path(cx, fn_def_id, &paths::INSERT_STR) {
+        } else if cx.tcx.is_diagnostic_item(sym::string_insert_str, fn_def_id) {
             single_char_insert_string::check(cx, expr, receiver, args);
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
index 69c5bc57e29..bf7555a29e2 100644
--- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs
@@ -6,7 +6,7 @@ use clippy_utils::source::{snippet, SpanRangeExt};
 use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, is_type_diagnostic_item, is_type_lang_item};
 use clippy_utils::visitors::find_all_ret_expressions;
 use clippy_utils::{
-    fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, match_def_path, paths, peel_middle_ty_refs,
+    fn_def_id, get_parent_expr, is_diag_item_method, is_diag_trait_item, peel_middle_ty_refs,
     return_ty,
 };
 use rustc_errors::Applicability;
@@ -250,7 +250,7 @@ fn check_string_from_utf8<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>,
     if let Some((call, arg)) = skip_addr_of_ancestors(cx, expr)
         && !arg.span.from_expansion()
         && let ExprKind::Call(callee, _) = call.kind
-        && fn_def_id(cx, call).is_some_and(|did| match_def_path(cx, did, &paths::STRING_FROM_UTF8))
+        && fn_def_id(cx, call).is_some_and(|did| cx.tcx.is_diagnostic_item(sym::string_from_utf8, did))
         && let Some(unwrap_call) = get_parent_expr(cx, call)
         && let ExprKind::MethodCall(unwrap_method_name, ..) = unwrap_call.kind
         && matches!(unwrap_method_name.ident.name, sym::unwrap | sym::expect)
diff --git a/src/tools/clippy/clippy_lints/src/methods/waker_clone_wake.rs b/src/tools/clippy/clippy_lints/src/methods/waker_clone_wake.rs
index da66632d55f..9b64cc7589c 100644
--- a/src/tools/clippy/clippy_lints/src/methods/waker_clone_wake.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/waker_clone_wake.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
-use clippy_utils::{is_trait_method, match_def_path, paths};
+use clippy_utils::is_trait_method;
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::LateContext;
@@ -12,7 +12,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'
     let ty = cx.typeck_results().expr_ty(recv);
 
     if let Some(did) = ty.ty_adt_def()
-        && match_def_path(cx, did.did(), &paths::WAKER)
+        && cx.tcx.is_diagnostic_item(sym::Waker, did.did())
         && let ExprKind::MethodCall(_, waker_ref, &[], _) = recv.kind
         && is_trait_method(cx, recv, sym::Clone)
     {
diff --git a/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs b/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs
index b915df52762..cfc15d92715 100644
--- a/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs
+++ b/src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::{snippet_with_applicability, SpanRangeExt};
-use clippy_utils::{match_def_path, paths};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -63,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions {
             ExprKind::Call(func, [param]) => {
                 if let ExprKind::Path(ref path) = func.kind
                     && let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id()
-                    && match_def_path(cx, def_id, &paths::PERMISSIONS_FROM_MODE)
+                    && cx.tcx.is_diagnostic_item(sym::permissions_from_mode, def_id)
                     && let ExprKind::Lit(_) = param.kind
                     && param.span.eq_ctxt(expr.span)
                     && param
diff --git a/src/tools/clippy/clippy_lints/src/operators/float_equality_without_abs.rs b/src/tools/clippy/clippy_lints/src/operators/float_equality_without_abs.rs
index cace85a2451..be97ad389bf 100644
--- a/src/tools/clippy/clippy_lints/src/operators/float_equality_without_abs.rs
+++ b/src/tools/clippy/clippy_lints/src/operators/float_equality_without_abs.rs
@@ -1,12 +1,12 @@
 use clippy_utils::diagnostics::span_lint_and_then;
-use clippy_utils::{match_def_path, paths, sugg};
+use clippy_utils::sugg;
 use rustc_ast::util::parser::AssocOp;
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
-use rustc_span::source_map::Spanned;
+use rustc_span::{sym, source_map::Spanned};
 
 use super::FLOAT_EQUALITY_WITHOUT_ABS;
 
@@ -36,7 +36,7 @@ pub(crate) fn check<'tcx>(
         // right hand side matches either f32::EPSILON or f64::EPSILON
         && let ExprKind::Path(ref epsilon_path) = rhs.kind
         && let Res::Def(DefKind::AssocConst, def_id) = cx.qpath_res(epsilon_path, rhs.hir_id)
-        && (match_def_path(cx, def_id, &paths::F32_EPSILON) || match_def_path(cx, def_id, &paths::F64_EPSILON))
+        && ([sym::f32_epsilon, sym::f64_epsilon].into_iter().any(|sym| cx.tcx.is_diagnostic_item(sym, def_id)))
 
         // values of the subtractions on the left hand side are of the type float
         && let t_val_l = cx.typeck_results().expr_ty(val_l)
diff --git a/src/tools/clippy/clippy_lints/src/redundant_clone.rs b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
index bfdc1cbeed7..4e24ddad83a 100644
--- a/src/tools/clippy/clippy_lints/src/redundant_clone.rs
+++ b/src/tools/clippy/clippy_lints/src/redundant_clone.rs
@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::{span_lint_hir, span_lint_hir_and_then};
 use clippy_utils::mir::{visit_local_usage, LocalUsage, PossibleBorrowerMap};
 use clippy_utils::source::SpanRangeExt;
 use clippy_utils::ty::{has_drop, is_copy, is_type_diagnostic_item, is_type_lang_item, walk_ptrs_ty_depth};
-use clippy_utils::{fn_has_unsatisfiable_preds, match_def_path, paths};
+use clippy_utils::fn_has_unsatisfiable_preds;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{def_id, Body, FnDecl, LangItem};
@@ -102,8 +102,8 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClone {
                     && is_type_lang_item(cx, arg_ty, LangItem::String));
 
             let from_deref = !from_borrow
-                && (match_def_path(cx, fn_def_id, &paths::PATH_TO_PATH_BUF)
-                    || match_def_path(cx, fn_def_id, &paths::OS_STR_TO_OS_STRING));
+                && (cx.tcx.is_diagnostic_item(sym::path_to_pathbuf, fn_def_id)
+                    || cx.tcx.is_diagnostic_item(sym::os_str_to_os_string, fn_def_id));
 
             if !from_borrow && !from_deref {
                 continue;
diff --git a/src/tools/clippy/clippy_lints/src/repeat_vec_with_capacity.rs b/src/tools/clippy/clippy_lints/src/repeat_vec_with_capacity.rs
index 678681ea425..08de10f69b0 100644
--- a/src/tools/clippy/clippy_lints/src/repeat_vec_with_capacity.rs
+++ b/src/tools/clippy/clippy_lints/src/repeat_vec_with_capacity.rs
@@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::higher::VecArgs;
 use clippy_utils::macros::matching_root_macro_call;
 use clippy_utils::source::snippet;
-use clippy_utils::{expr_or_init, fn_def_id, match_def_path, paths};
+use clippy_utils::{expr_or_init, fn_def_id};
 use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -67,7 +67,7 @@ fn emit_lint(cx: &LateContext<'_>, span: Span, kind: &str, note: &'static str, s
 fn check_vec_macro(cx: &LateContext<'_>, expr: &Expr<'_>) {
     if matching_root_macro_call(cx, expr.span, sym::vec_macro).is_some()
         && let Some(VecArgs::Repeat(repeat_expr, len_expr)) = VecArgs::hir(cx, expr)
-        && fn_def_id(cx, repeat_expr).is_some_and(|did| match_def_path(cx, did, &paths::VEC_WITH_CAPACITY))
+        && fn_def_id(cx, repeat_expr).is_some_and(|did| cx.tcx.is_diagnostic_item(sym::vec_with_capacity, did))
         && !len_expr.span.from_expansion()
         && let Some(Constant::Int(2..)) = ConstEvalCtxt::new(cx).eval(expr_or_init(cx, len_expr))
     {
@@ -91,7 +91,7 @@ fn check_repeat_fn(cx: &LateContext<'_>, expr: &Expr<'_>) {
     if !expr.span.from_expansion()
         && fn_def_id(cx, expr).is_some_and(|did| cx.tcx.is_diagnostic_item(sym::iter_repeat, did))
         && let ExprKind::Call(_, [repeat_expr]) = expr.kind
-        && fn_def_id(cx, repeat_expr).is_some_and(|did| match_def_path(cx, did, &paths::VEC_WITH_CAPACITY))
+        && fn_def_id(cx, repeat_expr).is_some_and(|did| cx.tcx.is_diagnostic_item(sym::vec_with_capacity, did))
         && !repeat_expr.span.from_expansion()
     {
         emit_lint(
diff --git a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
index b0e25c02265..04c16281ec4 100644
--- a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
+++ b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs
@@ -2,8 +2,8 @@ use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::macros::matching_root_macro_call;
 use clippy_utils::sugg::Sugg;
 use clippy_utils::{
-    get_enclosing_block, is_expr_path_def_path, is_integer_literal, is_path_diagnostic_item, path_to_local,
-    path_to_local_id, paths, SpanlessEq,
+    get_enclosing_block, is_integer_literal, is_path_diagnostic_item, path_to_local,
+    path_to_local_id, SpanlessEq,
 };
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_block, walk_expr, walk_stmt, Visitor};
@@ -150,10 +150,10 @@ impl SlowVectorInit {
         }
 
         if let ExprKind::Call(func, [len_expr]) = expr.kind
-            && is_expr_path_def_path(cx, func, &paths::VEC_WITH_CAPACITY)
+            && is_path_diagnostic_item(cx, func, sym::vec_with_capacity)
         {
             Some(InitializedSize::Initialized(len_expr))
-        } else if matches!(expr.kind, ExprKind::Call(func, _) if is_expr_path_def_path(cx, func, &paths::VEC_NEW)) {
+        } else if matches!(expr.kind, ExprKind::Call(func, _) if is_path_diagnostic_item(cx, func, sym::vec_new)) {
             Some(InitializedSize::Uninitialized)
         } else {
             None
diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs b/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs
index 6b5e6c6ab20..f01cb457af8 100644
--- a/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs
+++ b/src/tools/clippy/clippy_lints/src/unnecessary_owned_empty_strings.rs
@@ -1,6 +1,5 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::ty::is_type_lang_item;
-use clippy_utils::{match_def_path, paths};
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::{BorrowKind, Expr, ExprKind, LangItem, Mutability};
@@ -42,7 +41,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryOwnedEmptyStrings {
             && let ty::Ref(_, inner_str, _) = cx.typeck_results().expr_ty_adjusted(expr).kind()
             && inner_str.is_str()
         {
-            if match_def_path(cx, fun_def_id, &paths::STRING_NEW) {
+            if cx.tcx.is_diagnostic_item(sym::string_new, fun_def_id) {
                 span_lint_and_sugg(
                     cx,
                     UNNECESSARY_OWNED_EMPTY_STRINGS,
diff --git a/src/tools/clippy/clippy_utils/src/higher.rs b/src/tools/clippy/clippy_utils/src/higher.rs
index 8970b4d1229..e09cc9edf3a 100644
--- a/src/tools/clippy/clippy_utils/src/higher.rs
+++ b/src/tools/clippy/clippy_utils/src/higher.rs
@@ -4,7 +4,7 @@
 
 use crate::consts::{ConstEvalCtxt, Constant};
 use crate::ty::is_type_diagnostic_item;
-use crate::{is_expn_of, match_def_path, paths};
+use crate::is_expn_of;
 
 use rustc_ast::ast;
 use rustc_hir as hir;
@@ -297,10 +297,10 @@ impl<'a> VecArgs<'a> {
             && is_expn_of(fun.span, "vec").is_some()
             && let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id()
         {
-            return if match_def_path(cx, fun_def_id, &paths::VEC_FROM_ELEM) && args.len() == 2 {
+            return if cx.tcx.is_diagnostic_item(sym::vec_from_elem, fun_def_id) && args.len() == 2 {
                 // `vec![elem; size]` case
                 Some(VecArgs::Repeat(&args[0], &args[1]))
-            } else if match_def_path(cx, fun_def_id, &paths::SLICE_INTO_VEC) && args.len() == 1 {
+            } else if cx.tcx.is_diagnostic_item(sym::slice_into_vec, fun_def_id) && args.len() == 1 {
                 // `vec![a, b, c]` case
                 if let ExprKind::Call(_, [arg]) = &args[0].kind
                     && let ExprKind::Array(args) = arg.kind
@@ -309,7 +309,7 @@ impl<'a> VecArgs<'a> {
                 } else {
                     None
                 }
-            } else if match_def_path(cx, fun_def_id, &paths::VEC_NEW) && args.is_empty() {
+            } else if cx.tcx.is_diagnostic_item(sym::vec_new, fun_def_id) && args.is_empty() {
                 Some(VecArgs::Vec(&[]))
             } else {
                 None
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 5db14872c36..0d0d6219c5e 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -263,24 +263,18 @@ pub fn is_res_lang_ctor(cx: &LateContext<'_>, res: Res, lang_item: LangItem) ->
     }
 }
 
-pub fn is_res_diagnostic_ctor(cx: &LateContext<'_>, res: Res, diag_item: Symbol) -> bool {
-    if let Res::Def(DefKind::Ctor(..), id) = res
-        && let Some(id) = cx.tcx.opt_parent(id)
-    {
-        cx.tcx.is_diagnostic_item(diag_item, id)
-    } else {
-        false
-    }
-}
 
-/// Checks if a `QPath` resolves to a constructor of a diagnostic item.
-pub fn is_diagnostic_ctor(cx: &LateContext<'_>, qpath: &QPath<'_>, diagnostic_item: Symbol) -> bool {
-    if let QPath::Resolved(_, path) = qpath {
-        if let Res::Def(DefKind::Ctor(..), ctor_id) = path.res {
-            return cx.tcx.is_diagnostic_item(diagnostic_item, cx.tcx.parent(ctor_id));
-        }
-    }
-    false
+/// Checks if `{ctor_call_id}(...)` is `{enum_item}::{variant_name}(...)`.
+pub fn is_enum_variant_ctor(cx: &LateContext<'_>, enum_item: Symbol, variant_name: Symbol, ctor_call_id: DefId) -> bool {
+    let Some(enum_def_id) = cx.tcx.get_diagnostic_item(enum_item) else {
+        return false;
+    };
+
+    let variants = cx.tcx.adt_def(enum_def_id).variants().iter();
+    variants
+        .filter(|variant| variant.name == variant_name)
+        .filter_map(|variant| variant.ctor.as_ref())
+        .any(|(_, ctor_def_id)| *ctor_def_id == ctor_call_id)
 }
 
 /// Checks if the `DefId` matches the given diagnostic item or it's constructor.
diff --git a/src/tools/clippy/clippy_utils/src/mir/mod.rs b/src/tools/clippy/clippy_utils/src/mir/mod.rs
index e4966690d8c..654fb564848 100644
--- a/src/tools/clippy/clippy_utils/src/mir/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/mir/mod.rs
@@ -30,7 +30,7 @@ pub fn visit_local_usage(locals: &[Local], mir: &Body<'_>, location: Location) -
         locals.len()
     ];
 
-    traversal::Postorder::new(&mir.basic_blocks, location.block)
+    traversal::Postorder::new(&mir.basic_blocks, location.block, ())
         .collect::<Vec<_>>()
         .into_iter()
         .rev()
diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs
index 684c645c199..a30edc48fff 100644
--- a/src/tools/clippy/clippy_utils/src/paths.rs
+++ b/src/tools/clippy/clippy_utils/src/paths.rs
@@ -4,6 +4,7 @@
 //! Whenever possible, please consider diagnostic items over hardcoded paths.
 //! See <https://github.com/rust-lang/rust-clippy/issues/5393> for more information.
 
+// Paths inside rustc
 pub const APPLICABILITY: [&str; 2] = ["rustc_lint_defs", "Applicability"];
 pub const APPLICABILITY_VALUES: [[&str; 3]; 4] = [
     ["rustc_lint_defs", "Applicability", "Unspecified"],
@@ -12,56 +13,36 @@ pub const APPLICABILITY_VALUES: [[&str; 3]; 4] = [
     ["rustc_lint_defs", "Applicability", "MachineApplicable"],
 ];
 pub const DIAG: [&str; 2] = ["rustc_errors", "Diag"];
-pub const BINARYHEAP_ITER: [&str; 5] = ["alloc", "collections", "binary_heap", "BinaryHeap", "iter"];
-pub const BTREEMAP_CONTAINS_KEY: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "contains_key"];
-pub const BTREEMAP_INSERT: [&str; 6] = ["alloc", "collections", "btree", "map", "BTreeMap", "insert"];
-pub const BTREESET_ITER: [&str; 6] = ["alloc", "collections", "btree", "set", "BTreeSet", "iter"];
-pub const CORE_ITER_CLONED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "cloned"];
-pub const CORE_ITER_COPIED: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "copied"];
-pub const CORE_ITER_FILTER: [&str; 6] = ["core", "iter", "traits", "iterator", "Iterator", "filter"];
-pub const CORE_RESULT_OK_METHOD: [&str; 4] = ["core", "result", "Result", "ok"];
-pub const CSTRING_AS_C_STR: [&str; 5] = ["alloc", "ffi", "c_str", "CString", "as_c_str"];
 pub const EARLY_CONTEXT: [&str; 2] = ["rustc_lint", "EarlyContext"];
 pub const EARLY_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "EarlyLintPass"];
-pub const F32_EPSILON: [&str; 4] = ["core", "f32", "<impl f32>", "EPSILON"];
-pub const F64_EPSILON: [&str; 4] = ["core", "f64", "<impl f64>", "EPSILON"];
-pub const FILE_OPTIONS: [&str; 4] = ["std", "fs", "File", "options"];
-#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
-pub const FUTURES_IO_ASYNCREADEXT: [&str; 3] = ["futures_util", "io", "AsyncReadExt"];
-#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
-pub const FUTURES_IO_ASYNCWRITEEXT: [&str; 3] = ["futures_util", "io", "AsyncWriteExt"];
-pub const HASHMAP_CONTAINS_KEY: [&str; 6] = ["std", "collections", "hash", "map", "HashMap", "contains_key"];
-pub const HASHMAP_INSERT: [&str; 6] = ["std", "collections", "hash", "map", "HashMap", "insert"];
-pub const HASHMAP_ITER: [&str; 5] = ["std", "collections", "hash", "map", "Iter"];
-pub const HASHMAP_ITER_MUT: [&str; 5] = ["std", "collections", "hash", "map", "IterMut"];
-pub const HASHMAP_KEYS: [&str; 5] = ["std", "collections", "hash", "map", "Keys"];
-pub const HASHMAP_VALUES: [&str; 5] = ["std", "collections", "hash", "map", "Values"];
-pub const HASHMAP_DRAIN: [&str; 5] = ["std", "collections", "hash", "map", "Drain"];
-pub const HASHMAP_VALUES_MUT: [&str; 5] = ["std", "collections", "hash", "map", "ValuesMut"];
-pub const HASHSET_ITER_TY: [&str; 5] = ["std", "collections", "hash", "set", "Iter"];
-pub const HASHSET_ITER: [&str; 6] = ["std", "collections", "hash", "set", "HashSet", "iter"];
-pub const HASHSET_DRAIN: [&str; 5] = ["std", "collections", "hash", "set", "Drain"];
 pub const IDENT: [&str; 3] = ["rustc_span", "symbol", "Ident"];
 pub const IDENT_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Ident", "as_str"];
-pub const INSERT_STR: [&str; 4] = ["alloc", "string", "String", "insert_str"];
-pub const ITERTOOLS_NEXT_TUPLE: [&str; 3] = ["itertools", "Itertools", "next_tuple"];
 pub const KW_MODULE: [&str; 3] = ["rustc_span", "symbol", "kw"];
 pub const LATE_CONTEXT: [&str; 2] = ["rustc_lint", "LateContext"];
 pub const LATE_LINT_PASS: [&str; 3] = ["rustc_lint", "passes", "LateLintPass"];
 pub const LINT: [&str; 2] = ["rustc_lint_defs", "Lint"];
+pub const SYMBOL: [&str; 3] = ["rustc_span", "symbol", "Symbol"];
+pub const SYMBOL_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Symbol", "as_str"];
+pub const SYMBOL_INTERN: [&str; 4] = ["rustc_span", "symbol", "Symbol", "intern"];
+pub const SYMBOL_TO_IDENT_STRING: [&str; 4] = ["rustc_span", "symbol", "Symbol", "to_ident_string"];
+pub const SYM_MODULE: [&str; 3] = ["rustc_span", "symbol", "sym"];
+pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"];
+
+// Paths in `core`/`alloc`/`std`. This should be avoided and cleaned up by adding diagnostic items.
+// ... none currently!
+
+// Paths in clippy itself
 pub const MSRV: [&str; 3] = ["clippy_config", "msrvs", "Msrv"];
-pub const OPEN_OPTIONS_NEW: [&str; 4] = ["std", "fs", "OpenOptions", "new"];
-pub const OS_STRING_AS_OS_STR: [&str; 5] = ["std", "ffi", "os_str", "OsString", "as_os_str"];
-pub const OS_STR_TO_OS_STRING: [&str; 5] = ["std", "ffi", "os_str", "OsStr", "to_os_string"];
+
+// Paths in external crates
+#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
+pub const FUTURES_IO_ASYNCREADEXT: [&str; 3] = ["futures_util", "io", "AsyncReadExt"];
+#[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
+pub const FUTURES_IO_ASYNCWRITEEXT: [&str; 3] = ["futures_util", "io", "AsyncWriteExt"];
+pub const ITERTOOLS_NEXT_TUPLE: [&str; 3] = ["itertools", "Itertools", "next_tuple"];
 pub const PARKING_LOT_MUTEX_GUARD: [&str; 3] = ["lock_api", "mutex", "MutexGuard"];
 pub const PARKING_LOT_RWLOCK_READ_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockReadGuard"];
 pub const PARKING_LOT_RWLOCK_WRITE_GUARD: [&str; 3] = ["lock_api", "rwlock", "RwLockWriteGuard"];
-pub const PATH_BUF_AS_PATH: [&str; 4] = ["std", "path", "PathBuf", "as_path"];
-pub const PATH_MAIN_SEPARATOR: [&str; 3] = ["std", "path", "MAIN_SEPARATOR"];
-pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"];
-#[cfg_attr(not(unix), allow(clippy::invalid_paths))]
-pub const PERMISSIONS_FROM_MODE: [&str; 6] = ["std", "os", "unix", "fs", "PermissionsExt", "from_mode"];
-pub const PUSH_STR: [&str; 4] = ["alloc", "string", "String", "push_str"];
 pub const REGEX_BUILDER_NEW: [&str; 3] = ["regex", "RegexBuilder", "new"];
 pub const REGEX_BYTES_BUILDER_NEW: [&str; 4] = ["regex", "bytes", "RegexBuilder", "new"];
 pub const REGEX_BYTES_NEW: [&str; 4] = ["regex", "bytes", "Regex", "new"];
@@ -70,24 +51,6 @@ pub const REGEX_NEW: [&str; 3] = ["regex", "Regex", "new"];
 pub const REGEX_SET_NEW: [&str; 3] = ["regex", "RegexSet", "new"];
 pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"];
 pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"];
-pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "<impl [T]>", "into_vec"];
-pub const SLICE_INTO: [&str; 4] = ["core", "slice", "<impl [T]>", "iter"];
-pub const STD_IO_SEEK_FROM_CURRENT: [&str; 4] = ["std", "io", "SeekFrom", "Current"];
-pub const STD_IO_SEEKFROM_START: [&str; 4] = ["std", "io", "SeekFrom", "Start"];
-pub const STRING_AS_MUT_STR: [&str; 4] = ["alloc", "string", "String", "as_mut_str"];
-pub const STRING_AS_STR: [&str; 4] = ["alloc", "string", "String", "as_str"];
-pub const STRING_NEW: [&str; 4] = ["alloc", "string", "String", "new"];
-pub const STR_CHARS: [&str; 4] = ["core", "str", "<impl str>", "chars"];
-pub const STR_ENDS_WITH: [&str; 4] = ["core", "str", "<impl str>", "ends_with"];
-pub const STR_LEN: [&str; 4] = ["core", "str", "<impl str>", "len"];
-pub const STR_STARTS_WITH: [&str; 4] = ["core", "str", "<impl str>", "starts_with"];
-pub const SYMBOL: [&str; 3] = ["rustc_span", "symbol", "Symbol"];
-pub const SYMBOL_AS_STR: [&str; 4] = ["rustc_span", "symbol", "Symbol", "as_str"];
-pub const SYMBOL_INTERN: [&str; 4] = ["rustc_span", "symbol", "Symbol", "intern"];
-pub const SYMBOL_TO_IDENT_STRING: [&str; 4] = ["rustc_span", "symbol", "Symbol", "to_ident_string"];
-pub const SYM_MODULE: [&str; 3] = ["rustc_span", "symbol", "sym"];
-pub const SYNTAX_CONTEXT: [&str; 3] = ["rustc_span", "hygiene", "SyntaxContext"];
-pub const STRING_FROM_UTF8: [&str; 4] = ["alloc", "string", "String", "from_utf8"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
 pub const TOKIO_FILE_OPTIONS: [&str; 5] = ["tokio", "fs", "file", "File", "options"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
@@ -98,16 +61,3 @@ pub const TOKIO_IO_ASYNCWRITEEXT: [&str; 5] = ["tokio", "io", "util", "async_wri
 pub const TOKIO_IO_OPEN_OPTIONS: [&str; 4] = ["tokio", "fs", "open_options", "OpenOptions"];
 #[expect(clippy::invalid_paths)] // internal lints do not know about all external crates
 pub const TOKIO_IO_OPEN_OPTIONS_NEW: [&str; 5] = ["tokio", "fs", "open_options", "OpenOptions", "new"];
-pub const VEC_AS_MUT_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_mut_slice"];
-pub const VEC_AS_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_slice"];
-pub const VEC_DEQUE_ITER: [&str; 5] = ["alloc", "collections", "vec_deque", "VecDeque", "iter"];
-pub const VEC_FROM_ELEM: [&str; 3] = ["alloc", "vec", "from_elem"];
-pub const VEC_NEW: [&str; 4] = ["alloc", "vec", "Vec", "new"];
-pub const VEC_WITH_CAPACITY: [&str; 4] = ["alloc", "vec", "Vec", "with_capacity"];
-pub const INSTANT_NOW: [&str; 4] = ["std", "time", "Instant", "now"];
-pub const VEC_IS_EMPTY: [&str; 4] = ["alloc", "vec", "Vec", "is_empty"];
-pub const VEC_POP: [&str; 4] = ["alloc", "vec", "Vec", "pop"];
-pub const WAKER: [&str; 4] = ["core", "task", "wake", "Waker"];
-pub const OPTION_UNWRAP: [&str; 4] = ["core", "option", "Option", "unwrap"];
-pub const OPTION_EXPECT: [&str; 4] = ["core", "option", "Option", "expect"];
-pub const BOOL_THEN: [&str; 4] = ["core", "bool", "<impl bool>", "then"];
diff --git a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr
index f7e338935a7..d92c03f4888 100644
--- a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr
+++ b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr
@@ -236,5 +236,16 @@ LL |     if result.is_ok() {
 LL |         result.as_mut().unwrap();
    |         ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 25 previous errors
+error: creating a shared reference to mutable static is discouraged
+  --> tests/ui/checked_unwrap/simple_conditionals.rs:174:12
+   |
+LL |         if X.is_some() {
+   |            ^^^^^^^^^^^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+   = note: `-D static-mut-refs` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(static_mut_refs)]`
+
+error: aborting due to 26 previous errors
 
diff --git a/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
index 6b8a103d4a9..87d3517cd5f 100644
--- a/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
+++ b/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.rs
@@ -4,6 +4,7 @@
 #![allow(deref_nullptr)]
 #![allow(clippy::unnecessary_operation)]
 #![allow(dropping_copy_types)]
+#![allow(clippy::assign_op_pattern)]
 #![warn(clippy::multiple_unsafe_ops_per_block)]
 
 extern crate proc_macros;
diff --git a/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.stderr b/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.stderr
index e732bde0707..a9417a9ef91 100644
--- a/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.stderr
+++ b/src/tools/clippy/tests/ui/multiple_unsafe_ops_per_block.stderr
@@ -1,5 +1,5 @@
 error: this `unsafe` block contains 2 unsafe operations, expected only one
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:37:5
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:38:5
    |
 LL | /     unsafe {
 LL | |         STATIC += 1;
@@ -8,12 +8,12 @@ LL | |     }
    | |_____^
    |
 note: modification of a mutable static occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:38:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:39:9
    |
 LL |         STATIC += 1;
    |         ^^^^^^^^^^^
 note: unsafe function call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:39:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:40:9
    |
 LL |         not_very_safe();
    |         ^^^^^^^^^^^^^^^
@@ -21,7 +21,7 @@ LL |         not_very_safe();
    = help: to override `-D warnings` add `#[allow(clippy::multiple_unsafe_ops_per_block)]`
 
 error: this `unsafe` block contains 2 unsafe operations, expected only one
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:46:5
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:47:5
    |
 LL | /     unsafe {
 LL | |         drop(u.u);
@@ -30,18 +30,18 @@ LL | |     }
    | |_____^
    |
 note: union field access occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:47:14
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:48:14
    |
 LL |         drop(u.u);
    |              ^^^
 note: raw pointer dereference occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:48:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:49:9
    |
 LL |         *raw_ptr();
    |         ^^^^^^^^^^
 
 error: this `unsafe` block contains 3 unsafe operations, expected only one
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:53:5
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:54:5
    |
 LL | /     unsafe {
 LL | |         asm!("nop");
@@ -51,23 +51,23 @@ LL | |     }
    | |_____^
    |
 note: inline assembly used here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:54:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:55:9
    |
 LL |         asm!("nop");
    |         ^^^^^^^^^^^
 note: unsafe method call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:55:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:56:9
    |
 LL |         sample.not_very_safe();
    |         ^^^^^^^^^^^^^^^^^^^^^^
 note: modification of a mutable static occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:56:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:57:9
    |
 LL |         STATIC = 0;
    |         ^^^^^^^^^^
 
 error: this `unsafe` block contains 6 unsafe operations, expected only one
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:62:5
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:63:5
    |
 LL | /     unsafe {
 LL | |         drop(u.u);
@@ -79,55 +79,55 @@ LL | |     }
    | |_____^
    |
 note: union field access occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:63:14
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:64:14
    |
 LL |         drop(u.u);
    |              ^^^
 note: access of a mutable static occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:64:14
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:65:14
    |
 LL |         drop(STATIC);
    |              ^^^^^^
 note: unsafe method call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:65:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:66:9
    |
 LL |         sample.not_very_safe();
    |         ^^^^^^^^^^^^^^^^^^^^^^
 note: unsafe function call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:66:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:67:9
    |
 LL |         not_very_safe();
    |         ^^^^^^^^^^^^^^^
 note: raw pointer dereference occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:67:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:68:9
    |
 LL |         *raw_ptr();
    |         ^^^^^^^^^^
 note: inline assembly used here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:68:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:69:9
    |
 LL |         asm!("nop");
    |         ^^^^^^^^^^^
 
 error: this `unsafe` block contains 2 unsafe operations, expected only one
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:106:5
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:107:5
    |
 LL |     unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: unsafe function call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:106:14
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:107:14
    |
 LL |     unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: raw pointer dereference occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:106:39
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:107:39
    |
 LL |     unsafe { char::from_u32_unchecked(*ptr.cast::<u32>()) }
    |                                       ^^^^^^^^^^^^^^^^^^
 
 error: this `unsafe` block contains 2 unsafe operations, expected only one
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:124:5
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:125:5
    |
 LL | /     unsafe {
 LL | |         x();
@@ -136,18 +136,18 @@ LL | |     }
    | |_____^
    |
 note: unsafe function call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:125:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:126:9
    |
 LL |         x();
    |         ^^^
 note: unsafe function call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:126:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:127:9
    |
 LL |         x();
    |         ^^^
 
 error: this `unsafe` block contains 2 unsafe operations, expected only one
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:135:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:136:9
    |
 LL | /         unsafe {
 LL | |             T::X();
@@ -156,18 +156,18 @@ LL | |         }
    | |_________^
    |
 note: unsafe function call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:136:13
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:137:13
    |
 LL |             T::X();
    |             ^^^^^^
 note: unsafe function call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:137:13
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:138:13
    |
 LL |             T::X();
    |             ^^^^^^
 
 error: this `unsafe` block contains 2 unsafe operations, expected only one
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:145:5
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:146:5
    |
 LL | /     unsafe {
 LL | |         x.0();
@@ -176,12 +176,12 @@ LL | |     }
    | |_____^
    |
 note: unsafe function call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:146:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:147:9
    |
 LL |         x.0();
    |         ^^^^^
 note: unsafe function call occurs here
-  --> tests/ui/multiple_unsafe_ops_per_block.rs:147:9
+  --> tests/ui/multiple_unsafe_ops_per_block.rs:148:9
    |
 LL |         x.0();
    |         ^^^^^
diff --git a/src/tools/clippy/tests/ui/must_use_candidates.fixed b/src/tools/clippy/tests/ui/must_use_candidates.fixed
index c057eba4aca..adb266ffbc8 100644
--- a/src/tools/clippy/tests/ui/must_use_candidates.fixed
+++ b/src/tools/clippy/tests/ui/must_use_candidates.fixed
@@ -1,5 +1,10 @@
 #![feature(never_type)]
-#![allow(unused_mut, clippy::redundant_allocation, clippy::needless_pass_by_ref_mut)]
+#![allow(
+    unused_mut,
+    clippy::redundant_allocation,
+    clippy::needless_pass_by_ref_mut,
+    static_mut_refs
+)]
 #![warn(clippy::must_use_candidate)]
 use std::rc::Rc;
 use std::sync::atomic::{AtomicBool, Ordering};
diff --git a/src/tools/clippy/tests/ui/must_use_candidates.rs b/src/tools/clippy/tests/ui/must_use_candidates.rs
index 36019652006..49bb16af788 100644
--- a/src/tools/clippy/tests/ui/must_use_candidates.rs
+++ b/src/tools/clippy/tests/ui/must_use_candidates.rs
@@ -1,5 +1,10 @@
 #![feature(never_type)]
-#![allow(unused_mut, clippy::redundant_allocation, clippy::needless_pass_by_ref_mut)]
+#![allow(
+    unused_mut,
+    clippy::redundant_allocation,
+    clippy::needless_pass_by_ref_mut,
+    static_mut_refs
+)]
 #![warn(clippy::must_use_candidate)]
 use std::rc::Rc;
 use std::sync::atomic::{AtomicBool, Ordering};
diff --git a/src/tools/clippy/tests/ui/must_use_candidates.stderr b/src/tools/clippy/tests/ui/must_use_candidates.stderr
index c64636ba442..2117e37866e 100644
--- a/src/tools/clippy/tests/ui/must_use_candidates.stderr
+++ b/src/tools/clippy/tests/ui/must_use_candidates.stderr
@@ -1,5 +1,5 @@
 error: this function could have a `#[must_use]` attribute
-  --> tests/ui/must_use_candidates.rs:11:1
+  --> tests/ui/must_use_candidates.rs:16:1
    |
 LL | pub fn pure(i: u8) -> u8 {
    | ^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn pure(i: u8) -> u8`
@@ -8,25 +8,25 @@ LL | pub fn pure(i: u8) -> u8 {
    = help: to override `-D warnings` add `#[allow(clippy::must_use_candidate)]`
 
 error: this method could have a `#[must_use]` attribute
-  --> tests/ui/must_use_candidates.rs:16:5
+  --> tests/ui/must_use_candidates.rs:21:5
    |
 LL |     pub fn inherent_pure(&self) -> u8 {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn inherent_pure(&self) -> u8`
 
 error: this function could have a `#[must_use]` attribute
-  --> tests/ui/must_use_candidates.rs:47:1
+  --> tests/ui/must_use_candidates.rs:52:1
    |
 LL | pub fn with_marker(_d: std::marker::PhantomData<&mut u32>) -> bool {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn with_marker(_d: std::marker::PhantomData<&mut u32>) -> bool`
 
 error: this function could have a `#[must_use]` attribute
-  --> tests/ui/must_use_candidates.rs:59:1
+  --> tests/ui/must_use_candidates.rs:64:1
    |
 LL | pub fn rcd(_x: Rc<u32>) -> bool {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn rcd(_x: Rc<u32>) -> bool`
 
 error: this function could have a `#[must_use]` attribute
-  --> tests/ui/must_use_candidates.rs:67:1
+  --> tests/ui/must_use_candidates.rs:72:1
    |
 LL | pub fn arcd(_x: Arc<u32>) -> bool {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn arcd(_x: Arc<u32>) -> bool`
diff --git a/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed b/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed
index 9787bb635e7..3d1c78bd12d 100644
--- a/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed
+++ b/src/tools/clippy/tests/ui/redundant_static_lifetimes.fixed
@@ -1,4 +1,6 @@
 #![allow(unused)]
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
 
 #[derive(Debug)]
 struct Foo;
diff --git a/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs b/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs
index b5a4827fa94..5932f14b8d9 100644
--- a/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs
+++ b/src/tools/clippy/tests/ui/redundant_static_lifetimes.rs
@@ -1,4 +1,6 @@
 #![allow(unused)]
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
 
 #[derive(Debug)]
 struct Foo;
diff --git a/src/tools/clippy/tests/ui/redundant_static_lifetimes.stderr b/src/tools/clippy/tests/ui/redundant_static_lifetimes.stderr
index 5c5e2f2a573..48871eba2dc 100644
--- a/src/tools/clippy/tests/ui/redundant_static_lifetimes.stderr
+++ b/src/tools/clippy/tests/ui/redundant_static_lifetimes.stderr
@@ -1,5 +1,5 @@
 error: constants have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:6:17
+  --> tests/ui/redundant_static_lifetimes.rs:8:17
    |
 LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR: Consider removing 'static.
    |                -^^^^^^^---- help: consider removing `'static`: `&str`
@@ -8,103 +8,103 @@ LL | const VAR_ONE: &'static str = "Test constant #1"; // ERROR: Consider removi
    = help: to override `-D warnings` add `#[allow(clippy::redundant_static_lifetimes)]`
 
 error: constants have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:10:21
+  --> tests/ui/redundant_static_lifetimes.rs:12:21
    |
 LL | const VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR: Consider removing 'static
    |                    -^^^^^^^---- help: consider removing `'static`: `&str`
 
 error: constants have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:12:32
+  --> tests/ui/redundant_static_lifetimes.rs:14:32
    |
 LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static
    |                               -^^^^^^^---- help: consider removing `'static`: `&str`
 
 error: constants have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:12:47
+  --> tests/ui/redundant_static_lifetimes.rs:14:47
    |
 LL | const VAR_FOUR: (&str, (&str, &'static str), &'static str) = ("on", ("th", "th"), "on"); // ERROR: Consider removing 'static
    |                                              -^^^^^^^---- help: consider removing `'static`: `&str`
 
 error: constants have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:14:17
+  --> tests/ui/redundant_static_lifetimes.rs:16:17
    |
 LL | const VAR_SIX: &'static u8 = &5;
    |                -^^^^^^^--- help: consider removing `'static`: `&u8`
 
 error: constants have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:16:20
+  --> tests/ui/redundant_static_lifetimes.rs:18:20
    |
 LL | const VAR_HEIGHT: &'static Foo = &Foo {};
    |                   -^^^^^^^---- help: consider removing `'static`: `&Foo`
 
 error: constants have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:18:19
+  --> tests/ui/redundant_static_lifetimes.rs:20:19
    |
 LL | const VAR_SLICE: &'static [u8] = b"Test constant #1"; // ERROR: Consider removing 'static.
    |                  -^^^^^^^----- help: consider removing `'static`: `&[u8]`
 
 error: constants have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:20:19
+  --> tests/ui/redundant_static_lifetimes.rs:22:19
    |
 LL | const VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR: Consider removing 'static.
    |                  -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)`
 
 error: constants have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:22:19
+  --> tests/ui/redundant_static_lifetimes.rs:24:19
    |
 LL | const VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR: Consider removing 'static.
    |                  -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]`
 
 error: statics have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:24:25
+  --> tests/ui/redundant_static_lifetimes.rs:26:25
    |
 LL | static STATIC_VAR_ONE: &'static str = "Test static #1"; // ERROR: Consider removing 'static.
    |                        -^^^^^^^---- help: consider removing `'static`: `&str`
 
 error: statics have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:28:29
+  --> tests/ui/redundant_static_lifetimes.rs:30:29
    |
 LL | static STATIC_VAR_THREE: &[&'static str] = &["one", "two"]; // ERROR: Consider removing 'static
    |                            -^^^^^^^---- help: consider removing `'static`: `&str`
 
 error: statics have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:30:25
+  --> tests/ui/redundant_static_lifetimes.rs:32:25
    |
 LL | static STATIC_VAR_SIX: &'static u8 = &5;
    |                        -^^^^^^^--- help: consider removing `'static`: `&u8`
 
 error: statics have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:32:28
+  --> tests/ui/redundant_static_lifetimes.rs:34:28
    |
 LL | static STATIC_VAR_HEIGHT: &'static Foo = &Foo {};
    |                           -^^^^^^^---- help: consider removing `'static`: `&Foo`
 
 error: statics have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:34:27
+  --> tests/ui/redundant_static_lifetimes.rs:36:27
    |
 LL | static STATIC_VAR_SLICE: &'static [u8] = b"Test static #3"; // ERROR: Consider removing 'static.
    |                          -^^^^^^^----- help: consider removing `'static`: `&[u8]`
 
 error: statics have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:36:27
+  --> tests/ui/redundant_static_lifetimes.rs:38:27
    |
 LL | static STATIC_VAR_TUPLE: &'static (u8, u8) = &(1, 2); // ERROR: Consider removing 'static.
    |                          -^^^^^^^--------- help: consider removing `'static`: `&(u8, u8)`
 
 error: statics have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:38:27
+  --> tests/ui/redundant_static_lifetimes.rs:40:27
    |
 LL | static STATIC_VAR_ARRAY: &'static [u8; 1] = b"T"; // ERROR: Consider removing 'static.
    |                          -^^^^^^^-------- help: consider removing `'static`: `&[u8; 1]`
 
 error: statics have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:40:31
+  --> tests/ui/redundant_static_lifetimes.rs:42:31
    |
 LL | static mut STATIC_MUT_SLICE: &'static mut [u32] = &mut [0];
    |                              -^^^^^^^---------- help: consider removing `'static`: `&mut [u32]`
 
 error: statics have by default a `'static` lifetime
-  --> tests/ui/redundant_static_lifetimes.rs:69:16
+  --> tests/ui/redundant_static_lifetimes.rs:71:16
    |
 LL |     static V: &'static u8 = &17;
    |               -^^^^^^^--- help: consider removing `'static`: `&u8`
diff --git a/src/tools/clippy/tests/ui/useless_conversion.fixed b/src/tools/clippy/tests/ui/useless_conversion.fixed
index ce00fde2f99..eff617a8016 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.fixed
+++ b/src/tools/clippy/tests/ui/useless_conversion.fixed
@@ -1,5 +1,7 @@
 #![deny(clippy::useless_conversion)]
 #![allow(clippy::needless_if, clippy::unnecessary_wraps)]
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
 
 fn test_generic<T: Copy>(val: T) -> T {
     let _ = val;
diff --git a/src/tools/clippy/tests/ui/useless_conversion.rs b/src/tools/clippy/tests/ui/useless_conversion.rs
index 39979619586..64b06620789 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.rs
+++ b/src/tools/clippy/tests/ui/useless_conversion.rs
@@ -1,5 +1,7 @@
 #![deny(clippy::useless_conversion)]
 #![allow(clippy::needless_if, clippy::unnecessary_wraps)]
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
 
 fn test_generic<T: Copy>(val: T) -> T {
     let _ = T::from(val);
diff --git a/src/tools/clippy/tests/ui/useless_conversion.stderr b/src/tools/clippy/tests/ui/useless_conversion.stderr
index 82f945c5e89..b149357bcf4 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.stderr
+++ b/src/tools/clippy/tests/ui/useless_conversion.stderr
@@ -1,5 +1,5 @@
 error: useless conversion to the same type: `T`
-  --> tests/ui/useless_conversion.rs:5:13
+  --> tests/ui/useless_conversion.rs:7:13
    |
 LL |     let _ = T::from(val);
    |             ^^^^^^^^^^^^ help: consider removing `T::from()`: `val`
@@ -11,217 +11,217 @@ LL | #![deny(clippy::useless_conversion)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: useless conversion to the same type: `T`
-  --> tests/ui/useless_conversion.rs:6:5
+  --> tests/ui/useless_conversion.rs:8:5
    |
 LL |     val.into()
    |     ^^^^^^^^^^ help: consider removing `.into()`: `val`
 
 error: useless conversion to the same type: `i32`
-  --> tests/ui/useless_conversion.rs:18:22
+  --> tests/ui/useless_conversion.rs:20:22
    |
 LL |         let _: i32 = 0i32.into();
    |                      ^^^^^^^^^^^ help: consider removing `.into()`: `0i32`
 
 error: useless conversion to the same type: `std::str::Lines<'_>`
-  --> tests/ui/useless_conversion.rs:48:22
+  --> tests/ui/useless_conversion.rs:50:22
    |
 LL |     if Some("ok") == lines.into_iter().next() {}
    |                      ^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `lines`
 
 error: useless conversion to the same type: `std::str::Lines<'_>`
-  --> tests/ui/useless_conversion.rs:53:21
+  --> tests/ui/useless_conversion.rs:55:21
    |
 LL |     let mut lines = text.lines().into_iter();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `text.lines()`
 
 error: useless conversion to the same type: `std::str::Lines<'_>`
-  --> tests/ui/useless_conversion.rs:59:22
+  --> tests/ui/useless_conversion.rs:61:22
    |
 LL |     if Some("ok") == text.lines().into_iter().next() {}
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `text.lines()`
 
 error: useless conversion to the same type: `std::ops::Range<i32>`
-  --> tests/ui/useless_conversion.rs:65:13
+  --> tests/ui/useless_conversion.rs:67:13
    |
 LL |     let _ = NUMBERS.into_iter().next();
    |             ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS`
 
 error: useless conversion to the same type: `std::ops::Range<i32>`
-  --> tests/ui/useless_conversion.rs:70:17
+  --> tests/ui/useless_conversion.rs:72:17
    |
 LL |     let mut n = NUMBERS.into_iter();
    |                 ^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `NUMBERS`
 
 error: useless conversion to the same type: `std::string::String`
-  --> tests/ui/useless_conversion.rs:132:21
+  --> tests/ui/useless_conversion.rs:134:21
    |
 LL |     let _: String = "foo".to_string().into();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> tests/ui/useless_conversion.rs:133:21
+  --> tests/ui/useless_conversion.rs:135:21
    |
 LL |     let _: String = From::from("foo".to_string());
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> tests/ui/useless_conversion.rs:134:13
+  --> tests/ui/useless_conversion.rs:136:13
    |
 LL |     let _ = String::from("foo".to_string());
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> tests/ui/useless_conversion.rs:135:13
+  --> tests/ui/useless_conversion.rs:137:13
    |
 LL |     let _ = String::from(format!("A: {:04}", 123));
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)`
 
 error: useless conversion to the same type: `std::str::Lines<'_>`
-  --> tests/ui/useless_conversion.rs:136:13
+  --> tests/ui/useless_conversion.rs:138:13
    |
 LL |     let _ = "".lines().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()`
 
 error: useless conversion to the same type: `std::vec::IntoIter<i32>`
-  --> tests/ui/useless_conversion.rs:137:13
+  --> tests/ui/useless_conversion.rs:139:13
    |
 LL |     let _ = vec![1, 2, 3].into_iter().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()`
 
 error: useless conversion to the same type: `std::string::String`
-  --> tests/ui/useless_conversion.rs:138:21
+  --> tests/ui/useless_conversion.rs:140:21
    |
 LL |     let _: String = format!("Hello {}", "world").into();
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `format!("Hello {}", "world")`
 
 error: useless conversion to the same type: `i32`
-  --> tests/ui/useless_conversion.rs:143:13
+  --> tests/ui/useless_conversion.rs:145:13
    |
 LL |     let _ = i32::from(a + b) * 3;
    |             ^^^^^^^^^^^^^^^^ help: consider removing `i32::from()`: `(a + b)`
 
 error: useless conversion to the same type: `Foo<'a'>`
-  --> tests/ui/useless_conversion.rs:149:23
+  --> tests/ui/useless_conversion.rs:151:23
    |
 LL |     let _: Foo<'a'> = s2.into();
    |                       ^^^^^^^^^ help: consider removing `.into()`: `s2`
 
 error: useless conversion to the same type: `Foo<'a'>`
-  --> tests/ui/useless_conversion.rs:151:13
+  --> tests/ui/useless_conversion.rs:153:13
    |
 LL |     let _ = Foo::<'a'>::from(s3);
    |             ^^^^^^^^^^^^^^^^^^^^ help: consider removing `Foo::<'a'>::from()`: `s3`
 
 error: useless conversion to the same type: `std::vec::IntoIter<Foo<'a'>>`
-  --> tests/ui/useless_conversion.rs:153:13
+  --> tests/ui/useless_conversion.rs:155:13
    |
 LL |     let _ = vec![s4, s4, s4].into_iter().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![s4, s4, s4].into_iter()`
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> tests/ui/useless_conversion.rs:185:7
+  --> tests/ui/useless_conversion.rs:187:7
    |
 LL |     b(vec![1, 2].into_iter());
    |       ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> tests/ui/useless_conversion.rs:175:13
+  --> tests/ui/useless_conversion.rs:177:13
    |
 LL |     fn b<T: IntoIterator<Item = i32>>(_: T) {}
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> tests/ui/useless_conversion.rs:186:7
+  --> tests/ui/useless_conversion.rs:188:7
    |
 LL |     c(vec![1, 2].into_iter());
    |       ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> tests/ui/useless_conversion.rs:176:18
+  --> tests/ui/useless_conversion.rs:178:18
    |
 LL |     fn c(_: impl IntoIterator<Item = i32>) {}
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> tests/ui/useless_conversion.rs:187:7
+  --> tests/ui/useless_conversion.rs:189:7
    |
 LL |     d(vec![1, 2].into_iter());
    |       ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> tests/ui/useless_conversion.rs:179:12
+  --> tests/ui/useless_conversion.rs:181:12
    |
 LL |         T: IntoIterator<Item = i32>,
    |            ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> tests/ui/useless_conversion.rs:190:7
+  --> tests/ui/useless_conversion.rs:192:7
    |
 LL |     b(vec![1, 2].into_iter().into_iter());
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`s: `vec![1, 2]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> tests/ui/useless_conversion.rs:175:13
+  --> tests/ui/useless_conversion.rs:177:13
    |
 LL |     fn b<T: IntoIterator<Item = i32>>(_: T) {}
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> tests/ui/useless_conversion.rs:191:7
+  --> tests/ui/useless_conversion.rs:193:7
    |
 LL |     b(vec![1, 2].into_iter().into_iter().into_iter());
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`s: `vec![1, 2]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> tests/ui/useless_conversion.rs:175:13
+  --> tests/ui/useless_conversion.rs:177:13
    |
 LL |     fn b<T: IntoIterator<Item = i32>>(_: T) {}
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> tests/ui/useless_conversion.rs:237:24
+  --> tests/ui/useless_conversion.rs:239:24
    |
 LL |         foo2::<i32, _>([1, 2, 3].into_iter());
    |                        ^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `[1, 2, 3]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> tests/ui/useless_conversion.rs:216:12
+  --> tests/ui/useless_conversion.rs:218:12
    |
 LL |         I: IntoIterator<Item = i32> + Helper<X>,
    |            ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> tests/ui/useless_conversion.rs:245:14
+  --> tests/ui/useless_conversion.rs:247:14
    |
 LL |         foo3([1, 2, 3].into_iter());
    |              ^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `[1, 2, 3]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> tests/ui/useless_conversion.rs:225:12
+  --> tests/ui/useless_conversion.rs:227:12
    |
 LL |         I: IntoIterator<Item = i32>,
    |            ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> tests/ui/useless_conversion.rs:254:16
+  --> tests/ui/useless_conversion.rs:256:16
    |
 LL |         S1.foo([1, 2].into_iter());
    |                ^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `[1, 2]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> tests/ui/useless_conversion.rs:251:27
+  --> tests/ui/useless_conversion.rs:253:27
    |
 LL |             pub fn foo<I: IntoIterator>(&self, _: I) {}
    |                           ^^^^^^^^^^^^
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> tests/ui/useless_conversion.rs:273:44
+  --> tests/ui/useless_conversion.rs:275:44
    |
 LL |         v0.into_iter().interleave_shortest(v1.into_iter());
    |                                            ^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `v1`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> tests/ui/useless_conversion.rs:260:20
+  --> tests/ui/useless_conversion.rs:262:20
    |
 LL |                 J: IntoIterator,
    |                    ^^^^^^^^^^^^
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 5c18179b6fe..414f9f3a7f1 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -183,6 +183,9 @@ pub struct Config {
     /// The rustc executable.
     pub rustc_path: PathBuf,
 
+    /// The cargo executable.
+    pub cargo_path: Option<PathBuf>,
+
     /// The rustdoc executable.
     pub rustdoc_path: Option<PathBuf>,
 
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs
index 933913eb47c..93df6aa7255 100644
--- a/src/tools/compiletest/src/header.rs
+++ b/src/tools/compiletest/src/header.rs
@@ -125,7 +125,7 @@ pub struct TestProps {
     // Build documentation for all specified aux-builds as well
     pub build_aux_docs: bool,
     /// Build the documentation for each crate in a unique output directory.
-    /// Uses <root output directory>/docs/<test name>/doc
+    /// Uses `<root output directory>/docs/<test name>/doc`.
     pub unique_doc_out_dir: bool,
     // Flag to force a crate to be built with the host architecture
     pub force_host: bool,
@@ -1304,12 +1304,12 @@ pub fn llvm_has_libzstd(config: &Config) -> bool {
     false
 }
 
-/// Takes a directive of the form "<version1> [- <version2>]",
-/// returns the numeric representation of <version1> and <version2> as
-/// tuple: (<version1> as u32, <version2> as u32)
+/// Takes a directive of the form `"<version1> [- <version2>]"`,
+/// returns the numeric representation of `<version1>` and `<version2>` as
+/// tuple: `(<version1> as u32, <version2> as u32)`.
 ///
-/// If the <version2> part is omitted, the second component of the tuple
-/// is the same as <version1>.
+/// If the `<version2>` part is omitted, the second component of the tuple
+/// is the same as `<version1>`.
 fn extract_version_range<F>(line: &str, parse: F) -> Option<(u32, u32)>
 where
     F: Fn(&str) -> Option<u32>,
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index 250b5084d13..3339116d542 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -47,6 +47,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
     opts.reqopt("", "compile-lib-path", "path to host shared libraries", "PATH")
         .reqopt("", "run-lib-path", "path to target shared libraries", "PATH")
         .reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH")
+        .optopt("", "cargo-path", "path to cargo to use for compiling", "PATH")
         .optopt("", "rustdoc-path", "path to rustdoc to use for compiling", "PATH")
         .optopt("", "coverage-dump-path", "path to coverage-dump to use in tests", "PATH")
         .reqopt("", "python", "path to python to use for doc tests", "PATH")
@@ -260,6 +261,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
         compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")),
         run_lib_path: make_absolute(opt_path(matches, "run-lib-path")),
         rustc_path: opt_path(matches, "rustc-path"),
+        cargo_path: matches.opt_str("cargo-path").map(PathBuf::from),
         rustdoc_path: matches.opt_str("rustdoc-path").map(PathBuf::from),
         coverage_dump_path: matches.opt_str("coverage-dump-path").map(PathBuf::from),
         python: matches.opt_str("python").unwrap(),
@@ -364,6 +366,7 @@ pub fn log_config(config: &Config) {
     logv(c, format!("compile_lib_path: {:?}", config.compile_lib_path));
     logv(c, format!("run_lib_path: {:?}", config.run_lib_path));
     logv(c, format!("rustc_path: {:?}", config.rustc_path.display()));
+    logv(c, format!("cargo_path: {:?}", config.cargo_path));
     logv(c, format!("rustdoc_path: {:?}", config.rustdoc_path));
     logv(c, format!("src_base: {:?}", config.src_base.display()));
     logv(c, format!("build_base: {:?}", config.build_base.display()));
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index c18f569e528..7b23aa34639 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -2,8 +2,8 @@
 
 use std::borrow::Cow;
 use std::collections::{HashMap, HashSet};
-use std::ffi::{OsStr, OsString};
-use std::fs::{self, create_dir_all, File, OpenOptions};
+use std::ffi::OsString;
+use std::fs::{self, create_dir_all, File};
 use std::hash::{DefaultHasher, Hash, Hasher};
 use std::io::prelude::*;
 use std::io::{self, BufReader};
@@ -14,10 +14,7 @@ use std::{env, iter, str};
 
 use anyhow::Context;
 use colored::Colorize;
-use glob::glob;
-use miropt_test_tools::{files_for_miropt_test, MiroptTest, MiroptTestFile};
 use regex::{Captures, Regex};
-use rustfix::{apply_suggestions, get_suggestions_from_json, Filter};
 use tracing::*;
 
 use crate::common::{
@@ -31,12 +28,29 @@ use crate::compute_diff::{write_diff, write_filtered_diff};
 use crate::errors::{self, Error, ErrorKind};
 use crate::header::TestProps;
 use crate::read2::{read2_abbreviated, Truncated};
-use crate::util::{add_dylib_path, copy_dir_all, dylib_env_var, logv, static_regex, PathBufExt};
-use crate::{extract_gdb_version, is_android_gdb_target, json, ColorConfig};
+use crate::util::{add_dylib_path, logv, static_regex, PathBufExt};
+use crate::{json, ColorConfig};
 
-mod coverage;
 mod debugger;
-use debugger::DebuggerCommands;
+
+// Helper modules that implement test running logic for each test suite.
+// tidy-alphabet-start
+mod assembly;
+mod codegen;
+mod codegen_units;
+mod coverage;
+mod crash;
+mod debuginfo;
+mod incremental;
+mod js_doc;
+mod mir_opt;
+mod pretty;
+mod run_make;
+mod rustdoc;
+mod rustdoc_json;
+mod ui;
+mod valgrind;
+// tidy-alphabet-end
 
 #[cfg(test)]
 mod tests;
@@ -325,81 +339,6 @@ impl<'test> TestCx<'test> {
         }
     }
 
-    fn run_cfail_test(&self) {
-        let pm = self.pass_mode();
-        let proc_res = self.compile_test(WillExecute::No, self.should_emit_metadata(pm));
-        self.check_if_test_should_compile(&proc_res, pm);
-        self.check_no_compiler_crash(&proc_res, self.props.should_ice);
-
-        let output_to_check = self.get_output(&proc_res);
-        let expected_errors = errors::load_errors(&self.testpaths.file, self.revision);
-        if !expected_errors.is_empty() {
-            if !self.props.error_patterns.is_empty() || !self.props.regex_error_patterns.is_empty()
-            {
-                self.fatal("both error pattern and expected errors specified");
-            }
-            self.check_expected_errors(expected_errors, &proc_res);
-        } else {
-            self.check_all_error_patterns(&output_to_check, &proc_res, pm);
-        }
-        if self.props.should_ice {
-            match proc_res.status.code() {
-                Some(101) => (),
-                _ => self.fatal("expected ICE"),
-            }
-        }
-
-        self.check_forbid_output(&output_to_check, &proc_res);
-    }
-
-    fn run_crash_test(&self) {
-        let pm = self.pass_mode();
-        let proc_res = self.compile_test(WillExecute::No, self.should_emit_metadata(pm));
-
-        if std::env::var("COMPILETEST_VERBOSE_CRASHES").is_ok() {
-            eprintln!("{}", proc_res.status);
-            eprintln!("{}", proc_res.stdout);
-            eprintln!("{}", proc_res.stderr);
-            eprintln!("{}", proc_res.cmdline);
-        }
-
-        // if a test does not crash, consider it an error
-        if proc_res.status.success() || matches!(proc_res.status.code(), Some(1 | 0)) {
-            self.fatal(&format!(
-                "crashtest no longer crashes/triggers ICE, horray! Please give it a meaningful name, \
-            add a doc-comment to the start of the test explaining why it exists and \
-            move it to tests/ui or wherever you see fit. Adding 'Fixes #<issueNr>' to your PR description \
-            ensures that the corresponding ticket is auto-closed upon merge."
-            ));
-        }
-    }
-
-    fn run_rfail_test(&self) {
-        let pm = self.pass_mode();
-        let should_run = self.run_if_enabled();
-        let proc_res = self.compile_test(should_run, self.should_emit_metadata(pm));
-
-        if !proc_res.status.success() {
-            self.fatal_proc_rec("compilation failed!", &proc_res);
-        }
-
-        if let WillExecute::Disabled = should_run {
-            return;
-        }
-
-        let proc_res = self.exec_compiled_test();
-
-        // The value our Makefile configures valgrind to return on failure
-        const VALGRIND_ERR: i32 = 100;
-        if proc_res.status.code() == Some(VALGRIND_ERR) {
-            self.fatal_proc_rec("run-fail test isn't valgrind-clean!", &proc_res);
-        }
-
-        let output_to_check = self.get_output(&proc_res);
-        self.check_correct_failure_status(&proc_res);
-        self.check_all_error_patterns(&output_to_check, &proc_res, pm);
-    }
-
     fn get_output(&self, proc_res: &ProcRes) -> String {
         if self.props.check_stdout {
             format!("{}{}", proc_res.stdout, proc_res.stderr)
@@ -423,73 +362,6 @@ impl<'test> TestCx<'test> {
         }
     }
 
-    fn run_cpass_test(&self) {
-        let emit_metadata = self.should_emit_metadata(self.pass_mode());
-        let proc_res = self.compile_test(WillExecute::No, emit_metadata);
-
-        if !proc_res.status.success() {
-            self.fatal_proc_rec("compilation failed!", &proc_res);
-        }
-
-        // FIXME(#41968): Move this check to tidy?
-        if !errors::load_errors(&self.testpaths.file, self.revision).is_empty() {
-            self.fatal("compile-pass tests with expected warnings should be moved to ui/");
-        }
-    }
-
-    fn run_rpass_test(&self) {
-        let emit_metadata = self.should_emit_metadata(self.pass_mode());
-        let should_run = self.run_if_enabled();
-        let proc_res = self.compile_test(should_run, emit_metadata);
-
-        if !proc_res.status.success() {
-            self.fatal_proc_rec("compilation failed!", &proc_res);
-        }
-
-        // FIXME(#41968): Move this check to tidy?
-        if !errors::load_errors(&self.testpaths.file, self.revision).is_empty() {
-            self.fatal("run-pass tests with expected warnings should be moved to ui/");
-        }
-
-        if let WillExecute::Disabled = should_run {
-            return;
-        }
-
-        let proc_res = self.exec_compiled_test();
-        if !proc_res.status.success() {
-            self.fatal_proc_rec("test run failed!", &proc_res);
-        }
-    }
-
-    fn run_valgrind_test(&self) {
-        assert!(self.revision.is_none(), "revisions not relevant here");
-
-        if self.config.valgrind_path.is_none() {
-            assert!(!self.config.force_valgrind);
-            return self.run_rpass_test();
-        }
-
-        let should_run = self.run_if_enabled();
-        let mut proc_res = self.compile_test(should_run, Emit::None);
-
-        if !proc_res.status.success() {
-            self.fatal_proc_rec("compilation failed!", &proc_res);
-        }
-
-        if let WillExecute::Disabled = should_run {
-            return;
-        }
-
-        let mut new_config = self.config.clone();
-        new_config.runner = new_config.valgrind_path.clone();
-        let new_cx = TestCx { config: &new_config, ..*self };
-        proc_res = new_cx.exec_compiled_test();
-
-        if !proc_res.status.success() {
-            self.fatal_proc_rec("test run failed!", &proc_res);
-        }
-    }
-
     /// Runs a [`Command`] and waits for it to finish, then converts its exit
     /// status and output streams into a [`ProcRes`].
     ///
@@ -517,104 +389,6 @@ impl<'test> TestCx<'test> {
         proc_res
     }
 
-    fn run_pretty_test(&self) {
-        if self.props.pp_exact.is_some() {
-            logv(self.config, "testing for exact pretty-printing".to_owned());
-        } else {
-            logv(self.config, "testing for converging pretty-printing".to_owned());
-        }
-
-        let rounds = match self.props.pp_exact {
-            Some(_) => 1,
-            None => 2,
-        };
-
-        let src = fs::read_to_string(&self.testpaths.file).unwrap();
-        let mut srcs = vec![src];
-
-        let mut round = 0;
-        while round < rounds {
-            logv(
-                self.config,
-                format!("pretty-printing round {} revision {:?}", round, self.revision),
-            );
-            let read_from =
-                if round == 0 { ReadFrom::Path } else { ReadFrom::Stdin(srcs[round].to_owned()) };
-
-            let proc_res = self.print_source(read_from, &self.props.pretty_mode);
-            if !proc_res.status.success() {
-                self.fatal_proc_rec(
-                    &format!(
-                        "pretty-printing failed in round {} revision {:?}",
-                        round, self.revision
-                    ),
-                    &proc_res,
-                );
-            }
-
-            let ProcRes { stdout, .. } = proc_res;
-            srcs.push(stdout);
-            round += 1;
-        }
-
-        let mut expected = match self.props.pp_exact {
-            Some(ref file) => {
-                let filepath = self.testpaths.file.parent().unwrap().join(file);
-                fs::read_to_string(&filepath).unwrap()
-            }
-            None => srcs[srcs.len() - 2].clone(),
-        };
-        let mut actual = srcs[srcs.len() - 1].clone();
-
-        if self.props.pp_exact.is_some() {
-            // Now we have to care about line endings
-            let cr = "\r".to_owned();
-            actual = actual.replace(&cr, "");
-            expected = expected.replace(&cr, "");
-        }
-
-        if !self.config.bless {
-            self.compare_source(&expected, &actual);
-        } else if expected != actual {
-            let filepath_buf;
-            let filepath = match &self.props.pp_exact {
-                Some(file) => {
-                    filepath_buf = self.testpaths.file.parent().unwrap().join(file);
-                    &filepath_buf
-                }
-                None => &self.testpaths.file,
-            };
-            fs::write(filepath, &actual).unwrap();
-        }
-
-        // If we're only making sure that the output matches then just stop here
-        if self.props.pretty_compare_only {
-            return;
-        }
-
-        // Finally, let's make sure it actually appears to remain valid code
-        let proc_res = self.typecheck_source(actual);
-        if !proc_res.status.success() {
-            self.fatal_proc_rec("pretty-printed source does not typecheck", &proc_res);
-        }
-
-        if !self.props.pretty_expanded {
-            return;
-        }
-
-        // additionally, run `-Zunpretty=expanded` and try to build it.
-        let proc_res = self.print_source(ReadFrom::Path, "expanded");
-        if !proc_res.status.success() {
-            self.fatal_proc_rec("pretty-printing (expanded) failed", &proc_res);
-        }
-
-        let ProcRes { stdout: expanded_src, .. } = proc_res;
-        let proc_res = self.typecheck_source(expanded_src);
-        if !proc_res.status.success() {
-            self.fatal_proc_rec("pretty-printed source (expanded) does not typecheck", &proc_res);
-        }
-    }
-
     fn print_source(&self, read_from: ReadFrom, pretty_type: &str) -> ProcRes {
         let aux_dir = self.aux_output_dir_name();
         let input: &str = match read_from {
@@ -727,500 +501,6 @@ impl<'test> TestCx<'test> {
         self.compose_and_run_compiler(rustc, Some(src), self.testpaths)
     }
 
-    fn run_debuginfo_test(&self) {
-        match self.config.debugger.unwrap() {
-            Debugger::Cdb => self.run_debuginfo_cdb_test(),
-            Debugger::Gdb => self.run_debuginfo_gdb_test(),
-            Debugger::Lldb => self.run_debuginfo_lldb_test(),
-        }
-    }
-
-    fn run_debuginfo_cdb_test(&self) {
-        let config = Config {
-            target_rustcflags: self.cleanup_debug_info_options(&self.config.target_rustcflags),
-            host_rustcflags: self.cleanup_debug_info_options(&self.config.host_rustcflags),
-            ..self.config.clone()
-        };
-
-        let test_cx = TestCx { config: &config, ..*self };
-
-        test_cx.run_debuginfo_cdb_test_no_opt();
-    }
-
-    fn run_debuginfo_cdb_test_no_opt(&self) {
-        let exe_file = self.make_exe_name();
-
-        // Existing PDB files are update in-place. When changing the debuginfo
-        // the compiler generates for something, this can lead to the situation
-        // where both the old and the new version of the debuginfo for the same
-        // type is present in the PDB, which is very confusing.
-        // Therefore we delete any existing PDB file before compiling the test
-        // case.
-        // FIXME: If can reliably detect that MSVC's link.exe is used, then
-        //        passing `/INCREMENTAL:NO` might be a cleaner way to do this.
-        let pdb_file = exe_file.with_extension(".pdb");
-        if pdb_file.exists() {
-            std::fs::remove_file(pdb_file).unwrap();
-        }
-
-        // compile test file (it should have 'compile-flags:-g' in the header)
-        let should_run = self.run_if_enabled();
-        let compile_result = self.compile_test(should_run, Emit::None);
-        if !compile_result.status.success() {
-            self.fatal_proc_rec("compilation failed!", &compile_result);
-        }
-        if let WillExecute::Disabled = should_run {
-            return;
-        }
-
-        let prefixes = {
-            static PREFIXES: &[&str] = &["cdb", "cdbg"];
-            // No "native rust support" variation for CDB yet.
-            PREFIXES
-        };
-
-        // Parse debugger commands etc from test files
-        let dbg_cmds = DebuggerCommands::parse_from(
-            &self.testpaths.file,
-            self.config,
-            prefixes,
-            self.revision,
-        )
-        .unwrap_or_else(|e| self.fatal(&e));
-
-        // https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-commands
-        let mut script_str = String::with_capacity(2048);
-        script_str.push_str("version\n"); // List CDB (and more) version info in test output
-        script_str.push_str(".nvlist\n"); // List loaded `*.natvis` files, bulk of custom MSVC debug
-
-        // If a .js file exists next to the source file being tested, then this is a JavaScript
-        // debugging extension that needs to be loaded.
-        let mut js_extension = self.testpaths.file.clone();
-        js_extension.set_extension("cdb.js");
-        if js_extension.exists() {
-            script_str.push_str(&format!(".scriptload \"{}\"\n", js_extension.to_string_lossy()));
-        }
-
-        // Set breakpoints on every line that contains the string "#break"
-        let source_file_name = self.testpaths.file.file_name().unwrap().to_string_lossy();
-        for line in &dbg_cmds.breakpoint_lines {
-            script_str.push_str(&format!("bp `{}:{}`\n", source_file_name, line));
-        }
-
-        // Append the other `cdb-command:`s
-        for line in &dbg_cmds.commands {
-            script_str.push_str(line);
-            script_str.push('\n');
-        }
-
-        script_str.push_str("qq\n"); // Quit the debugger (including remote debugger, if any)
-
-        // Write the script into a file
-        debug!("script_str = {}", script_str);
-        self.dump_output_file(&script_str, "debugger.script");
-        let debugger_script = self.make_out_name("debugger.script");
-
-        let cdb_path = &self.config.cdb.as_ref().unwrap();
-        let mut cdb = Command::new(cdb_path);
-        cdb.arg("-lines") // Enable source line debugging.
-            .arg("-cf")
-            .arg(&debugger_script)
-            .arg(&exe_file);
-
-        let debugger_run_result = self.compose_and_run(
-            cdb,
-            self.config.run_lib_path.to_str().unwrap(),
-            None, // aux_path
-            None, // input
-        );
-
-        if !debugger_run_result.status.success() {
-            self.fatal_proc_rec("Error while running CDB", &debugger_run_result);
-        }
-
-        if let Err(e) = dbg_cmds.check_output(&debugger_run_result) {
-            self.fatal_proc_rec(&e, &debugger_run_result);
-        }
-    }
-
-    fn run_debuginfo_gdb_test(&self) {
-        let config = Config {
-            target_rustcflags: self.cleanup_debug_info_options(&self.config.target_rustcflags),
-            host_rustcflags: self.cleanup_debug_info_options(&self.config.host_rustcflags),
-            ..self.config.clone()
-        };
-
-        let test_cx = TestCx { config: &config, ..*self };
-
-        test_cx.run_debuginfo_gdb_test_no_opt();
-    }
-
-    fn run_debuginfo_gdb_test_no_opt(&self) {
-        let dbg_cmds = DebuggerCommands::parse_from(
-            &self.testpaths.file,
-            self.config,
-            &["gdb"],
-            self.revision,
-        )
-        .unwrap_or_else(|e| self.fatal(&e));
-        let mut cmds = dbg_cmds.commands.join("\n");
-
-        // compile test file (it should have 'compile-flags:-g' in the header)
-        let should_run = self.run_if_enabled();
-        let compiler_run_result = self.compile_test(should_run, Emit::None);
-        if !compiler_run_result.status.success() {
-            self.fatal_proc_rec("compilation failed!", &compiler_run_result);
-        }
-        if let WillExecute::Disabled = should_run {
-            return;
-        }
-
-        let exe_file = self.make_exe_name();
-
-        let debugger_run_result;
-        if is_android_gdb_target(&self.config.target) {
-            cmds = cmds.replace("run", "continue");
-
-            let tool_path = match self.config.android_cross_path.to_str() {
-                Some(x) => x.to_owned(),
-                None => self.fatal("cannot find android cross path"),
-            };
-
-            // write debugger script
-            let mut script_str = String::with_capacity(2048);
-            script_str.push_str(&format!("set charset {}\n", Self::charset()));
-            script_str.push_str(&format!("set sysroot {}\n", tool_path));
-            script_str.push_str(&format!("file {}\n", exe_file.to_str().unwrap()));
-            script_str.push_str("target remote :5039\n");
-            script_str.push_str(&format!(
-                "set solib-search-path \
-                 ./{}/stage2/lib/rustlib/{}/lib/\n",
-                self.config.host, self.config.target
-            ));
-            for line in &dbg_cmds.breakpoint_lines {
-                script_str.push_str(
-                    format!(
-                        "break {:?}:{}\n",
-                        self.testpaths.file.file_name().unwrap().to_string_lossy(),
-                        *line
-                    )
-                    .as_str(),
-                );
-            }
-            script_str.push_str(&cmds);
-            script_str.push_str("\nquit\n");
-
-            debug!("script_str = {}", script_str);
-            self.dump_output_file(&script_str, "debugger.script");
-
-            let adb_path = &self.config.adb_path;
-
-            Command::new(adb_path)
-                .arg("push")
-                .arg(&exe_file)
-                .arg(&self.config.adb_test_dir)
-                .status()
-                .unwrap_or_else(|e| panic!("failed to exec `{adb_path:?}`: {e:?}"));
-
-            Command::new(adb_path)
-                .args(&["forward", "tcp:5039", "tcp:5039"])
-                .status()
-                .unwrap_or_else(|e| panic!("failed to exec `{adb_path:?}`: {e:?}"));
-
-            let adb_arg = format!(
-                "export LD_LIBRARY_PATH={}; \
-                 gdbserver{} :5039 {}/{}",
-                self.config.adb_test_dir.clone(),
-                if self.config.target.contains("aarch64") { "64" } else { "" },
-                self.config.adb_test_dir.clone(),
-                exe_file.file_name().unwrap().to_str().unwrap()
-            );
-
-            debug!("adb arg: {}", adb_arg);
-            let mut adb = Command::new(adb_path)
-                .args(&["shell", &adb_arg])
-                .stdout(Stdio::piped())
-                .stderr(Stdio::inherit())
-                .spawn()
-                .unwrap_or_else(|e| panic!("failed to exec `{adb_path:?}`: {e:?}"));
-
-            // Wait for the gdbserver to print out "Listening on port ..."
-            // at which point we know that it's started and then we can
-            // execute the debugger below.
-            let mut stdout = BufReader::new(adb.stdout.take().unwrap());
-            let mut line = String::new();
-            loop {
-                line.truncate(0);
-                stdout.read_line(&mut line).unwrap();
-                if line.starts_with("Listening on port 5039") {
-                    break;
-                }
-            }
-            drop(stdout);
-
-            let mut debugger_script = OsString::from("-command=");
-            debugger_script.push(self.make_out_name("debugger.script"));
-            let debugger_opts: &[&OsStr] =
-                &["-quiet".as_ref(), "-batch".as_ref(), "-nx".as_ref(), &debugger_script];
-
-            let gdb_path = self.config.gdb.as_ref().unwrap();
-            let Output { status, stdout, stderr } = Command::new(&gdb_path)
-                .args(debugger_opts)
-                .output()
-                .unwrap_or_else(|e| panic!("failed to exec `{gdb_path:?}`: {e:?}"));
-            let cmdline = {
-                let mut gdb = Command::new(&format!("{}-gdb", self.config.target));
-                gdb.args(debugger_opts);
-                let cmdline = self.make_cmdline(&gdb, "");
-                logv(self.config, format!("executing {}", cmdline));
-                cmdline
-            };
-
-            debugger_run_result = ProcRes {
-                status,
-                stdout: String::from_utf8(stdout).unwrap(),
-                stderr: String::from_utf8(stderr).unwrap(),
-                truncated: Truncated::No,
-                cmdline,
-            };
-            if adb.kill().is_err() {
-                println!("Adb process is already finished.");
-            }
-        } else {
-            let rust_src_root =
-                self.config.find_rust_src_root().expect("Could not find Rust source root");
-            let rust_pp_module_rel_path = Path::new("./src/etc");
-            let rust_pp_module_abs_path =
-                rust_src_root.join(rust_pp_module_rel_path).to_str().unwrap().to_owned();
-            // write debugger script
-            let mut script_str = String::with_capacity(2048);
-            script_str.push_str(&format!("set charset {}\n", Self::charset()));
-            script_str.push_str("show version\n");
-
-            match self.config.gdb_version {
-                Some(version) => {
-                    println!("NOTE: compiletest thinks it is using GDB version {}", version);
-
-                    if version > extract_gdb_version("7.4").unwrap() {
-                        // Add the directory containing the pretty printers to
-                        // GDB's script auto loading safe path
-                        script_str.push_str(&format!(
-                            "add-auto-load-safe-path {}\n",
-                            rust_pp_module_abs_path.replace(r"\", r"\\")
-                        ));
-
-                        let output_base_dir = self.output_base_dir().to_str().unwrap().to_owned();
-
-                        // Add the directory containing the output binary to
-                        // include embedded pretty printers to GDB's script
-                        // auto loading safe path
-                        script_str.push_str(&format!(
-                            "add-auto-load-safe-path {}\n",
-                            output_base_dir.replace(r"\", r"\\")
-                        ));
-                    }
-                }
-                _ => {
-                    println!(
-                        "NOTE: compiletest does not know which version of \
-                         GDB it is using"
-                    );
-                }
-            }
-
-            // The following line actually doesn't have to do anything with
-            // pretty printing, it just tells GDB to print values on one line:
-            script_str.push_str("set print pretty off\n");
-
-            // Add the pretty printer directory to GDB's source-file search path
-            script_str
-                .push_str(&format!("directory {}\n", rust_pp_module_abs_path.replace(r"\", r"\\")));
-
-            // Load the target executable
-            script_str
-                .push_str(&format!("file {}\n", exe_file.to_str().unwrap().replace(r"\", r"\\")));
-
-            // Force GDB to print values in the Rust format.
-            script_str.push_str("set language rust\n");
-
-            // Add line breakpoints
-            for line in &dbg_cmds.breakpoint_lines {
-                script_str.push_str(&format!(
-                    "break '{}':{}\n",
-                    self.testpaths.file.file_name().unwrap().to_string_lossy(),
-                    *line
-                ));
-            }
-
-            script_str.push_str(&cmds);
-            script_str.push_str("\nquit\n");
-
-            debug!("script_str = {}", script_str);
-            self.dump_output_file(&script_str, "debugger.script");
-
-            let mut debugger_script = OsString::from("-command=");
-            debugger_script.push(self.make_out_name("debugger.script"));
-
-            let debugger_opts: &[&OsStr] =
-                &["-quiet".as_ref(), "-batch".as_ref(), "-nx".as_ref(), &debugger_script];
-
-            let mut gdb = Command::new(self.config.gdb.as_ref().unwrap());
-            let pythonpath = if let Ok(pp) = std::env::var("PYTHONPATH") {
-                format!("{pp}:{rust_pp_module_abs_path}")
-            } else {
-                rust_pp_module_abs_path
-            };
-            gdb.args(debugger_opts).env("PYTHONPATH", pythonpath);
-
-            debugger_run_result =
-                self.compose_and_run(gdb, self.config.run_lib_path.to_str().unwrap(), None, None);
-        }
-
-        if !debugger_run_result.status.success() {
-            self.fatal_proc_rec("gdb failed to execute", &debugger_run_result);
-        }
-
-        if let Err(e) = dbg_cmds.check_output(&debugger_run_result) {
-            self.fatal_proc_rec(&e, &debugger_run_result);
-        }
-    }
-
-    fn run_debuginfo_lldb_test(&self) {
-        if self.config.lldb_python_dir.is_none() {
-            self.fatal("Can't run LLDB test because LLDB's python path is not set.");
-        }
-
-        let config = Config {
-            target_rustcflags: self.cleanup_debug_info_options(&self.config.target_rustcflags),
-            host_rustcflags: self.cleanup_debug_info_options(&self.config.host_rustcflags),
-            ..self.config.clone()
-        };
-
-        let test_cx = TestCx { config: &config, ..*self };
-
-        test_cx.run_debuginfo_lldb_test_no_opt();
-    }
-
-    fn run_debuginfo_lldb_test_no_opt(&self) {
-        // compile test file (it should have 'compile-flags:-g' in the header)
-        let should_run = self.run_if_enabled();
-        let compile_result = self.compile_test(should_run, Emit::None);
-        if !compile_result.status.success() {
-            self.fatal_proc_rec("compilation failed!", &compile_result);
-        }
-        if let WillExecute::Disabled = should_run {
-            return;
-        }
-
-        let exe_file = self.make_exe_name();
-
-        match self.config.lldb_version {
-            Some(ref version) => {
-                println!("NOTE: compiletest thinks it is using LLDB version {}", version);
-            }
-            _ => {
-                println!(
-                    "NOTE: compiletest does not know which version of \
-                     LLDB it is using"
-                );
-            }
-        }
-
-        // Parse debugger commands etc from test files
-        let dbg_cmds = DebuggerCommands::parse_from(
-            &self.testpaths.file,
-            self.config,
-            &["lldb"],
-            self.revision,
-        )
-        .unwrap_or_else(|e| self.fatal(&e));
-
-        // Write debugger script:
-        // We don't want to hang when calling `quit` while the process is still running
-        let mut script_str = String::from("settings set auto-confirm true\n");
-
-        // Make LLDB emit its version, so we have it documented in the test output
-        script_str.push_str("version\n");
-
-        // Switch LLDB into "Rust mode"
-        let rust_src_root =
-            self.config.find_rust_src_root().expect("Could not find Rust source root");
-        let rust_pp_module_rel_path = Path::new("./src/etc");
-        let rust_pp_module_abs_path = rust_src_root.join(rust_pp_module_rel_path);
-
-        script_str.push_str(&format!(
-            "command script import {}/lldb_lookup.py\n",
-            rust_pp_module_abs_path.to_str().unwrap()
-        ));
-        File::open(rust_pp_module_abs_path.join("lldb_commands"))
-            .and_then(|mut file| file.read_to_string(&mut script_str))
-            .expect("Failed to read lldb_commands");
-
-        // Set breakpoints on every line that contains the string "#break"
-        let source_file_name = self.testpaths.file.file_name().unwrap().to_string_lossy();
-        for line in &dbg_cmds.breakpoint_lines {
-            script_str.push_str(&format!(
-                "breakpoint set --file '{}' --line {}\n",
-                source_file_name, line
-            ));
-        }
-
-        // Append the other commands
-        for line in &dbg_cmds.commands {
-            script_str.push_str(line);
-            script_str.push('\n');
-        }
-
-        // Finally, quit the debugger
-        script_str.push_str("\nquit\n");
-
-        // Write the script into a file
-        debug!("script_str = {}", script_str);
-        self.dump_output_file(&script_str, "debugger.script");
-        let debugger_script = self.make_out_name("debugger.script");
-
-        // Let LLDB execute the script via lldb_batchmode.py
-        let debugger_run_result = self.run_lldb(&exe_file, &debugger_script, &rust_src_root);
-
-        if !debugger_run_result.status.success() {
-            self.fatal_proc_rec("Error while running LLDB", &debugger_run_result);
-        }
-
-        if let Err(e) = dbg_cmds.check_output(&debugger_run_result) {
-            self.fatal_proc_rec(&e, &debugger_run_result);
-        }
-    }
-
-    fn run_lldb(
-        &self,
-        test_executable: &Path,
-        debugger_script: &Path,
-        rust_src_root: &Path,
-    ) -> ProcRes {
-        // Prepare the lldb_batchmode which executes the debugger script
-        let lldb_script_path = rust_src_root.join("src/etc/lldb_batchmode.py");
-        let pythonpath = if let Ok(pp) = std::env::var("PYTHONPATH") {
-            format!("{pp}:{}", self.config.lldb_python_dir.as_ref().unwrap())
-        } else {
-            self.config.lldb_python_dir.as_ref().unwrap().to_string()
-        };
-        self.run_command_to_procres(
-            Command::new(&self.config.python)
-                .arg(&lldb_script_path)
-                .arg(test_executable)
-                .arg(debugger_script)
-                .env("PYTHONUNBUFFERED", "1") // Help debugging #78665
-                .env("PYTHONPATH", pythonpath),
-        )
-    }
-
-    fn cleanup_debug_info_options(&self, options: &Vec<String>) -> Vec<String> {
-        // Remove options that are either unwanted (-O) or may lead to duplicates due to RUSTFLAGS.
-        let options_to_remove = ["-O".to_owned(), "-g".to_owned(), "--debuginfo".to_owned()];
-
-        options.iter().filter(|x| !options_to_remove.contains(x)).cloned().collect()
-    }
-
     fn maybe_add_external_args(&self, cmd: &mut Command, args: &Vec<String>) {
         // Filter out the arguments that should not be added by runtest here.
         //
@@ -2016,6 +1296,14 @@ impl<'test> TestCx<'test> {
             || self.config.src_base.ends_with("rustdoc-json")
     }
 
+    fn get_mir_dump_dir(&self) -> PathBuf {
+        let mut mir_dump_dir = PathBuf::from(self.config.build_base.as_path());
+        debug!("input_file: {:?}", self.testpaths.file);
+        mir_dump_dir.push(&self.testpaths.relative_dir);
+        mir_dump_dir.push(self.testpaths.file.file_stem().unwrap());
+        mir_dump_dir
+    }
+
     fn make_compile_args(
         &self,
         input_file: &Path,
@@ -2626,75 +1914,11 @@ impl<'test> TestCx<'test> {
         self.compose_and_run(filecheck, "", None, None)
     }
 
-    fn run_codegen_test(&self) {
-        if self.config.llvm_filecheck.is_none() {
-            self.fatal("missing --llvm-filecheck");
-        }
-
-        let (proc_res, output_path) = self.compile_test_and_save_ir();
-        if !proc_res.status.success() {
-            self.fatal_proc_rec("compilation failed!", &proc_res);
-        }
-
-        if let Some(PassMode::Build) = self.pass_mode() {
-            return;
-        }
-        let proc_res = self.verify_with_filecheck(&output_path);
-        if !proc_res.status.success() {
-            self.fatal_proc_rec("verification with 'FileCheck' failed", &proc_res);
-        }
-    }
-
-    fn run_assembly_test(&self) {
-        if self.config.llvm_filecheck.is_none() {
-            self.fatal("missing --llvm-filecheck");
-        }
-
-        let (proc_res, output_path) = self.compile_test_and_save_assembly();
-        if !proc_res.status.success() {
-            self.fatal_proc_rec("compilation failed!", &proc_res);
-        }
-
-        let proc_res = self.verify_with_filecheck(&output_path);
-        if !proc_res.status.success() {
-            self.fatal_proc_rec("verification with 'FileCheck' failed", &proc_res);
-        }
-    }
-
     fn charset() -> &'static str {
         // FreeBSD 10.1 defaults to GDB 6.1.1 which doesn't support "auto" charset
         if cfg!(target_os = "freebsd") { "ISO-8859-1" } else { "UTF-8" }
     }
 
-    fn run_rustdoc_test(&self) {
-        assert!(self.revision.is_none(), "revisions not relevant here");
-
-        let out_dir = self.output_base_dir();
-        remove_and_create_dir_all(&out_dir);
-
-        let proc_res = self.document(&out_dir, &self.testpaths);
-        if !proc_res.status.success() {
-            self.fatal_proc_rec("rustdoc failed!", &proc_res);
-        }
-
-        if self.props.check_test_line_numbers_match {
-            self.check_rustdoc_test_option(proc_res);
-        } else {
-            let root = self.config.find_rust_src_root().unwrap();
-            let mut cmd = Command::new(&self.config.python);
-            cmd.arg(root.join("src/etc/htmldocck.py")).arg(&out_dir).arg(&self.testpaths.file);
-            if self.config.bless {
-                cmd.arg("--bless");
-            }
-            let res = self.run_command_to_procres(&mut cmd);
-            if !res.status.success() {
-                self.fatal_proc_rec_with_ctx("htmldocck failed!", &res, |mut this| {
-                    this.compare_to_default_rustdoc(&out_dir)
-                });
-            }
-        }
-    }
-
     fn compare_to_default_rustdoc(&mut self, out_dir: &Path) {
         if !self.config.has_tidy {
             return;
@@ -2847,49 +2071,6 @@ impl<'test> TestCx<'test> {
         };
     }
 
-    fn run_rustdoc_json_test(&self) {
-        //FIXME: Add bless option.
-
-        assert!(self.revision.is_none(), "revisions not relevant here");
-
-        let out_dir = self.output_base_dir();
-        remove_and_create_dir_all(&out_dir);
-
-        let proc_res = self.document(&out_dir, &self.testpaths);
-        if !proc_res.status.success() {
-            self.fatal_proc_rec("rustdoc failed!", &proc_res);
-        }
-
-        let root = self.config.find_rust_src_root().unwrap();
-        let mut json_out = out_dir.join(self.testpaths.file.file_stem().unwrap());
-        json_out.set_extension("json");
-        let res = self.run_command_to_procres(
-            Command::new(self.config.jsondocck_path.as_ref().unwrap())
-                .arg("--doc-dir")
-                .arg(root.join(&out_dir))
-                .arg("--template")
-                .arg(&self.testpaths.file),
-        );
-
-        if !res.status.success() {
-            self.fatal_proc_rec_with_ctx("jsondocck failed!", &res, |_| {
-                println!("Rustdoc Output:");
-                proc_res.print_info();
-            })
-        }
-
-        let mut json_out = out_dir.join(self.testpaths.file.file_stem().unwrap());
-        json_out.set_extension("json");
-
-        let res = self.run_command_to_procres(
-            Command::new(self.config.jsondoclint_path.as_ref().unwrap()).arg(&json_out),
-        );
-
-        if !res.status.success() {
-            self.fatal_proc_rec("jsondoclint failed!", &res);
-        }
-    }
-
     fn get_lines<P: AsRef<Path>>(
         &self,
         path: &P,
@@ -2990,824 +2171,6 @@ impl<'test> TestCx<'test> {
         }
     }
 
-    fn run_codegen_units_test(&self) {
-        assert!(self.revision.is_none(), "revisions not relevant here");
-
-        let proc_res = self.compile_test(WillExecute::No, Emit::None);
-
-        if !proc_res.status.success() {
-            self.fatal_proc_rec("compilation failed!", &proc_res);
-        }
-
-        self.check_no_compiler_crash(&proc_res, self.props.should_ice);
-
-        const PREFIX: &str = "MONO_ITEM ";
-        const CGU_MARKER: &str = "@@";
-
-        // Some MonoItems can contain {closure@/path/to/checkout/tests/codgen-units/test.rs}
-        // To prevent the current dir from leaking, we just replace the entire path to the test
-        // file with TEST_PATH.
-        let actual: Vec<MonoItem> = proc_res
-            .stdout
-            .lines()
-            .filter(|line| line.starts_with(PREFIX))
-            .map(|line| {
-                line.replace(&self.testpaths.file.display().to_string(), "TEST_PATH").to_string()
-            })
-            .map(|line| str_to_mono_item(&line, true))
-            .collect();
-
-        let expected: Vec<MonoItem> = errors::load_errors(&self.testpaths.file, None)
-            .iter()
-            .map(|e| str_to_mono_item(&e.msg[..], false))
-            .collect();
-
-        let mut missing = Vec::new();
-        let mut wrong_cgus = Vec::new();
-
-        for expected_item in &expected {
-            let actual_item_with_same_name = actual.iter().find(|ti| ti.name == expected_item.name);
-
-            if let Some(actual_item) = actual_item_with_same_name {
-                if !expected_item.codegen_units.is_empty() &&
-                   // Also check for codegen units
-                   expected_item.codegen_units != actual_item.codegen_units
-                {
-                    wrong_cgus.push((expected_item.clone(), actual_item.clone()));
-                }
-            } else {
-                missing.push(expected_item.string.clone());
-            }
-        }
-
-        let unexpected: Vec<_> = actual
-            .iter()
-            .filter(|acgu| !expected.iter().any(|ecgu| acgu.name == ecgu.name))
-            .map(|acgu| acgu.string.clone())
-            .collect();
-
-        if !missing.is_empty() {
-            missing.sort();
-
-            println!("\nThese items should have been contained but were not:\n");
-
-            for item in &missing {
-                println!("{}", item);
-            }
-
-            println!("\n");
-        }
-
-        if !unexpected.is_empty() {
-            let sorted = {
-                let mut sorted = unexpected.clone();
-                sorted.sort();
-                sorted
-            };
-
-            println!("\nThese items were contained but should not have been:\n");
-
-            for item in sorted {
-                println!("{}", item);
-            }
-
-            println!("\n");
-        }
-
-        if !wrong_cgus.is_empty() {
-            wrong_cgus.sort_by_key(|pair| pair.0.name.clone());
-            println!("\nThe following items were assigned to wrong codegen units:\n");
-
-            for &(ref expected_item, ref actual_item) in &wrong_cgus {
-                println!("{}", expected_item.name);
-                println!("  expected: {}", codegen_units_to_str(&expected_item.codegen_units));
-                println!("  actual:   {}", codegen_units_to_str(&actual_item.codegen_units));
-                println!();
-            }
-        }
-
-        if !(missing.is_empty() && unexpected.is_empty() && wrong_cgus.is_empty()) {
-            panic!();
-        }
-
-        #[derive(Clone, Eq, PartialEq)]
-        struct MonoItem {
-            name: String,
-            codegen_units: HashSet<String>,
-            string: String,
-        }
-
-        // [MONO_ITEM] name [@@ (cgu)+]
-        fn str_to_mono_item(s: &str, cgu_has_crate_disambiguator: bool) -> MonoItem {
-            let s = if s.starts_with(PREFIX) { (&s[PREFIX.len()..]).trim() } else { s.trim() };
-
-            let full_string = format!("{}{}", PREFIX, s);
-
-            let parts: Vec<&str> =
-                s.split(CGU_MARKER).map(str::trim).filter(|s| !s.is_empty()).collect();
-
-            let name = parts[0].trim();
-
-            let cgus = if parts.len() > 1 {
-                let cgus_str = parts[1];
-
-                cgus_str
-                    .split(' ')
-                    .map(str::trim)
-                    .filter(|s| !s.is_empty())
-                    .map(|s| {
-                        if cgu_has_crate_disambiguator {
-                            remove_crate_disambiguators_from_set_of_cgu_names(s)
-                        } else {
-                            s.to_string()
-                        }
-                    })
-                    .collect()
-            } else {
-                HashSet::new()
-            };
-
-            MonoItem { name: name.to_owned(), codegen_units: cgus, string: full_string }
-        }
-
-        fn codegen_units_to_str(cgus: &HashSet<String>) -> String {
-            let mut cgus: Vec<_> = cgus.iter().collect();
-            cgus.sort();
-
-            let mut string = String::new();
-            for cgu in cgus {
-                string.push_str(&cgu[..]);
-                string.push(' ');
-            }
-
-            string
-        }
-
-        // Given a cgu-name-prefix of the form <crate-name>.<crate-disambiguator> or
-        // the form <crate-name1>.<crate-disambiguator1>-in-<crate-name2>.<crate-disambiguator2>,
-        // remove all crate-disambiguators.
-        fn remove_crate_disambiguator_from_cgu(cgu: &str) -> String {
-            let Some(captures) =
-                static_regex!(r"^[^\.]+(?P<d1>\.[[:alnum:]]+)(-in-[^\.]+(?P<d2>\.[[:alnum:]]+))?")
-                    .captures(cgu)
-            else {
-                panic!("invalid cgu name encountered: {cgu}");
-            };
-
-            let mut new_name = cgu.to_owned();
-
-            if let Some(d2) = captures.name("d2") {
-                new_name.replace_range(d2.start()..d2.end(), "");
-            }
-
-            let d1 = captures.name("d1").unwrap();
-            new_name.replace_range(d1.start()..d1.end(), "");
-
-            new_name
-        }
-
-        // The name of merged CGUs is constructed as the names of the original
-        // CGUs joined with "--". This function splits such composite CGU names
-        // and handles each component individually.
-        fn remove_crate_disambiguators_from_set_of_cgu_names(cgus: &str) -> String {
-            cgus.split("--").map(remove_crate_disambiguator_from_cgu).collect::<Vec<_>>().join("--")
-        }
-    }
-
-    fn init_incremental_test(&self) {
-        // (See `run_incremental_test` for an overview of how incremental tests work.)
-
-        // Before any of the revisions have executed, create the
-        // incremental workproduct directory.  Delete any old
-        // incremental work products that may be there from prior
-        // runs.
-        let incremental_dir = self.props.incremental_dir.as_ref().unwrap();
-        if incremental_dir.exists() {
-            // Canonicalizing the path will convert it to the //?/ format
-            // on Windows, which enables paths longer than 260 character
-            let canonicalized = incremental_dir.canonicalize().unwrap();
-            fs::remove_dir_all(canonicalized).unwrap();
-        }
-        fs::create_dir_all(&incremental_dir).unwrap();
-
-        if self.config.verbose {
-            println!("init_incremental_test: incremental_dir={}", incremental_dir.display());
-        }
-    }
-
-    fn run_incremental_test(&self) {
-        // Basic plan for a test incremental/foo/bar.rs:
-        // - load list of revisions rpass1, cfail2, rpass3
-        //   - each should begin with `cpass`, `rpass`, `cfail`, or `rfail`
-        //   - if `cpass`, expect compilation to succeed, don't execute
-        //   - if `rpass`, expect compilation and execution to succeed
-        //   - if `cfail`, expect compilation to fail
-        //   - if `rfail`, expect compilation to succeed and execution to fail
-        // - create a directory build/foo/bar.incremental
-        // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C rpass1
-        //   - because name of revision starts with "rpass", expect success
-        // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C cfail2
-        //   - because name of revision starts with "cfail", expect an error
-        //   - load expected errors as usual, but filter for those that end in `[rfail2]`
-        // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C rpass3
-        //   - because name of revision starts with "rpass", expect success
-        // - execute build/foo/bar.exe and save output
-        //
-        // FIXME -- use non-incremental mode as an oracle? That doesn't apply
-        // to #[rustc_dirty] and clean tests I guess
-
-        let revision = self.revision.expect("incremental tests require a list of revisions");
-
-        // Incremental workproduct directory should have already been created.
-        let incremental_dir = self.props.incremental_dir.as_ref().unwrap();
-        assert!(incremental_dir.exists(), "init_incremental_test failed to create incremental dir");
-
-        if self.config.verbose {
-            print!("revision={:?} props={:#?}", revision, self.props);
-        }
-
-        if revision.starts_with("cpass") {
-            if self.props.should_ice {
-                self.fatal("can only use should-ice in cfail tests");
-            }
-            self.run_cpass_test();
-        } else if revision.starts_with("rpass") {
-            if self.props.should_ice {
-                self.fatal("can only use should-ice in cfail tests");
-            }
-            self.run_rpass_test();
-        } else if revision.starts_with("rfail") {
-            if self.props.should_ice {
-                self.fatal("can only use should-ice in cfail tests");
-            }
-            self.run_rfail_test();
-        } else if revision.starts_with("cfail") {
-            self.run_cfail_test();
-        } else {
-            self.fatal("revision name must begin with cpass, rpass, rfail, or cfail");
-        }
-    }
-
-    fn run_rmake_test(&self) {
-        let test_dir = &self.testpaths.file;
-        if test_dir.join("rmake.rs").exists() {
-            self.run_rmake_v2_test();
-        } else if test_dir.join("Makefile").exists() {
-            self.run_rmake_legacy_test();
-        } else {
-            self.fatal("failed to find either `rmake.rs` or `Makefile`")
-        }
-    }
-
-    fn run_rmake_legacy_test(&self) {
-        let cwd = env::current_dir().unwrap();
-        let src_root = self.config.src_base.parent().unwrap().parent().unwrap();
-        let src_root = cwd.join(&src_root);
-
-        let tmpdir = cwd.join(self.output_base_name());
-        if tmpdir.exists() {
-            self.aggressive_rm_rf(&tmpdir).unwrap();
-        }
-        create_dir_all(&tmpdir).unwrap();
-
-        let host = &self.config.host;
-        let make = if host.contains("dragonfly")
-            || host.contains("freebsd")
-            || host.contains("netbsd")
-            || host.contains("openbsd")
-            || host.contains("aix")
-        {
-            "gmake"
-        } else {
-            "make"
-        };
-
-        let mut cmd = Command::new(make);
-        cmd.current_dir(&self.testpaths.file)
-            .stdout(Stdio::piped())
-            .stderr(Stdio::piped())
-            .env("TARGET", &self.config.target)
-            .env("PYTHON", &self.config.python)
-            .env("S", src_root)
-            .env("RUST_BUILD_STAGE", &self.config.stage_id)
-            .env("RUSTC", cwd.join(&self.config.rustc_path))
-            .env("TMPDIR", &tmpdir)
-            .env("LD_LIB_PATH_ENVVAR", dylib_env_var())
-            .env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path))
-            .env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path))
-            .env("LLVM_COMPONENTS", &self.config.llvm_components)
-            // We for sure don't want these tests to run in parallel, so make
-            // sure they don't have access to these vars if we run via `make`
-            // at the top level
-            .env_remove("MAKEFLAGS")
-            .env_remove("MFLAGS")
-            .env_remove("CARGO_MAKEFLAGS");
-
-        if let Some(ref rustdoc) = self.config.rustdoc_path {
-            cmd.env("RUSTDOC", cwd.join(rustdoc));
-        }
-
-        if let Some(ref node) = self.config.nodejs {
-            cmd.env("NODE", node);
-        }
-
-        if let Some(ref linker) = self.config.target_linker {
-            cmd.env("RUSTC_LINKER", linker);
-        }
-
-        if let Some(ref clang) = self.config.run_clang_based_tests_with {
-            cmd.env("CLANG", clang);
-        }
-
-        if let Some(ref filecheck) = self.config.llvm_filecheck {
-            cmd.env("LLVM_FILECHECK", filecheck);
-        }
-
-        if let Some(ref llvm_bin_dir) = self.config.llvm_bin_dir {
-            cmd.env("LLVM_BIN_DIR", llvm_bin_dir);
-        }
-
-        if let Some(ref remote_test_client) = self.config.remote_test_client {
-            cmd.env("REMOTE_TEST_CLIENT", remote_test_client);
-        }
-
-        // We don't want RUSTFLAGS set from the outside to interfere with
-        // compiler flags set in the test cases:
-        cmd.env_remove("RUSTFLAGS");
-
-        // Use dynamic musl for tests because static doesn't allow creating dylibs
-        if self.config.host.contains("musl") {
-            cmd.env("RUSTFLAGS", "-Ctarget-feature=-crt-static").env("IS_MUSL_HOST", "1");
-        }
-
-        if self.config.bless {
-            cmd.env("RUSTC_BLESS_TEST", "--bless");
-            // Assume this option is active if the environment variable is "defined", with _any_ value.
-            // As an example, a `Makefile` can use this option by:
-            //
-            //   ifdef RUSTC_BLESS_TEST
-            //       cp "$(TMPDIR)"/actual_something.ext expected_something.ext
-            //   else
-            //       $(DIFF) expected_something.ext "$(TMPDIR)"/actual_something.ext
-            //   endif
-        }
-
-        if self.config.target.contains("msvc") && !self.config.cc.is_empty() {
-            // We need to pass a path to `lib.exe`, so assume that `cc` is `cl.exe`
-            // and that `lib.exe` lives next to it.
-            let lib = Path::new(&self.config.cc).parent().unwrap().join("lib.exe");
-
-            // MSYS doesn't like passing flags of the form `/foo` as it thinks it's
-            // a path and instead passes `C:\msys64\foo`, so convert all
-            // `/`-arguments to MSVC here to `-` arguments.
-            let cflags = self
-                .config
-                .cflags
-                .split(' ')
-                .map(|s| s.replace("/", "-"))
-                .collect::<Vec<_>>()
-                .join(" ");
-            let cxxflags = self
-                .config
-                .cxxflags
-                .split(' ')
-                .map(|s| s.replace("/", "-"))
-                .collect::<Vec<_>>()
-                .join(" ");
-
-            cmd.env("IS_MSVC", "1")
-                .env("IS_WINDOWS", "1")
-                .env("MSVC_LIB", format!("'{}' -nologo", lib.display()))
-                .env("MSVC_LIB_PATH", format!("{}", lib.display()))
-                .env("CC", format!("'{}' {}", self.config.cc, cflags))
-                .env("CXX", format!("'{}' {}", &self.config.cxx, cxxflags));
-        } else {
-            cmd.env("CC", format!("{} {}", self.config.cc, self.config.cflags))
-                .env("CXX", format!("{} {}", self.config.cxx, self.config.cxxflags))
-                .env("AR", &self.config.ar);
-
-            if self.config.target.contains("windows") {
-                cmd.env("IS_WINDOWS", "1");
-            }
-        }
-
-        let (output, truncated) =
-            self.read2_abbreviated(cmd.spawn().expect("failed to spawn `make`"));
-        if !output.status.success() {
-            let res = ProcRes {
-                status: output.status,
-                stdout: String::from_utf8_lossy(&output.stdout).into_owned(),
-                stderr: String::from_utf8_lossy(&output.stderr).into_owned(),
-                truncated,
-                cmdline: format!("{:?}", cmd),
-            };
-            self.fatal_proc_rec("make failed", &res);
-        }
-    }
-
-    fn aggressive_rm_rf(&self, path: &Path) -> io::Result<()> {
-        for e in path.read_dir()? {
-            let entry = e?;
-            let path = entry.path();
-            if entry.file_type()?.is_dir() {
-                self.aggressive_rm_rf(&path)?;
-            } else {
-                // Remove readonly files as well on windows (by default we can't)
-                fs::remove_file(&path).or_else(|e| {
-                    if cfg!(windows) && e.kind() == io::ErrorKind::PermissionDenied {
-                        let mut meta = entry.metadata()?.permissions();
-                        meta.set_readonly(false);
-                        fs::set_permissions(&path, meta)?;
-                        fs::remove_file(&path)
-                    } else {
-                        Err(e)
-                    }
-                })?;
-            }
-        }
-        fs::remove_dir(path)
-    }
-
-    fn run_rmake_v2_test(&self) {
-        // For `run-make` V2, we need to perform 2 steps to build and run a `run-make` V2 recipe
-        // (`rmake.rs`) to run the actual tests. The support library is already built as a tool rust
-        // library and is available under `build/$TARGET/stageN-tools-bin/librun_make_support.rlib`.
-        //
-        // 1. We need to build the recipe `rmake.rs` as a binary and link in the `run_make_support`
-        //    library.
-        // 2. We need to run the recipe binary.
-
-        // So we assume the rust-lang/rust project setup looks like the following (our `.` is the
-        // top-level directory, irrelevant entries to our purposes omitted):
-        //
-        // ```
-        // .                               // <- `source_root`
-        // ├── build/                      // <- `build_root`
-        // ├── compiler/
-        // ├── library/
-        // ├── src/
-        // │  └── tools/
-        // │     └── run_make_support/
-        // └── tests
-        //    └── run-make/
-        // ```
-
-        // `source_root` is the top-level directory containing the rust-lang/rust checkout.
-        let source_root =
-            self.config.find_rust_src_root().expect("could not determine rust source root");
-        // `self.config.build_base` is actually the build base folder + "test" + test suite name, it
-        // looks like `build/<host_triple>/test/run-make`. But we want `build/<host_triple>/`. Note
-        // that the `build` directory does not need to be called `build`, nor does it need to be
-        // under `source_root`, so we must compute it based off of `self.config.build_base`.
-        let build_root =
-            self.config.build_base.parent().and_then(Path::parent).unwrap().to_path_buf();
-
-        // We construct the following directory tree for each rmake.rs test:
-        // ```
-        // <base_dir>/
-        //     rmake.exe
-        //     rmake_out/
-        // ```
-        // having the recipe executable separate from the output artifacts directory allows the
-        // recipes to `remove_dir_all($TMPDIR)` without running into issues related trying to remove
-        // a currently running executable because the recipe executable is not under the
-        // `rmake_out/` directory.
-        //
-        // This setup intentionally diverges from legacy Makefile run-make tests.
-        let base_dir = self.output_base_name();
-        if base_dir.exists() {
-            self.aggressive_rm_rf(&base_dir).unwrap();
-        }
-        let rmake_out_dir = base_dir.join("rmake_out");
-        create_dir_all(&rmake_out_dir).unwrap();
-
-        // Copy all input files (apart from rmake.rs) to the temporary directory,
-        // so that the input directory structure from `tests/run-make/<test>` is mirrored
-        // to the `rmake_out` directory.
-        for path in walkdir::WalkDir::new(&self.testpaths.file).min_depth(1) {
-            let path = path.unwrap().path().to_path_buf();
-            if path.file_name().is_some_and(|s| s != "rmake.rs") {
-                let target = rmake_out_dir.join(path.strip_prefix(&self.testpaths.file).unwrap());
-                if path.is_dir() {
-                    copy_dir_all(&path, target).unwrap();
-                } else {
-                    fs::copy(&path, target).unwrap();
-                }
-            }
-        }
-
-        // `self.config.stage_id` looks like `stage1-<target_triple>`, but we only want
-        // the `stage1` part as that is what the output directories of bootstrap are prefixed with.
-        // Note that this *assumes* build layout from bootstrap is produced as:
-        //
-        // ```
-        // build/<target_triple>/          // <- this is `build_root`
-        // ├── stage0
-        // ├── stage0-bootstrap-tools
-        // ├── stage0-codegen
-        // ├── stage0-rustc
-        // ├── stage0-std
-        // ├── stage0-sysroot
-        // ├── stage0-tools
-        // ├── stage0-tools-bin
-        // ├── stage1
-        // ├── stage1-std
-        // ├── stage1-tools
-        // ├── stage1-tools-bin
-        // └── test
-        // ```
-        // FIXME(jieyouxu): improve the communication between bootstrap and compiletest here so
-        // we don't have to hack out a `stageN`.
-        let stage = self.config.stage_id.split('-').next().unwrap();
-
-        // In order to link in the support library as a rlib when compiling recipes, we need three
-        // paths:
-        // 1. Path of the built support library rlib itself.
-        // 2. Path of the built support library's dependencies directory.
-        // 3. Path of the built support library's dependencies' dependencies directory.
-        //
-        // The paths look like
-        //
-        // ```
-        // build/<target_triple>/
-        // ├── stageN-tools-bin/
-        // │   └── librun_make_support.rlib       // <- support rlib itself
-        // ├── stageN-tools/
-        // │   ├── release/deps/                  // <- deps of deps
-        // │   └── <host_triple>/release/deps/    // <- deps
-        // ```
-        //
-        // FIXME(jieyouxu): there almost certainly is a better way to do this (specifically how the
-        // support lib and its deps are organized, can't we copy them to the tools-bin dir as
-        // well?), but this seems to work for now.
-
-        let stage_tools_bin = build_root.join(format!("{stage}-tools-bin"));
-        let support_lib_path = stage_tools_bin.join("librun_make_support.rlib");
-
-        let stage_tools = build_root.join(format!("{stage}-tools"));
-        let support_lib_deps = stage_tools.join(&self.config.host).join("release").join("deps");
-        let support_lib_deps_deps = stage_tools.join("release").join("deps");
-
-        // To compile the recipe with rustc, we need to provide suitable dynamic library search
-        // paths to rustc. This includes both:
-        // 1. The "base" dylib search paths that was provided to compiletest, e.g. `LD_LIBRARY_PATH`
-        //    on some linux distros.
-        // 2. Specific library paths in `self.config.compile_lib_path` needed for running rustc.
-
-        let base_dylib_search_paths =
-            Vec::from_iter(env::split_paths(&env::var(dylib_env_var()).unwrap()));
-
-        let host_dylib_search_paths = {
-            let mut paths = vec![self.config.compile_lib_path.clone()];
-            paths.extend(base_dylib_search_paths.iter().cloned());
-            paths
-        };
-
-        // Calculate the paths of the recipe binary. As previously discussed, this is placed at
-        // `<base_dir>/<bin_name>` with `bin_name` being `rmake` or `rmake.exe` depending on
-        // platform.
-        let recipe_bin = {
-            let mut p = base_dir.join("rmake");
-            p.set_extension(env::consts::EXE_EXTENSION);
-            p
-        };
-
-        let mut rustc = Command::new(&self.config.rustc_path);
-        rustc
-            .arg("-o")
-            .arg(&recipe_bin)
-            // Specify library search paths for `run_make_support`.
-            .arg(format!("-Ldependency={}", &support_lib_path.parent().unwrap().to_string_lossy()))
-            .arg(format!("-Ldependency={}", &support_lib_deps.to_string_lossy()))
-            .arg(format!("-Ldependency={}", &support_lib_deps_deps.to_string_lossy()))
-            // Provide `run_make_support` as extern prelude, so test writers don't need to write
-            // `extern run_make_support;`.
-            .arg("--extern")
-            .arg(format!("run_make_support={}", &support_lib_path.to_string_lossy()))
-            .arg("--edition=2021")
-            .arg(&self.testpaths.file.join("rmake.rs"))
-            // Provide necessary library search paths for rustc.
-            .env(dylib_env_var(), &env::join_paths(host_dylib_search_paths).unwrap());
-
-        // In test code we want to be very pedantic about values being silently discarded that are
-        // annotated with `#[must_use]`.
-        rustc.arg("-Dunused_must_use");
-
-        // > `cg_clif` uses `COMPILETEST_FORCE_STAGE0=1 ./x.py test --stage 0` for running the rustc
-        // > test suite. With the introduction of rmake.rs this broke. `librun_make_support.rlib` is
-        // > compiled using the bootstrap rustc wrapper which sets `--sysroot
-        // > build/aarch64-unknown-linux-gnu/stage0-sysroot`, but then compiletest will compile
-        // > `rmake.rs` using the sysroot of the bootstrap compiler causing it to not find the
-        // > `libstd.rlib` against which `librun_make_support.rlib` is compiled.
-        //
-        // The gist here is that we have to pass the proper stage0 sysroot if we want
-        //
-        // ```
-        // $ COMPILETEST_FORCE_STAGE0=1 ./x test run-make --stage 0
-        // ```
-        //
-        // to work correctly.
-        //
-        // See <https://github.com/rust-lang/rust/pull/122248> for more background.
-        if std::env::var_os("COMPILETEST_FORCE_STAGE0").is_some() {
-            let stage0_sysroot = build_root.join("stage0-sysroot");
-            rustc.arg("--sysroot").arg(&stage0_sysroot);
-        }
-
-        // Now run rustc to build the recipe.
-        let res = self.run_command_to_procres(&mut rustc);
-        if !res.status.success() {
-            self.fatal_proc_rec("run-make test failed: could not build `rmake.rs` recipe", &res);
-        }
-
-        // To actually run the recipe, we have to provide the recipe with a bunch of information
-        // provided through env vars.
-
-        // Compute stage-specific standard library paths.
-        let stage_std_path = build_root.join(&stage).join("lib");
-
-        // Compute dynamic library search paths for recipes.
-        let recipe_dylib_search_paths = {
-            let mut paths = base_dylib_search_paths.clone();
-            paths.push(support_lib_path.parent().unwrap().to_path_buf());
-            paths.push(stage_std_path.join("rustlib").join(&self.config.host).join("lib"));
-            paths
-        };
-
-        // Compute runtime library search paths for recipes. This is target-specific.
-        let target_runtime_dylib_search_paths = {
-            let mut paths = vec![rmake_out_dir.clone()];
-            paths.extend(base_dylib_search_paths.iter().cloned());
-            paths
-        };
-
-        // FIXME(jieyouxu): please rename `TARGET_RPATH_ENV`, `HOST_RPATH_DIR` and
-        // `TARGET_RPATH_DIR`, it is **extremely** confusing!
-        let mut cmd = Command::new(&recipe_bin);
-        cmd.current_dir(&rmake_out_dir)
-            .stdout(Stdio::piped())
-            .stderr(Stdio::piped())
-            // Provide the target-specific env var that is used to record dylib search paths. For
-            // example, this could be `LD_LIBRARY_PATH` on some linux distros but `PATH` on Windows.
-            .env("LD_LIB_PATH_ENVVAR", dylib_env_var())
-            // Provide the dylib search paths.
-            .env(dylib_env_var(), &env::join_paths(recipe_dylib_search_paths).unwrap())
-            // Provide runtime dylib search paths.
-            .env("TARGET_RPATH_ENV", &env::join_paths(target_runtime_dylib_search_paths).unwrap())
-            // Provide the target.
-            .env("TARGET", &self.config.target)
-            // Some tests unfortunately still need Python, so provide path to a Python interpreter.
-            .env("PYTHON", &self.config.python)
-            // Provide path to checkout root. This is the top-level directory containing
-            // rust-lang/rust checkout.
-            .env("SOURCE_ROOT", &source_root)
-            // Provide path to stage-corresponding rustc.
-            .env("RUSTC", &self.config.rustc_path)
-            // Provide the directory to libraries that are needed to run the *compiler*. This is not
-            // to be confused with `TARGET_RPATH_ENV` or `TARGET_RPATH_DIR`. This is needed if the
-            // recipe wants to invoke rustc.
-            .env("HOST_RPATH_DIR", &self.config.compile_lib_path)
-            // Provide the directory to libraries that might be needed to run compiled binaries
-            // (further compiled by the recipe!).
-            .env("TARGET_RPATH_DIR", &self.config.run_lib_path)
-            // Provide which LLVM components are available (e.g. which LLVM components are provided
-            // through a specific CI runner).
-            .env("LLVM_COMPONENTS", &self.config.llvm_components);
-
-        if let Some(ref rustdoc) = self.config.rustdoc_path {
-            cmd.env("RUSTDOC", source_root.join(rustdoc));
-        }
-
-        if let Some(ref node) = self.config.nodejs {
-            cmd.env("NODE", node);
-        }
-
-        if let Some(ref linker) = self.config.target_linker {
-            cmd.env("RUSTC_LINKER", linker);
-        }
-
-        if let Some(ref clang) = self.config.run_clang_based_tests_with {
-            cmd.env("CLANG", clang);
-        }
-
-        if let Some(ref filecheck) = self.config.llvm_filecheck {
-            cmd.env("LLVM_FILECHECK", filecheck);
-        }
-
-        if let Some(ref llvm_bin_dir) = self.config.llvm_bin_dir {
-            cmd.env("LLVM_BIN_DIR", llvm_bin_dir);
-        }
-
-        if let Some(ref remote_test_client) = self.config.remote_test_client {
-            cmd.env("REMOTE_TEST_CLIENT", remote_test_client);
-        }
-
-        // We don't want RUSTFLAGS set from the outside to interfere with
-        // compiler flags set in the test cases:
-        cmd.env_remove("RUSTFLAGS");
-
-        // Use dynamic musl for tests because static doesn't allow creating dylibs
-        if self.config.host.contains("musl") {
-            cmd.env("RUSTFLAGS", "-Ctarget-feature=-crt-static").env("IS_MUSL_HOST", "1");
-        }
-
-        if self.config.bless {
-            // If we're running in `--bless` mode, set an environment variable to tell
-            // `run_make_support` to bless snapshot files instead of checking them.
-            //
-            // The value is this test's source directory, because the support code
-            // will need that path in order to bless the _original_ snapshot files,
-            // not the copies in `rmake_out`.
-            // (See <https://github.com/rust-lang/rust/issues/129038>.)
-            cmd.env("RUSTC_BLESS_TEST", &self.testpaths.file);
-        }
-
-        if self.config.target.contains("msvc") && !self.config.cc.is_empty() {
-            // We need to pass a path to `lib.exe`, so assume that `cc` is `cl.exe`
-            // and that `lib.exe` lives next to it.
-            let lib = Path::new(&self.config.cc).parent().unwrap().join("lib.exe");
-
-            // MSYS doesn't like passing flags of the form `/foo` as it thinks it's
-            // a path and instead passes `C:\msys64\foo`, so convert all
-            // `/`-arguments to MSVC here to `-` arguments.
-            let cflags = self
-                .config
-                .cflags
-                .split(' ')
-                .map(|s| s.replace("/", "-"))
-                .collect::<Vec<_>>()
-                .join(" ");
-            let cxxflags = self
-                .config
-                .cxxflags
-                .split(' ')
-                .map(|s| s.replace("/", "-"))
-                .collect::<Vec<_>>()
-                .join(" ");
-
-            cmd.env("IS_MSVC", "1")
-                .env("IS_WINDOWS", "1")
-                .env("MSVC_LIB", format!("'{}' -nologo", lib.display()))
-                .env("MSVC_LIB_PATH", format!("{}", lib.display()))
-                // Note: we diverge from legacy run_make and don't lump `CC` the compiler and
-                // default flags together.
-                .env("CC_DEFAULT_FLAGS", &cflags)
-                .env("CC", &self.config.cc)
-                .env("CXX_DEFAULT_FLAGS", &cxxflags)
-                .env("CXX", &self.config.cxx);
-        } else {
-            cmd.env("CC_DEFAULT_FLAGS", &self.config.cflags)
-                .env("CC", &self.config.cc)
-                .env("CXX_DEFAULT_FLAGS", &self.config.cxxflags)
-                .env("CXX", &self.config.cxx)
-                .env("AR", &self.config.ar);
-
-            if self.config.target.contains("windows") {
-                cmd.env("IS_WINDOWS", "1");
-            }
-        }
-
-        let (Output { stdout, stderr, status }, truncated) =
-            self.read2_abbreviated(cmd.spawn().expect("failed to spawn `rmake`"));
-        if !status.success() {
-            let res = ProcRes {
-                status,
-                stdout: String::from_utf8_lossy(&stdout).into_owned(),
-                stderr: String::from_utf8_lossy(&stderr).into_owned(),
-                truncated,
-                cmdline: format!("{:?}", cmd),
-            };
-            self.fatal_proc_rec("rmake recipe failed to complete", &res);
-        }
-    }
-
-    fn run_js_doc_test(&self) {
-        if let Some(nodejs) = &self.config.nodejs {
-            let out_dir = self.output_base_dir();
-
-            self.document(&out_dir, &self.testpaths);
-
-            let root = self.config.find_rust_src_root().unwrap();
-            let file_stem =
-                self.testpaths.file.file_stem().and_then(|f| f.to_str()).expect("no file stem");
-            let res = self.run_command_to_procres(
-                Command::new(&nodejs)
-                    .arg(root.join("src/tools/rustdoc-js/tester.js"))
-                    .arg("--doc-folder")
-                    .arg(out_dir)
-                    .arg("--crate-name")
-                    .arg(file_stem.replace("-", "_"))
-                    .arg("--test-file")
-                    .arg(self.testpaths.file.with_extension("js")),
-            );
-            if !res.status.success() {
-                self.fatal_proc_rec("rustdoc-js test failed!", &res);
-            }
-        } else {
-            self.fatal("no nodeJS");
-        }
-    }
-
     fn force_color_svg(&self) -> bool {
         self.props.compile_flags.iter().any(|s| s.contains("--color=always"))
     }
@@ -3895,377 +2258,6 @@ impl<'test> TestCx<'test> {
         errors
     }
 
-    fn run_ui_test(&self) {
-        if let Some(FailMode::Build) = self.props.fail_mode {
-            // Make sure a build-fail test cannot fail due to failing analysis (e.g. typeck).
-            let pm = Some(PassMode::Check);
-            let proc_res =
-                self.compile_test_general(WillExecute::No, Emit::Metadata, pm, Vec::new());
-            self.check_if_test_should_compile(&proc_res, pm);
-        }
-
-        let pm = self.pass_mode();
-        let should_run = self.should_run(pm);
-        let emit_metadata = self.should_emit_metadata(pm);
-        let proc_res = self.compile_test(should_run, emit_metadata);
-        self.check_if_test_should_compile(&proc_res, pm);
-        if matches!(proc_res.truncated, Truncated::Yes)
-            && !self.props.dont_check_compiler_stdout
-            && !self.props.dont_check_compiler_stderr
-        {
-            self.fatal_proc_rec(
-                "compiler output got truncated, cannot compare with reference file",
-                &proc_res,
-            );
-        }
-
-        // if the user specified a format in the ui test
-        // print the output to the stderr file, otherwise extract
-        // the rendered error messages from json and print them
-        let explicit = self.props.compile_flags.iter().any(|s| s.contains("--error-format"));
-
-        let expected_fixed = self.load_expected_output(UI_FIXED);
-
-        self.check_and_prune_duplicate_outputs(&proc_res, &[], &[]);
-
-        let mut errors = self.load_compare_outputs(&proc_res, TestOutput::Compile, explicit);
-        let rustfix_input = json::rustfix_diagnostics_only(&proc_res.stderr);
-
-        if self.config.compare_mode.is_some() {
-            // don't test rustfix with nll right now
-        } else if self.config.rustfix_coverage {
-            // Find out which tests have `MachineApplicable` suggestions but are missing
-            // `run-rustfix` or `run-rustfix-only-machine-applicable` headers.
-            //
-            // This will return an empty `Vec` in case the executed test file has a
-            // `compile-flags: --error-format=xxxx` header with a value other than `json`.
-            let suggestions = get_suggestions_from_json(
-                &rustfix_input,
-                &HashSet::new(),
-                Filter::MachineApplicableOnly,
-            )
-            .unwrap_or_default();
-            if !suggestions.is_empty()
-                && !self.props.run_rustfix
-                && !self.props.rustfix_only_machine_applicable
-            {
-                let mut coverage_file_path = self.config.build_base.clone();
-                coverage_file_path.push("rustfix_missing_coverage.txt");
-                debug!("coverage_file_path: {}", coverage_file_path.display());
-
-                let mut file = OpenOptions::new()
-                    .create(true)
-                    .append(true)
-                    .open(coverage_file_path.as_path())
-                    .expect("could not create or open file");
-
-                if let Err(e) = writeln!(file, "{}", self.testpaths.file.display()) {
-                    panic!("couldn't write to {}: {e:?}", coverage_file_path.display());
-                }
-            }
-        } else if self.props.run_rustfix {
-            // Apply suggestions from rustc to the code itself
-            let unfixed_code = self.load_expected_output_from_path(&self.testpaths.file).unwrap();
-            let suggestions = get_suggestions_from_json(
-                &rustfix_input,
-                &HashSet::new(),
-                if self.props.rustfix_only_machine_applicable {
-                    Filter::MachineApplicableOnly
-                } else {
-                    Filter::Everything
-                },
-            )
-            .unwrap();
-            let fixed_code = apply_suggestions(&unfixed_code, &suggestions).unwrap_or_else(|e| {
-                panic!(
-                    "failed to apply suggestions for {:?} with rustfix: {}",
-                    self.testpaths.file, e
-                )
-            });
-
-            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` \
-                 file was found"
-            );
-        }
-
-        if errors > 0 {
-            println!("To update references, rerun the tests and pass the `--bless` flag");
-            let relative_path_to_file =
-                self.testpaths.relative_dir.join(self.testpaths.file.file_name().unwrap());
-            println!(
-                "To only update this specific test, also pass `--test-args {}`",
-                relative_path_to_file.display(),
-            );
-            self.fatal_proc_rec(
-                &format!("{} errors occurred comparing output.", errors),
-                &proc_res,
-            );
-        }
-
-        let expected_errors = errors::load_errors(&self.testpaths.file, self.revision);
-
-        if let WillExecute::Yes = should_run {
-            let proc_res = self.exec_compiled_test();
-            let run_output_errors = if self.props.check_run_results {
-                self.load_compare_outputs(&proc_res, TestOutput::Run, explicit)
-            } else {
-                0
-            };
-            if run_output_errors > 0 {
-                self.fatal_proc_rec(
-                    &format!("{} errors occurred comparing run output.", run_output_errors),
-                    &proc_res,
-                );
-            }
-            if self.should_run_successfully(pm) {
-                if !proc_res.status.success() {
-                    self.fatal_proc_rec("test run failed!", &proc_res);
-                }
-            } else if proc_res.status.success() {
-                self.fatal_proc_rec("test run succeeded!", &proc_res);
-            }
-
-            if !self.props.error_patterns.is_empty() || !self.props.regex_error_patterns.is_empty()
-            {
-                // "// error-pattern" comments
-                let output_to_check = self.get_output(&proc_res);
-                self.check_all_error_patterns(&output_to_check, &proc_res, pm);
-            }
-        }
-
-        debug!(
-            "run_ui_test: explicit={:?} config.compare_mode={:?} expected_errors={:?} \
-               proc_res.status={:?} props.error_patterns={:?}",
-            explicit,
-            self.config.compare_mode,
-            expected_errors,
-            proc_res.status,
-            self.props.error_patterns
-        );
-
-        let check_patterns = should_run == WillExecute::No
-            && (!self.props.error_patterns.is_empty()
-                || !self.props.regex_error_patterns.is_empty());
-        if !explicit && self.config.compare_mode.is_none() {
-            let check_annotations = !check_patterns || !expected_errors.is_empty();
-
-            if check_annotations {
-                // "//~ERROR comments"
-                self.check_expected_errors(expected_errors, &proc_res);
-            }
-        } else if explicit && !expected_errors.is_empty() {
-            let msg = format!(
-                "line {}: cannot combine `--error-format` with {} annotations; use `error-pattern` instead",
-                expected_errors[0].line_num,
-                expected_errors[0].kind.unwrap_or(ErrorKind::Error),
-            );
-            self.fatal(&msg);
-        }
-        if check_patterns {
-            // "// error-pattern" comments
-            let output_to_check = self.get_output(&proc_res);
-            self.check_all_error_patterns(&output_to_check, &proc_res, pm);
-        }
-
-        if self.props.run_rustfix && self.config.compare_mode.is_none() {
-            // And finally, compile the fixed code and make sure it both
-            // succeeds and has no diagnostics.
-            let mut rustc = self.make_compile_args(
-                &self.expected_output_path(UI_FIXED),
-                TargetLocation::ThisFile(self.make_exe_name()),
-                emit_metadata,
-                AllowUnused::No,
-                LinkToAux::Yes,
-                Vec::new(),
-            );
-
-            // If a test is revisioned, it's fixed source file can be named "a.foo.fixed", which,
-            // well, "a.foo" isn't a valid crate name. So we explicitly mangle the test name
-            // (including the revision) here to avoid the test writer having to manually specify a
-            // `#![crate_name = "..."]` as a workaround. This is okay since we're only checking if
-            // the fixed code is compilable.
-            if self.revision.is_some() {
-                let crate_name =
-                    self.testpaths.file.file_stem().expect("test must have a file stem");
-                // crate name must be alphanumeric or `_`.
-                let crate_name =
-                    crate_name.to_str().expect("crate name implies file name must be valid UTF-8");
-                // replace `a.foo` -> `a__foo` for crate name purposes.
-                // replace `revision-name-with-dashes` -> `revision_name_with_underscore`
-                let crate_name = crate_name.replace('.', "__");
-                let crate_name = crate_name.replace('-', "_");
-                rustc.arg("--crate-name");
-                rustc.arg(crate_name);
-            }
-
-            let res = self.compose_and_run_compiler(rustc, None, self.testpaths);
-            if !res.status.success() {
-                self.fatal_proc_rec("failed to compile fixed code", &res);
-            }
-            if !res.stderr.is_empty()
-                && !self.props.rustfix_only_machine_applicable
-                && !json::rustfix_diagnostics_only(&res.stderr).is_empty()
-            {
-                self.fatal_proc_rec("fixed code is still producing diagnostics", &res);
-            }
-        }
-    }
-
-    fn run_mir_opt_test(&self) {
-        let pm = self.pass_mode();
-        let should_run = self.should_run(pm);
-
-        let mut test_info = files_for_miropt_test(
-            &self.testpaths.file,
-            self.config.get_pointer_width(),
-            self.config.target_cfg().panic.for_miropt_test_tools(),
-        );
-
-        let passes = std::mem::take(&mut test_info.passes);
-
-        let proc_res = self.compile_test_with_passes(should_run, Emit::Mir, passes);
-        if !proc_res.status.success() {
-            self.fatal_proc_rec("compilation failed!", &proc_res);
-        }
-        self.check_mir_dump(test_info);
-
-        if let WillExecute::Yes = should_run {
-            let proc_res = self.exec_compiled_test();
-
-            if !proc_res.status.success() {
-                self.fatal_proc_rec("test run failed!", &proc_res);
-            }
-        }
-    }
-
-    fn check_mir_dump(&self, test_info: MiroptTest) {
-        let test_dir = self.testpaths.file.parent().unwrap();
-        let test_crate =
-            self.testpaths.file.file_stem().unwrap().to_str().unwrap().replace('-', "_");
-
-        let MiroptTest { run_filecheck, suffix, files, passes: _ } = test_info;
-
-        if self.config.bless {
-            for e in
-                glob(&format!("{}/{}.*{}.mir", test_dir.display(), test_crate, suffix)).unwrap()
-            {
-                std::fs::remove_file(e.unwrap()).unwrap();
-            }
-            for e in
-                glob(&format!("{}/{}.*{}.diff", test_dir.display(), test_crate, suffix)).unwrap()
-            {
-                std::fs::remove_file(e.unwrap()).unwrap();
-            }
-        }
-
-        for MiroptTestFile { from_file, to_file, expected_file } in files {
-            let dumped_string = if let Some(after) = to_file {
-                self.diff_mir_files(from_file.into(), after.into())
-            } else {
-                let mut output_file = PathBuf::new();
-                output_file.push(self.get_mir_dump_dir());
-                output_file.push(&from_file);
-                debug!(
-                    "comparing the contents of: {} with {}",
-                    output_file.display(),
-                    expected_file.display()
-                );
-                if !output_file.exists() {
-                    panic!(
-                        "Output file `{}` from test does not exist, available files are in `{}`",
-                        output_file.display(),
-                        output_file.parent().unwrap().display()
-                    );
-                }
-                self.check_mir_test_timestamp(&from_file, &output_file);
-                let dumped_string = fs::read_to_string(&output_file).unwrap();
-                self.normalize_output(&dumped_string, &[])
-            };
-
-            if self.config.bless {
-                let _ = std::fs::remove_file(&expected_file);
-                std::fs::write(expected_file, dumped_string.as_bytes()).unwrap();
-            } else {
-                if !expected_file.exists() {
-                    panic!("Output file `{}` from test does not exist", expected_file.display());
-                }
-                let expected_string = fs::read_to_string(&expected_file).unwrap();
-                if dumped_string != expected_string {
-                    print!("{}", write_diff(&expected_string, &dumped_string, 3));
-                    panic!(
-                        "Actual MIR output differs from expected MIR output {}",
-                        expected_file.display()
-                    );
-                }
-            }
-        }
-
-        if run_filecheck {
-            let output_path = self.output_base_name().with_extension("mir");
-            let proc_res = self.verify_with_filecheck(&output_path);
-            if !proc_res.status.success() {
-                self.fatal_proc_rec("verification with 'FileCheck' failed", &proc_res);
-            }
-        }
-    }
-
-    fn diff_mir_files(&self, before: PathBuf, after: PathBuf) -> String {
-        let to_full_path = |path: PathBuf| {
-            let full = self.get_mir_dump_dir().join(&path);
-            if !full.exists() {
-                panic!(
-                    "the mir dump file for {} does not exist (requested in {})",
-                    path.display(),
-                    self.testpaths.file.display(),
-                );
-            }
-            full
-        };
-        let before = to_full_path(before);
-        let after = to_full_path(after);
-        debug!("comparing the contents of: {} with {}", before.display(), after.display());
-        let before = fs::read_to_string(before).unwrap();
-        let after = fs::read_to_string(after).unwrap();
-        let before = self.normalize_output(&before, &[]);
-        let after = self.normalize_output(&after, &[]);
-        let mut dumped_string = String::new();
-        for result in diff::lines(&before, &after) {
-            use std::fmt::Write;
-            match result {
-                diff::Result::Left(s) => writeln!(dumped_string, "- {}", s).unwrap(),
-                diff::Result::Right(s) => writeln!(dumped_string, "+ {}", s).unwrap(),
-                diff::Result::Both(s, _) => writeln!(dumped_string, "  {}", s).unwrap(),
-            }
-        }
-        dumped_string
-    }
-
-    fn check_mir_test_timestamp(&self, test_name: &str, output_file: &Path) {
-        let t = |file| fs::metadata(file).unwrap().modified().unwrap();
-        let source_file = &self.testpaths.file;
-        let output_time = t(output_file);
-        let source_time = t(source_file);
-        if source_time > output_time {
-            debug!("source file time: {:?} output file time: {:?}", source_time, output_time);
-            panic!(
-                "test source file `{}` is newer than potentially stale output file `{}`.",
-                source_file.display(),
-                test_name
-            );
-        }
-    }
-
-    fn get_mir_dump_dir(&self) -> PathBuf {
-        let mut mir_dump_dir = PathBuf::from(self.config.build_base.as_path());
-        debug!("input_file: {:?}", self.testpaths.file);
-        mir_dump_dir.push(&self.testpaths.relative_dir);
-        mir_dump_dir.push(self.testpaths.file.file_stem().unwrap());
-        mir_dump_dir
-    }
-
     fn normalize_output(&self, output: &str, custom_rules: &[(String, String)]) -> String {
         // Crude heuristic to detect when the output should have JSON-specific
         // normalization steps applied.
@@ -4634,6 +2626,77 @@ impl<'test> TestCx<'test> {
         let stamp = crate::stamp(&self.config, self.testpaths, self.revision);
         fs::write(&stamp, compute_stamp_hash(&self.config)).unwrap();
     }
+
+    fn init_incremental_test(&self) {
+        // (See `run_incremental_test` for an overview of how incremental tests work.)
+
+        // Before any of the revisions have executed, create the
+        // incremental workproduct directory.  Delete any old
+        // incremental work products that may be there from prior
+        // runs.
+        let incremental_dir = self.props.incremental_dir.as_ref().unwrap();
+        if incremental_dir.exists() {
+            // Canonicalizing the path will convert it to the //?/ format
+            // on Windows, which enables paths longer than 260 character
+            let canonicalized = incremental_dir.canonicalize().unwrap();
+            fs::remove_dir_all(canonicalized).unwrap();
+        }
+        fs::create_dir_all(&incremental_dir).unwrap();
+
+        if self.config.verbose {
+            println!("init_incremental_test: incremental_dir={}", incremental_dir.display());
+        }
+    }
+
+    // FIXME(jieyouxu): `run_rpass_test` is hoisted out here and not in incremental because
+    // apparently valgrind test falls back to `run_rpass_test` if valgrind isn't available, which
+    // seems highly questionable to me.
+    fn run_rpass_test(&self) {
+        let emit_metadata = self.should_emit_metadata(self.pass_mode());
+        let should_run = self.run_if_enabled();
+        let proc_res = self.compile_test(should_run, emit_metadata);
+
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("compilation failed!", &proc_res);
+        }
+
+        // FIXME(#41968): Move this check to tidy?
+        if !errors::load_errors(&self.testpaths.file, self.revision).is_empty() {
+            self.fatal("run-pass tests with expected warnings should be moved to ui/");
+        }
+
+        if let WillExecute::Disabled = should_run {
+            return;
+        }
+
+        let proc_res = self.exec_compiled_test();
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("test run failed!", &proc_res);
+        }
+    }
+
+    fn aggressive_rm_rf(&self, path: &Path) -> io::Result<()> {
+        for e in path.read_dir()? {
+            let entry = e?;
+            let path = entry.path();
+            if entry.file_type()?.is_dir() {
+                self.aggressive_rm_rf(&path)?;
+            } else {
+                // Remove readonly files as well on windows (by default we can't)
+                fs::remove_file(&path).or_else(|e| {
+                    if cfg!(windows) && e.kind() == io::ErrorKind::PermissionDenied {
+                        let mut meta = entry.metadata()?.permissions();
+                        meta.set_readonly(false);
+                        fs::set_permissions(&path, meta)?;
+                        fs::remove_file(&path)
+                    } else {
+                        Err(e)
+                    }
+                })?;
+            }
+        }
+        fs::remove_dir(path)
+    }
 }
 
 struct ProcArgs {
diff --git a/src/tools/compiletest/src/runtest/assembly.rs b/src/tools/compiletest/src/runtest/assembly.rs
new file mode 100644
index 00000000000..430a5534da1
--- /dev/null
+++ b/src/tools/compiletest/src/runtest/assembly.rs
@@ -0,0 +1,19 @@
+use super::TestCx;
+
+impl TestCx<'_> {
+    pub(super) fn run_assembly_test(&self) {
+        if self.config.llvm_filecheck.is_none() {
+            self.fatal("missing --llvm-filecheck");
+        }
+
+        let (proc_res, output_path) = self.compile_test_and_save_assembly();
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("compilation failed!", &proc_res);
+        }
+
+        let proc_res = self.verify_with_filecheck(&output_path);
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("verification with 'FileCheck' failed", &proc_res);
+        }
+    }
+}
diff --git a/src/tools/compiletest/src/runtest/codegen.rs b/src/tools/compiletest/src/runtest/codegen.rs
new file mode 100644
index 00000000000..6e61ab5e46d
--- /dev/null
+++ b/src/tools/compiletest/src/runtest/codegen.rs
@@ -0,0 +1,22 @@
+use super::{PassMode, TestCx};
+
+impl TestCx<'_> {
+    pub(super) fn run_codegen_test(&self) {
+        if self.config.llvm_filecheck.is_none() {
+            self.fatal("missing --llvm-filecheck");
+        }
+
+        let (proc_res, output_path) = self.compile_test_and_save_ir();
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("compilation failed!", &proc_res);
+        }
+
+        if let Some(PassMode::Build) = self.pass_mode() {
+            return;
+        }
+        let proc_res = self.verify_with_filecheck(&output_path);
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("verification with 'FileCheck' failed", &proc_res);
+        }
+    }
+}
diff --git a/src/tools/compiletest/src/runtest/codegen_units.rs b/src/tools/compiletest/src/runtest/codegen_units.rs
new file mode 100644
index 00000000000..6c866cbef21
--- /dev/null
+++ b/src/tools/compiletest/src/runtest/codegen_units.rs
@@ -0,0 +1,191 @@
+use std::collections::HashSet;
+
+use super::{Emit, TestCx, WillExecute};
+use crate::errors;
+use crate::util::static_regex;
+
+impl TestCx<'_> {
+    pub(super) fn run_codegen_units_test(&self) {
+        assert!(self.revision.is_none(), "revisions not relevant here");
+
+        let proc_res = self.compile_test(WillExecute::No, Emit::None);
+
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("compilation failed!", &proc_res);
+        }
+
+        self.check_no_compiler_crash(&proc_res, self.props.should_ice);
+
+        const PREFIX: &str = "MONO_ITEM ";
+        const CGU_MARKER: &str = "@@";
+
+        // Some MonoItems can contain {closure@/path/to/checkout/tests/codgen-units/test.rs}
+        // To prevent the current dir from leaking, we just replace the entire path to the test
+        // file with TEST_PATH.
+        let actual: Vec<MonoItem> = proc_res
+            .stdout
+            .lines()
+            .filter(|line| line.starts_with(PREFIX))
+            .map(|line| {
+                line.replace(&self.testpaths.file.display().to_string(), "TEST_PATH").to_string()
+            })
+            .map(|line| str_to_mono_item(&line, true))
+            .collect();
+
+        let expected: Vec<MonoItem> = errors::load_errors(&self.testpaths.file, None)
+            .iter()
+            .map(|e| str_to_mono_item(&e.msg[..], false))
+            .collect();
+
+        let mut missing = Vec::new();
+        let mut wrong_cgus = Vec::new();
+
+        for expected_item in &expected {
+            let actual_item_with_same_name = actual.iter().find(|ti| ti.name == expected_item.name);
+
+            if let Some(actual_item) = actual_item_with_same_name {
+                if !expected_item.codegen_units.is_empty() &&
+                   // Also check for codegen units
+                   expected_item.codegen_units != actual_item.codegen_units
+                {
+                    wrong_cgus.push((expected_item.clone(), actual_item.clone()));
+                }
+            } else {
+                missing.push(expected_item.string.clone());
+            }
+        }
+
+        let unexpected: Vec<_> = actual
+            .iter()
+            .filter(|acgu| !expected.iter().any(|ecgu| acgu.name == ecgu.name))
+            .map(|acgu| acgu.string.clone())
+            .collect();
+
+        if !missing.is_empty() {
+            missing.sort();
+
+            println!("\nThese items should have been contained but were not:\n");
+
+            for item in &missing {
+                println!("{}", item);
+            }
+
+            println!("\n");
+        }
+
+        if !unexpected.is_empty() {
+            let sorted = {
+                let mut sorted = unexpected.clone();
+                sorted.sort();
+                sorted
+            };
+
+            println!("\nThese items were contained but should not have been:\n");
+
+            for item in sorted {
+                println!("{}", item);
+            }
+
+            println!("\n");
+        }
+
+        if !wrong_cgus.is_empty() {
+            wrong_cgus.sort_by_key(|pair| pair.0.name.clone());
+            println!("\nThe following items were assigned to wrong codegen units:\n");
+
+            for &(ref expected_item, ref actual_item) in &wrong_cgus {
+                println!("{}", expected_item.name);
+                println!("  expected: {}", codegen_units_to_str(&expected_item.codegen_units));
+                println!("  actual:   {}", codegen_units_to_str(&actual_item.codegen_units));
+                println!();
+            }
+        }
+
+        if !(missing.is_empty() && unexpected.is_empty() && wrong_cgus.is_empty()) {
+            panic!();
+        }
+
+        #[derive(Clone, Eq, PartialEq)]
+        struct MonoItem {
+            name: String,
+            codegen_units: HashSet<String>,
+            string: String,
+        }
+
+        // [MONO_ITEM] name [@@ (cgu)+]
+        fn str_to_mono_item(s: &str, cgu_has_crate_disambiguator: bool) -> MonoItem {
+            let s = if s.starts_with(PREFIX) { (&s[PREFIX.len()..]).trim() } else { s.trim() };
+
+            let full_string = format!("{}{}", PREFIX, s);
+
+            let parts: Vec<&str> =
+                s.split(CGU_MARKER).map(str::trim).filter(|s| !s.is_empty()).collect();
+
+            let name = parts[0].trim();
+
+            let cgus = if parts.len() > 1 {
+                let cgus_str = parts[1];
+
+                cgus_str
+                    .split(' ')
+                    .map(str::trim)
+                    .filter(|s| !s.is_empty())
+                    .map(|s| {
+                        if cgu_has_crate_disambiguator {
+                            remove_crate_disambiguators_from_set_of_cgu_names(s)
+                        } else {
+                            s.to_string()
+                        }
+                    })
+                    .collect()
+            } else {
+                HashSet::new()
+            };
+
+            MonoItem { name: name.to_owned(), codegen_units: cgus, string: full_string }
+        }
+
+        fn codegen_units_to_str(cgus: &HashSet<String>) -> String {
+            let mut cgus: Vec<_> = cgus.iter().collect();
+            cgus.sort();
+
+            let mut string = String::new();
+            for cgu in cgus {
+                string.push_str(&cgu[..]);
+                string.push(' ');
+            }
+
+            string
+        }
+
+        // Given a cgu-name-prefix of the form <crate-name>.<crate-disambiguator> or
+        // the form <crate-name1>.<crate-disambiguator1>-in-<crate-name2>.<crate-disambiguator2>,
+        // remove all crate-disambiguators.
+        fn remove_crate_disambiguator_from_cgu(cgu: &str) -> String {
+            let Some(captures) =
+                static_regex!(r"^[^\.]+(?P<d1>\.[[:alnum:]]+)(-in-[^\.]+(?P<d2>\.[[:alnum:]]+))?")
+                    .captures(cgu)
+            else {
+                panic!("invalid cgu name encountered: {cgu}");
+            };
+
+            let mut new_name = cgu.to_owned();
+
+            if let Some(d2) = captures.name("d2") {
+                new_name.replace_range(d2.start()..d2.end(), "");
+            }
+
+            let d1 = captures.name("d1").unwrap();
+            new_name.replace_range(d1.start()..d1.end(), "");
+
+            new_name
+        }
+
+        // The name of merged CGUs is constructed as the names of the original
+        // CGUs joined with "--". This function splits such composite CGU names
+        // and handles each component individually.
+        fn remove_crate_disambiguators_from_set_of_cgu_names(cgus: &str) -> String {
+            cgus.split("--").map(remove_crate_disambiguator_from_cgu).collect::<Vec<_>>().join("--")
+        }
+    }
+}
diff --git a/src/tools/compiletest/src/runtest/coverage.rs b/src/tools/compiletest/src/runtest/coverage.rs
index 05191a15980..961a1602986 100644
--- a/src/tools/compiletest/src/runtest/coverage.rs
+++ b/src/tools/compiletest/src/runtest/coverage.rs
@@ -18,7 +18,7 @@ impl<'test> TestCx<'test> {
             .unwrap_or_else(|| self.fatal("missing --coverage-dump"))
     }
 
-    pub(crate) fn run_coverage_map_test(&self) {
+    pub(super) fn run_coverage_map_test(&self) {
         let coverage_dump_path = self.coverage_dump_path();
 
         let (proc_res, llvm_ir_path) = self.compile_test_and_save_ir();
@@ -50,7 +50,7 @@ impl<'test> TestCx<'test> {
         }
     }
 
-    pub(crate) fn run_coverage_run_test(&self) {
+    pub(super) fn run_coverage_run_test(&self) {
         let should_run = self.run_if_enabled();
         let proc_res = self.compile_test(should_run, Emit::None);
 
diff --git a/src/tools/compiletest/src/runtest/crash.rs b/src/tools/compiletest/src/runtest/crash.rs
new file mode 100644
index 00000000000..7f2bec4949b
--- /dev/null
+++ b/src/tools/compiletest/src/runtest/crash.rs
@@ -0,0 +1,25 @@
+use super::{TestCx, WillExecute};
+
+impl TestCx<'_> {
+    pub(super) fn run_crash_test(&self) {
+        let pm = self.pass_mode();
+        let proc_res = self.compile_test(WillExecute::No, self.should_emit_metadata(pm));
+
+        if std::env::var("COMPILETEST_VERBOSE_CRASHES").is_ok() {
+            eprintln!("{}", proc_res.status);
+            eprintln!("{}", proc_res.stdout);
+            eprintln!("{}", proc_res.stderr);
+            eprintln!("{}", proc_res.cmdline);
+        }
+
+        // if a test does not crash, consider it an error
+        if proc_res.status.success() || matches!(proc_res.status.code(), Some(1 | 0)) {
+            self.fatal(&format!(
+                "crashtest no longer crashes/triggers ICE, horray! Please give it a meaningful name, \
+            add a doc-comment to the start of the test explaining why it exists and \
+            move it to tests/ui or wherever you see fit. Adding 'Fixes #<issueNr>' to your PR description \
+            ensures that the corresponding ticket is auto-closed upon merge."
+            ));
+        }
+    }
+}
diff --git a/src/tools/compiletest/src/runtest/debuginfo.rs b/src/tools/compiletest/src/runtest/debuginfo.rs
new file mode 100644
index 00000000000..36127414ab1
--- /dev/null
+++ b/src/tools/compiletest/src/runtest/debuginfo.rs
@@ -0,0 +1,509 @@
+use std::ffi::{OsStr, OsString};
+use std::fs::File;
+use std::io::{BufRead, BufReader, Read};
+use std::path::Path;
+use std::process::{Command, Output, Stdio};
+
+use tracing::debug;
+
+use super::debugger::DebuggerCommands;
+use super::{Debugger, Emit, ProcRes, TestCx, Truncated, WillExecute};
+use crate::common::Config;
+use crate::util::logv;
+use crate::{extract_gdb_version, is_android_gdb_target};
+
+impl TestCx<'_> {
+    pub(super) fn run_debuginfo_test(&self) {
+        match self.config.debugger.unwrap() {
+            Debugger::Cdb => self.run_debuginfo_cdb_test(),
+            Debugger::Gdb => self.run_debuginfo_gdb_test(),
+            Debugger::Lldb => self.run_debuginfo_lldb_test(),
+        }
+    }
+
+    fn run_debuginfo_cdb_test(&self) {
+        let config = Config {
+            target_rustcflags: self.cleanup_debug_info_options(&self.config.target_rustcflags),
+            host_rustcflags: self.cleanup_debug_info_options(&self.config.host_rustcflags),
+            ..self.config.clone()
+        };
+
+        let test_cx = TestCx { config: &config, ..*self };
+
+        test_cx.run_debuginfo_cdb_test_no_opt();
+    }
+
+    fn run_debuginfo_cdb_test_no_opt(&self) {
+        let exe_file = self.make_exe_name();
+
+        // Existing PDB files are update in-place. When changing the debuginfo
+        // the compiler generates for something, this can lead to the situation
+        // where both the old and the new version of the debuginfo for the same
+        // type is present in the PDB, which is very confusing.
+        // Therefore we delete any existing PDB file before compiling the test
+        // case.
+        // FIXME: If can reliably detect that MSVC's link.exe is used, then
+        //        passing `/INCREMENTAL:NO` might be a cleaner way to do this.
+        let pdb_file = exe_file.with_extension(".pdb");
+        if pdb_file.exists() {
+            std::fs::remove_file(pdb_file).unwrap();
+        }
+
+        // compile test file (it should have 'compile-flags:-g' in the header)
+        let should_run = self.run_if_enabled();
+        let compile_result = self.compile_test(should_run, Emit::None);
+        if !compile_result.status.success() {
+            self.fatal_proc_rec("compilation failed!", &compile_result);
+        }
+        if let WillExecute::Disabled = should_run {
+            return;
+        }
+
+        let prefixes = {
+            static PREFIXES: &[&str] = &["cdb", "cdbg"];
+            // No "native rust support" variation for CDB yet.
+            PREFIXES
+        };
+
+        // Parse debugger commands etc from test files
+        let dbg_cmds = DebuggerCommands::parse_from(
+            &self.testpaths.file,
+            self.config,
+            prefixes,
+            self.revision,
+        )
+        .unwrap_or_else(|e| self.fatal(&e));
+
+        // https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-commands
+        let mut script_str = String::with_capacity(2048);
+        script_str.push_str("version\n"); // List CDB (and more) version info in test output
+        script_str.push_str(".nvlist\n"); // List loaded `*.natvis` files, bulk of custom MSVC debug
+
+        // If a .js file exists next to the source file being tested, then this is a JavaScript
+        // debugging extension that needs to be loaded.
+        let mut js_extension = self.testpaths.file.clone();
+        js_extension.set_extension("cdb.js");
+        if js_extension.exists() {
+            script_str.push_str(&format!(".scriptload \"{}\"\n", js_extension.to_string_lossy()));
+        }
+
+        // Set breakpoints on every line that contains the string "#break"
+        let source_file_name = self.testpaths.file.file_name().unwrap().to_string_lossy();
+        for line in &dbg_cmds.breakpoint_lines {
+            script_str.push_str(&format!("bp `{}:{}`\n", source_file_name, line));
+        }
+
+        // Append the other `cdb-command:`s
+        for line in &dbg_cmds.commands {
+            script_str.push_str(line);
+            script_str.push('\n');
+        }
+
+        script_str.push_str("qq\n"); // Quit the debugger (including remote debugger, if any)
+
+        // Write the script into a file
+        debug!("script_str = {}", script_str);
+        self.dump_output_file(&script_str, "debugger.script");
+        let debugger_script = self.make_out_name("debugger.script");
+
+        let cdb_path = &self.config.cdb.as_ref().unwrap();
+        let mut cdb = Command::new(cdb_path);
+        cdb.arg("-lines") // Enable source line debugging.
+            .arg("-cf")
+            .arg(&debugger_script)
+            .arg(&exe_file);
+
+        let debugger_run_result = self.compose_and_run(
+            cdb,
+            self.config.run_lib_path.to_str().unwrap(),
+            None, // aux_path
+            None, // input
+        );
+
+        if !debugger_run_result.status.success() {
+            self.fatal_proc_rec("Error while running CDB", &debugger_run_result);
+        }
+
+        if let Err(e) = dbg_cmds.check_output(&debugger_run_result) {
+            self.fatal_proc_rec(&e, &debugger_run_result);
+        }
+    }
+
+    fn run_debuginfo_gdb_test(&self) {
+        let config = Config {
+            target_rustcflags: self.cleanup_debug_info_options(&self.config.target_rustcflags),
+            host_rustcflags: self.cleanup_debug_info_options(&self.config.host_rustcflags),
+            ..self.config.clone()
+        };
+
+        let test_cx = TestCx { config: &config, ..*self };
+
+        test_cx.run_debuginfo_gdb_test_no_opt();
+    }
+
+    fn run_debuginfo_gdb_test_no_opt(&self) {
+        let dbg_cmds = DebuggerCommands::parse_from(
+            &self.testpaths.file,
+            self.config,
+            &["gdb"],
+            self.revision,
+        )
+        .unwrap_or_else(|e| self.fatal(&e));
+        let mut cmds = dbg_cmds.commands.join("\n");
+
+        // compile test file (it should have 'compile-flags:-g' in the header)
+        let should_run = self.run_if_enabled();
+        let compiler_run_result = self.compile_test(should_run, Emit::None);
+        if !compiler_run_result.status.success() {
+            self.fatal_proc_rec("compilation failed!", &compiler_run_result);
+        }
+        if let WillExecute::Disabled = should_run {
+            return;
+        }
+
+        let exe_file = self.make_exe_name();
+
+        let debugger_run_result;
+        if is_android_gdb_target(&self.config.target) {
+            cmds = cmds.replace("run", "continue");
+
+            let tool_path = match self.config.android_cross_path.to_str() {
+                Some(x) => x.to_owned(),
+                None => self.fatal("cannot find android cross path"),
+            };
+
+            // write debugger script
+            let mut script_str = String::with_capacity(2048);
+            script_str.push_str(&format!("set charset {}\n", Self::charset()));
+            script_str.push_str(&format!("set sysroot {}\n", tool_path));
+            script_str.push_str(&format!("file {}\n", exe_file.to_str().unwrap()));
+            script_str.push_str("target remote :5039\n");
+            script_str.push_str(&format!(
+                "set solib-search-path \
+                 ./{}/stage2/lib/rustlib/{}/lib/\n",
+                self.config.host, self.config.target
+            ));
+            for line in &dbg_cmds.breakpoint_lines {
+                script_str.push_str(
+                    format!(
+                        "break {:?}:{}\n",
+                        self.testpaths.file.file_name().unwrap().to_string_lossy(),
+                        *line
+                    )
+                    .as_str(),
+                );
+            }
+            script_str.push_str(&cmds);
+            script_str.push_str("\nquit\n");
+
+            debug!("script_str = {}", script_str);
+            self.dump_output_file(&script_str, "debugger.script");
+
+            let adb_path = &self.config.adb_path;
+
+            Command::new(adb_path)
+                .arg("push")
+                .arg(&exe_file)
+                .arg(&self.config.adb_test_dir)
+                .status()
+                .unwrap_or_else(|e| panic!("failed to exec `{adb_path:?}`: {e:?}"));
+
+            Command::new(adb_path)
+                .args(&["forward", "tcp:5039", "tcp:5039"])
+                .status()
+                .unwrap_or_else(|e| panic!("failed to exec `{adb_path:?}`: {e:?}"));
+
+            let adb_arg = format!(
+                "export LD_LIBRARY_PATH={}; \
+                 gdbserver{} :5039 {}/{}",
+                self.config.adb_test_dir.clone(),
+                if self.config.target.contains("aarch64") { "64" } else { "" },
+                self.config.adb_test_dir.clone(),
+                exe_file.file_name().unwrap().to_str().unwrap()
+            );
+
+            debug!("adb arg: {}", adb_arg);
+            let mut adb = Command::new(adb_path)
+                .args(&["shell", &adb_arg])
+                .stdout(Stdio::piped())
+                .stderr(Stdio::inherit())
+                .spawn()
+                .unwrap_or_else(|e| panic!("failed to exec `{adb_path:?}`: {e:?}"));
+
+            // Wait for the gdbserver to print out "Listening on port ..."
+            // at which point we know that it's started and then we can
+            // execute the debugger below.
+            let mut stdout = BufReader::new(adb.stdout.take().unwrap());
+            let mut line = String::new();
+            loop {
+                line.truncate(0);
+                stdout.read_line(&mut line).unwrap();
+                if line.starts_with("Listening on port 5039") {
+                    break;
+                }
+            }
+            drop(stdout);
+
+            let mut debugger_script = OsString::from("-command=");
+            debugger_script.push(self.make_out_name("debugger.script"));
+            let debugger_opts: &[&OsStr] =
+                &["-quiet".as_ref(), "-batch".as_ref(), "-nx".as_ref(), &debugger_script];
+
+            let gdb_path = self.config.gdb.as_ref().unwrap();
+            let Output { status, stdout, stderr } = Command::new(&gdb_path)
+                .args(debugger_opts)
+                .output()
+                .unwrap_or_else(|e| panic!("failed to exec `{gdb_path:?}`: {e:?}"));
+            let cmdline = {
+                let mut gdb = Command::new(&format!("{}-gdb", self.config.target));
+                gdb.args(debugger_opts);
+                let cmdline = self.make_cmdline(&gdb, "");
+                logv(self.config, format!("executing {}", cmdline));
+                cmdline
+            };
+
+            debugger_run_result = ProcRes {
+                status,
+                stdout: String::from_utf8(stdout).unwrap(),
+                stderr: String::from_utf8(stderr).unwrap(),
+                truncated: Truncated::No,
+                cmdline,
+            };
+            if adb.kill().is_err() {
+                println!("Adb process is already finished.");
+            }
+        } else {
+            let rust_src_root =
+                self.config.find_rust_src_root().expect("Could not find Rust source root");
+            let rust_pp_module_rel_path = Path::new("./src/etc");
+            let rust_pp_module_abs_path =
+                rust_src_root.join(rust_pp_module_rel_path).to_str().unwrap().to_owned();
+            // write debugger script
+            let mut script_str = String::with_capacity(2048);
+            script_str.push_str(&format!("set charset {}\n", Self::charset()));
+            script_str.push_str("show version\n");
+
+            match self.config.gdb_version {
+                Some(version) => {
+                    println!("NOTE: compiletest thinks it is using GDB version {}", version);
+
+                    if version > extract_gdb_version("7.4").unwrap() {
+                        // Add the directory containing the pretty printers to
+                        // GDB's script auto loading safe path
+                        script_str.push_str(&format!(
+                            "add-auto-load-safe-path {}\n",
+                            rust_pp_module_abs_path.replace(r"\", r"\\")
+                        ));
+
+                        let output_base_dir = self.output_base_dir().to_str().unwrap().to_owned();
+
+                        // Add the directory containing the output binary to
+                        // include embedded pretty printers to GDB's script
+                        // auto loading safe path
+                        script_str.push_str(&format!(
+                            "add-auto-load-safe-path {}\n",
+                            output_base_dir.replace(r"\", r"\\")
+                        ));
+                    }
+                }
+                _ => {
+                    println!(
+                        "NOTE: compiletest does not know which version of \
+                         GDB it is using"
+                    );
+                }
+            }
+
+            // The following line actually doesn't have to do anything with
+            // pretty printing, it just tells GDB to print values on one line:
+            script_str.push_str("set print pretty off\n");
+
+            // Add the pretty printer directory to GDB's source-file search path
+            script_str
+                .push_str(&format!("directory {}\n", rust_pp_module_abs_path.replace(r"\", r"\\")));
+
+            // Load the target executable
+            script_str
+                .push_str(&format!("file {}\n", exe_file.to_str().unwrap().replace(r"\", r"\\")));
+
+            // Force GDB to print values in the Rust format.
+            script_str.push_str("set language rust\n");
+
+            // Add line breakpoints
+            for line in &dbg_cmds.breakpoint_lines {
+                script_str.push_str(&format!(
+                    "break '{}':{}\n",
+                    self.testpaths.file.file_name().unwrap().to_string_lossy(),
+                    *line
+                ));
+            }
+
+            script_str.push_str(&cmds);
+            script_str.push_str("\nquit\n");
+
+            debug!("script_str = {}", script_str);
+            self.dump_output_file(&script_str, "debugger.script");
+
+            let mut debugger_script = OsString::from("-command=");
+            debugger_script.push(self.make_out_name("debugger.script"));
+
+            let debugger_opts: &[&OsStr] =
+                &["-quiet".as_ref(), "-batch".as_ref(), "-nx".as_ref(), &debugger_script];
+
+            let mut gdb = Command::new(self.config.gdb.as_ref().unwrap());
+            let pythonpath = if let Ok(pp) = std::env::var("PYTHONPATH") {
+                format!("{pp}:{rust_pp_module_abs_path}")
+            } else {
+                rust_pp_module_abs_path
+            };
+            gdb.args(debugger_opts).env("PYTHONPATH", pythonpath);
+
+            debugger_run_result =
+                self.compose_and_run(gdb, self.config.run_lib_path.to_str().unwrap(), None, None);
+        }
+
+        if !debugger_run_result.status.success() {
+            self.fatal_proc_rec("gdb failed to execute", &debugger_run_result);
+        }
+
+        if let Err(e) = dbg_cmds.check_output(&debugger_run_result) {
+            self.fatal_proc_rec(&e, &debugger_run_result);
+        }
+    }
+
+    fn run_debuginfo_lldb_test(&self) {
+        if self.config.lldb_python_dir.is_none() {
+            self.fatal("Can't run LLDB test because LLDB's python path is not set.");
+        }
+
+        let config = Config {
+            target_rustcflags: self.cleanup_debug_info_options(&self.config.target_rustcflags),
+            host_rustcflags: self.cleanup_debug_info_options(&self.config.host_rustcflags),
+            ..self.config.clone()
+        };
+
+        let test_cx = TestCx { config: &config, ..*self };
+
+        test_cx.run_debuginfo_lldb_test_no_opt();
+    }
+
+    fn run_debuginfo_lldb_test_no_opt(&self) {
+        // compile test file (it should have 'compile-flags:-g' in the header)
+        let should_run = self.run_if_enabled();
+        let compile_result = self.compile_test(should_run, Emit::None);
+        if !compile_result.status.success() {
+            self.fatal_proc_rec("compilation failed!", &compile_result);
+        }
+        if let WillExecute::Disabled = should_run {
+            return;
+        }
+
+        let exe_file = self.make_exe_name();
+
+        match self.config.lldb_version {
+            Some(ref version) => {
+                println!("NOTE: compiletest thinks it is using LLDB version {}", version);
+            }
+            _ => {
+                println!(
+                    "NOTE: compiletest does not know which version of \
+                     LLDB it is using"
+                );
+            }
+        }
+
+        // Parse debugger commands etc from test files
+        let dbg_cmds = DebuggerCommands::parse_from(
+            &self.testpaths.file,
+            self.config,
+            &["lldb"],
+            self.revision,
+        )
+        .unwrap_or_else(|e| self.fatal(&e));
+
+        // Write debugger script:
+        // We don't want to hang when calling `quit` while the process is still running
+        let mut script_str = String::from("settings set auto-confirm true\n");
+
+        // Make LLDB emit its version, so we have it documented in the test output
+        script_str.push_str("version\n");
+
+        // Switch LLDB into "Rust mode"
+        let rust_src_root =
+            self.config.find_rust_src_root().expect("Could not find Rust source root");
+        let rust_pp_module_rel_path = Path::new("./src/etc");
+        let rust_pp_module_abs_path = rust_src_root.join(rust_pp_module_rel_path);
+
+        script_str.push_str(&format!(
+            "command script import {}/lldb_lookup.py\n",
+            rust_pp_module_abs_path.to_str().unwrap()
+        ));
+        File::open(rust_pp_module_abs_path.join("lldb_commands"))
+            .and_then(|mut file| file.read_to_string(&mut script_str))
+            .expect("Failed to read lldb_commands");
+
+        // Set breakpoints on every line that contains the string "#break"
+        let source_file_name = self.testpaths.file.file_name().unwrap().to_string_lossy();
+        for line in &dbg_cmds.breakpoint_lines {
+            script_str.push_str(&format!(
+                "breakpoint set --file '{}' --line {}\n",
+                source_file_name, line
+            ));
+        }
+
+        // Append the other commands
+        for line in &dbg_cmds.commands {
+            script_str.push_str(line);
+            script_str.push('\n');
+        }
+
+        // Finally, quit the debugger
+        script_str.push_str("\nquit\n");
+
+        // Write the script into a file
+        debug!("script_str = {}", script_str);
+        self.dump_output_file(&script_str, "debugger.script");
+        let debugger_script = self.make_out_name("debugger.script");
+
+        // Let LLDB execute the script via lldb_batchmode.py
+        let debugger_run_result = self.run_lldb(&exe_file, &debugger_script, &rust_src_root);
+
+        if !debugger_run_result.status.success() {
+            self.fatal_proc_rec("Error while running LLDB", &debugger_run_result);
+        }
+
+        if let Err(e) = dbg_cmds.check_output(&debugger_run_result) {
+            self.fatal_proc_rec(&e, &debugger_run_result);
+        }
+    }
+
+    fn run_lldb(
+        &self,
+        test_executable: &Path,
+        debugger_script: &Path,
+        rust_src_root: &Path,
+    ) -> ProcRes {
+        // Prepare the lldb_batchmode which executes the debugger script
+        let lldb_script_path = rust_src_root.join("src/etc/lldb_batchmode.py");
+        let pythonpath = if let Ok(pp) = std::env::var("PYTHONPATH") {
+            format!("{pp}:{}", self.config.lldb_python_dir.as_ref().unwrap())
+        } else {
+            self.config.lldb_python_dir.as_ref().unwrap().to_string()
+        };
+        self.run_command_to_procres(
+            Command::new(&self.config.python)
+                .arg(&lldb_script_path)
+                .arg(test_executable)
+                .arg(debugger_script)
+                .env("PYTHONUNBUFFERED", "1") // Help debugging #78665
+                .env("PYTHONPATH", pythonpath),
+        )
+    }
+
+    fn cleanup_debug_info_options(&self, options: &Vec<String>) -> Vec<String> {
+        // Remove options that are either unwanted (-O) or may lead to duplicates due to RUSTFLAGS.
+        let options_to_remove = ["-O".to_owned(), "-g".to_owned(), "--debuginfo".to_owned()];
+
+        options.iter().filter(|x| !options_to_remove.contains(x)).cloned().collect()
+    }
+}
diff --git a/src/tools/compiletest/src/runtest/incremental.rs b/src/tools/compiletest/src/runtest/incremental.rs
new file mode 100644
index 00000000000..81b006292e4
--- /dev/null
+++ b/src/tools/compiletest/src/runtest/incremental.rs
@@ -0,0 +1,128 @@
+use super::{TestCx, WillExecute};
+use crate::errors;
+
+// FIXME(jieyouxu): `run_rpass_test` got hoisted out of this because apparently valgrind falls back
+// to `run_rpass_test` if valgrind isn't available, which is questionable, but keeping it for
+// refactoring changes to preserve current behavior.
+
+impl TestCx<'_> {
+    pub(super) fn run_incremental_test(&self) {
+        // Basic plan for a test incremental/foo/bar.rs:
+        // - load list of revisions rpass1, cfail2, rpass3
+        //   - each should begin with `cpass`, `rpass`, `cfail`, or `rfail`
+        //   - if `cpass`, expect compilation to succeed, don't execute
+        //   - if `rpass`, expect compilation and execution to succeed
+        //   - if `cfail`, expect compilation to fail
+        //   - if `rfail`, expect compilation to succeed and execution to fail
+        // - create a directory build/foo/bar.incremental
+        // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C rpass1
+        //   - because name of revision starts with "rpass", expect success
+        // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C cfail2
+        //   - because name of revision starts with "cfail", expect an error
+        //   - load expected errors as usual, but filter for those that end in `[rfail2]`
+        // - compile foo/bar.rs with -C incremental=.../foo/bar.incremental and -C rpass3
+        //   - because name of revision starts with "rpass", expect success
+        // - execute build/foo/bar.exe and save output
+        //
+        // FIXME -- use non-incremental mode as an oracle? That doesn't apply
+        // to #[rustc_dirty] and clean tests I guess
+
+        let revision = self.revision.expect("incremental tests require a list of revisions");
+
+        // Incremental workproduct directory should have already been created.
+        let incremental_dir = self.props.incremental_dir.as_ref().unwrap();
+        assert!(incremental_dir.exists(), "init_incremental_test failed to create incremental dir");
+
+        if self.config.verbose {
+            print!("revision={:?} props={:#?}", revision, self.props);
+        }
+
+        if revision.starts_with("cpass") {
+            if self.props.should_ice {
+                self.fatal("can only use should-ice in cfail tests");
+            }
+            self.run_cpass_test();
+        } else if revision.starts_with("rpass") {
+            if self.props.should_ice {
+                self.fatal("can only use should-ice in cfail tests");
+            }
+            self.run_rpass_test();
+        } else if revision.starts_with("rfail") {
+            if self.props.should_ice {
+                self.fatal("can only use should-ice in cfail tests");
+            }
+            self.run_rfail_test();
+        } else if revision.starts_with("cfail") {
+            self.run_cfail_test();
+        } else {
+            self.fatal("revision name must begin with cpass, rpass, rfail, or cfail");
+        }
+    }
+
+    fn run_cpass_test(&self) {
+        let emit_metadata = self.should_emit_metadata(self.pass_mode());
+        let proc_res = self.compile_test(WillExecute::No, emit_metadata);
+
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("compilation failed!", &proc_res);
+        }
+
+        // FIXME(#41968): Move this check to tidy?
+        if !errors::load_errors(&self.testpaths.file, self.revision).is_empty() {
+            self.fatal("compile-pass tests with expected warnings should be moved to ui/");
+        }
+    }
+
+    fn run_cfail_test(&self) {
+        let pm = self.pass_mode();
+        let proc_res = self.compile_test(WillExecute::No, self.should_emit_metadata(pm));
+        self.check_if_test_should_compile(&proc_res, pm);
+        self.check_no_compiler_crash(&proc_res, self.props.should_ice);
+
+        let output_to_check = self.get_output(&proc_res);
+        let expected_errors = errors::load_errors(&self.testpaths.file, self.revision);
+        if !expected_errors.is_empty() {
+            if !self.props.error_patterns.is_empty() || !self.props.regex_error_patterns.is_empty()
+            {
+                self.fatal("both error pattern and expected errors specified");
+            }
+            self.check_expected_errors(expected_errors, &proc_res);
+        } else {
+            self.check_all_error_patterns(&output_to_check, &proc_res, pm);
+        }
+        if self.props.should_ice {
+            match proc_res.status.code() {
+                Some(101) => (),
+                _ => self.fatal("expected ICE"),
+            }
+        }
+
+        self.check_forbid_output(&output_to_check, &proc_res);
+    }
+
+    fn run_rfail_test(&self) {
+        let pm = self.pass_mode();
+        let should_run = self.run_if_enabled();
+        let proc_res = self.compile_test(should_run, self.should_emit_metadata(pm));
+
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("compilation failed!", &proc_res);
+        }
+
+        if let WillExecute::Disabled = should_run {
+            return;
+        }
+
+        let proc_res = self.exec_compiled_test();
+
+        // The value our Makefile configures valgrind to return on failure
+        const VALGRIND_ERR: i32 = 100;
+        if proc_res.status.code() == Some(VALGRIND_ERR) {
+            self.fatal_proc_rec("run-fail test isn't valgrind-clean!", &proc_res);
+        }
+
+        let output_to_check = self.get_output(&proc_res);
+        self.check_correct_failure_status(&proc_res);
+        self.check_all_error_patterns(&output_to_check, &proc_res, pm);
+    }
+}
diff --git a/src/tools/compiletest/src/runtest/js_doc.rs b/src/tools/compiletest/src/runtest/js_doc.rs
new file mode 100644
index 00000000000..68c74cd155c
--- /dev/null
+++ b/src/tools/compiletest/src/runtest/js_doc.rs
@@ -0,0 +1,32 @@
+use std::process::Command;
+
+use super::TestCx;
+
+impl TestCx<'_> {
+    pub(super) fn run_js_doc_test(&self) {
+        if let Some(nodejs) = &self.config.nodejs {
+            let out_dir = self.output_base_dir();
+
+            self.document(&out_dir, &self.testpaths);
+
+            let root = self.config.find_rust_src_root().unwrap();
+            let file_stem =
+                self.testpaths.file.file_stem().and_then(|f| f.to_str()).expect("no file stem");
+            let res = self.run_command_to_procres(
+                Command::new(&nodejs)
+                    .arg(root.join("src/tools/rustdoc-js/tester.js"))
+                    .arg("--doc-folder")
+                    .arg(out_dir)
+                    .arg("--crate-name")
+                    .arg(file_stem.replace("-", "_"))
+                    .arg("--test-file")
+                    .arg(self.testpaths.file.with_extension("js")),
+            );
+            if !res.status.success() {
+                self.fatal_proc_rec("rustdoc-js test failed!", &res);
+            }
+        } else {
+            self.fatal("no nodeJS");
+        }
+    }
+}
diff --git a/src/tools/compiletest/src/runtest/mir_opt.rs b/src/tools/compiletest/src/runtest/mir_opt.rs
new file mode 100644
index 00000000000..02289a8df1e
--- /dev/null
+++ b/src/tools/compiletest/src/runtest/mir_opt.rs
@@ -0,0 +1,155 @@
+use std::fs;
+use std::path::{Path, PathBuf};
+
+use glob::glob;
+use miropt_test_tools::{files_for_miropt_test, MiroptTest, MiroptTestFile};
+use tracing::debug;
+
+use super::{Emit, TestCx, WillExecute};
+use crate::compute_diff::write_diff;
+
+impl TestCx<'_> {
+    pub(super) fn run_mir_opt_test(&self) {
+        let pm = self.pass_mode();
+        let should_run = self.should_run(pm);
+
+        let mut test_info = files_for_miropt_test(
+            &self.testpaths.file,
+            self.config.get_pointer_width(),
+            self.config.target_cfg().panic.for_miropt_test_tools(),
+        );
+
+        let passes = std::mem::take(&mut test_info.passes);
+
+        let proc_res = self.compile_test_with_passes(should_run, Emit::Mir, passes);
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("compilation failed!", &proc_res);
+        }
+        self.check_mir_dump(test_info);
+
+        if let WillExecute::Yes = should_run {
+            let proc_res = self.exec_compiled_test();
+
+            if !proc_res.status.success() {
+                self.fatal_proc_rec("test run failed!", &proc_res);
+            }
+        }
+    }
+
+    fn check_mir_dump(&self, test_info: MiroptTest) {
+        let test_dir = self.testpaths.file.parent().unwrap();
+        let test_crate =
+            self.testpaths.file.file_stem().unwrap().to_str().unwrap().replace('-', "_");
+
+        let MiroptTest { run_filecheck, suffix, files, passes: _ } = test_info;
+
+        if self.config.bless {
+            for e in
+                glob(&format!("{}/{}.*{}.mir", test_dir.display(), test_crate, suffix)).unwrap()
+            {
+                fs::remove_file(e.unwrap()).unwrap();
+            }
+            for e in
+                glob(&format!("{}/{}.*{}.diff", test_dir.display(), test_crate, suffix)).unwrap()
+            {
+                fs::remove_file(e.unwrap()).unwrap();
+            }
+        }
+
+        for MiroptTestFile { from_file, to_file, expected_file } in files {
+            let dumped_string = if let Some(after) = to_file {
+                self.diff_mir_files(from_file.into(), after.into())
+            } else {
+                let mut output_file = PathBuf::new();
+                output_file.push(self.get_mir_dump_dir());
+                output_file.push(&from_file);
+                debug!(
+                    "comparing the contents of: {} with {}",
+                    output_file.display(),
+                    expected_file.display()
+                );
+                if !output_file.exists() {
+                    panic!(
+                        "Output file `{}` from test does not exist, available files are in `{}`",
+                        output_file.display(),
+                        output_file.parent().unwrap().display()
+                    );
+                }
+                self.check_mir_test_timestamp(&from_file, &output_file);
+                let dumped_string = fs::read_to_string(&output_file).unwrap();
+                self.normalize_output(&dumped_string, &[])
+            };
+
+            if self.config.bless {
+                let _ = fs::remove_file(&expected_file);
+                fs::write(expected_file, dumped_string.as_bytes()).unwrap();
+            } else {
+                if !expected_file.exists() {
+                    panic!("Output file `{}` from test does not exist", expected_file.display());
+                }
+                let expected_string = fs::read_to_string(&expected_file).unwrap();
+                if dumped_string != expected_string {
+                    print!("{}", write_diff(&expected_string, &dumped_string, 3));
+                    panic!(
+                        "Actual MIR output differs from expected MIR output {}",
+                        expected_file.display()
+                    );
+                }
+            }
+        }
+
+        if run_filecheck {
+            let output_path = self.output_base_name().with_extension("mir");
+            let proc_res = self.verify_with_filecheck(&output_path);
+            if !proc_res.status.success() {
+                self.fatal_proc_rec("verification with 'FileCheck' failed", &proc_res);
+            }
+        }
+    }
+
+    fn diff_mir_files(&self, before: PathBuf, after: PathBuf) -> String {
+        let to_full_path = |path: PathBuf| {
+            let full = self.get_mir_dump_dir().join(&path);
+            if !full.exists() {
+                panic!(
+                    "the mir dump file for {} does not exist (requested in {})",
+                    path.display(),
+                    self.testpaths.file.display(),
+                );
+            }
+            full
+        };
+        let before = to_full_path(before);
+        let after = to_full_path(after);
+        debug!("comparing the contents of: {} with {}", before.display(), after.display());
+        let before = fs::read_to_string(before).unwrap();
+        let after = fs::read_to_string(after).unwrap();
+        let before = self.normalize_output(&before, &[]);
+        let after = self.normalize_output(&after, &[]);
+        let mut dumped_string = String::new();
+        for result in diff::lines(&before, &after) {
+            use std::fmt::Write;
+            match result {
+                diff::Result::Left(s) => writeln!(dumped_string, "- {}", s).unwrap(),
+                diff::Result::Right(s) => writeln!(dumped_string, "+ {}", s).unwrap(),
+                diff::Result::Both(s, _) => writeln!(dumped_string, "  {}", s).unwrap(),
+            }
+        }
+        dumped_string
+    }
+
+    fn check_mir_test_timestamp(&self, test_name: &str, output_file: &Path) {
+        let t = |file| fs::metadata(file).unwrap().modified().unwrap();
+        let source_file = &self.testpaths.file;
+        let output_time = t(output_file);
+        let source_time = t(source_file);
+        if source_time > output_time {
+            debug!("source file time: {:?} output file time: {:?}", source_time, output_time);
+            panic!(
+                "test source file `{}` is newer than potentially stale output file `{}`.",
+                source_file.display(),
+                test_name
+            );
+        }
+    }
+}
diff --git a/src/tools/compiletest/src/runtest/pretty.rs b/src/tools/compiletest/src/runtest/pretty.rs
new file mode 100644
index 00000000000..40e767e84ef
--- /dev/null
+++ b/src/tools/compiletest/src/runtest/pretty.rs
@@ -0,0 +1,104 @@
+use std::fs;
+
+use super::{ProcRes, ReadFrom, TestCx};
+use crate::util::logv;
+
+impl TestCx<'_> {
+    pub(super) fn run_pretty_test(&self) {
+        if self.props.pp_exact.is_some() {
+            logv(self.config, "testing for exact pretty-printing".to_owned());
+        } else {
+            logv(self.config, "testing for converging pretty-printing".to_owned());
+        }
+
+        let rounds = match self.props.pp_exact {
+            Some(_) => 1,
+            None => 2,
+        };
+
+        let src = fs::read_to_string(&self.testpaths.file).unwrap();
+        let mut srcs = vec![src];
+
+        let mut round = 0;
+        while round < rounds {
+            logv(
+                self.config,
+                format!("pretty-printing round {} revision {:?}", round, self.revision),
+            );
+            let read_from =
+                if round == 0 { ReadFrom::Path } else { ReadFrom::Stdin(srcs[round].to_owned()) };
+
+            let proc_res = self.print_source(read_from, &self.props.pretty_mode);
+            if !proc_res.status.success() {
+                self.fatal_proc_rec(
+                    &format!(
+                        "pretty-printing failed in round {} revision {:?}",
+                        round, self.revision
+                    ),
+                    &proc_res,
+                );
+            }
+
+            let ProcRes { stdout, .. } = proc_res;
+            srcs.push(stdout);
+            round += 1;
+        }
+
+        let mut expected = match self.props.pp_exact {
+            Some(ref file) => {
+                let filepath = self.testpaths.file.parent().unwrap().join(file);
+                fs::read_to_string(&filepath).unwrap()
+            }
+            None => srcs[srcs.len() - 2].clone(),
+        };
+        let mut actual = srcs[srcs.len() - 1].clone();
+
+        if self.props.pp_exact.is_some() {
+            // Now we have to care about line endings
+            let cr = "\r".to_owned();
+            actual = actual.replace(&cr, "");
+            expected = expected.replace(&cr, "");
+        }
+
+        if !self.config.bless {
+            self.compare_source(&expected, &actual);
+        } else if expected != actual {
+            let filepath_buf;
+            let filepath = match &self.props.pp_exact {
+                Some(file) => {
+                    filepath_buf = self.testpaths.file.parent().unwrap().join(file);
+                    &filepath_buf
+                }
+                None => &self.testpaths.file,
+            };
+            fs::write(filepath, &actual).unwrap();
+        }
+
+        // If we're only making sure that the output matches then just stop here
+        if self.props.pretty_compare_only {
+            return;
+        }
+
+        // Finally, let's make sure it actually appears to remain valid code
+        let proc_res = self.typecheck_source(actual);
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("pretty-printed source does not typecheck", &proc_res);
+        }
+
+        if !self.props.pretty_expanded {
+            return;
+        }
+
+        // additionally, run `-Zunpretty=expanded` and try to build it.
+        let proc_res = self.print_source(ReadFrom::Path, "expanded");
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("pretty-printing (expanded) failed", &proc_res);
+        }
+
+        let ProcRes { stdout: expanded_src, .. } = proc_res;
+        let proc_res = self.typecheck_source(expanded_src);
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("pretty-printed source (expanded) does not typecheck", &proc_res);
+        }
+    }
+}
diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs
new file mode 100644
index 00000000000..75fe6a6baaf
--- /dev/null
+++ b/src/tools/compiletest/src/runtest/run_make.rs
@@ -0,0 +1,526 @@
+use std::path::Path;
+use std::process::{Command, Output, Stdio};
+use std::{env, fs};
+
+use super::{ProcRes, TestCx};
+use crate::util::{copy_dir_all, dylib_env_var};
+
+impl TestCx<'_> {
+    pub(super) fn run_rmake_test(&self) {
+        let test_dir = &self.testpaths.file;
+        if test_dir.join("rmake.rs").exists() {
+            self.run_rmake_v2_test();
+        } else if test_dir.join("Makefile").exists() {
+            self.run_rmake_legacy_test();
+        } else {
+            self.fatal("failed to find either `rmake.rs` or `Makefile`")
+        }
+    }
+
+    fn run_rmake_legacy_test(&self) {
+        let cwd = env::current_dir().unwrap();
+        let src_root = self.config.src_base.parent().unwrap().parent().unwrap();
+        let src_root = cwd.join(&src_root);
+
+        let tmpdir = cwd.join(self.output_base_name());
+        if tmpdir.exists() {
+            self.aggressive_rm_rf(&tmpdir).unwrap();
+        }
+        fs::create_dir_all(&tmpdir).unwrap();
+
+        let host = &self.config.host;
+        let make = if host.contains("dragonfly")
+            || host.contains("freebsd")
+            || host.contains("netbsd")
+            || host.contains("openbsd")
+            || host.contains("aix")
+        {
+            "gmake"
+        } else {
+            "make"
+        };
+
+        let mut cmd = Command::new(make);
+        cmd.current_dir(&self.testpaths.file)
+            .stdout(Stdio::piped())
+            .stderr(Stdio::piped())
+            .env("TARGET", &self.config.target)
+            .env("PYTHON", &self.config.python)
+            .env("S", src_root)
+            .env("RUST_BUILD_STAGE", &self.config.stage_id)
+            .env("RUSTC", cwd.join(&self.config.rustc_path))
+            .env("TMPDIR", &tmpdir)
+            .env("LD_LIB_PATH_ENVVAR", dylib_env_var())
+            .env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path))
+            .env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path))
+            .env("LLVM_COMPONENTS", &self.config.llvm_components)
+            // We for sure don't want these tests to run in parallel, so make
+            // sure they don't have access to these vars if we run via `make`
+            // at the top level
+            .env_remove("MAKEFLAGS")
+            .env_remove("MFLAGS")
+            .env_remove("CARGO_MAKEFLAGS");
+
+        if let Some(ref cargo) = self.config.cargo_path {
+            cmd.env("CARGO", cwd.join(cargo));
+        }
+
+        if let Some(ref rustdoc) = self.config.rustdoc_path {
+            cmd.env("RUSTDOC", cwd.join(rustdoc));
+        }
+
+        if let Some(ref node) = self.config.nodejs {
+            cmd.env("NODE", node);
+        }
+
+        if let Some(ref linker) = self.config.target_linker {
+            cmd.env("RUSTC_LINKER", linker);
+        }
+
+        if let Some(ref clang) = self.config.run_clang_based_tests_with {
+            cmd.env("CLANG", clang);
+        }
+
+        if let Some(ref filecheck) = self.config.llvm_filecheck {
+            cmd.env("LLVM_FILECHECK", filecheck);
+        }
+
+        if let Some(ref llvm_bin_dir) = self.config.llvm_bin_dir {
+            cmd.env("LLVM_BIN_DIR", llvm_bin_dir);
+        }
+
+        if let Some(ref remote_test_client) = self.config.remote_test_client {
+            cmd.env("REMOTE_TEST_CLIENT", remote_test_client);
+        }
+
+        // We don't want RUSTFLAGS set from the outside to interfere with
+        // compiler flags set in the test cases:
+        cmd.env_remove("RUSTFLAGS");
+
+        // Use dynamic musl for tests because static doesn't allow creating dylibs
+        if self.config.host.contains("musl") {
+            cmd.env("RUSTFLAGS", "-Ctarget-feature=-crt-static").env("IS_MUSL_HOST", "1");
+        }
+
+        if self.config.bless {
+            cmd.env("RUSTC_BLESS_TEST", "--bless");
+            // Assume this option is active if the environment variable is "defined", with _any_ value.
+            // As an example, a `Makefile` can use this option by:
+            //
+            //   ifdef RUSTC_BLESS_TEST
+            //       cp "$(TMPDIR)"/actual_something.ext expected_something.ext
+            //   else
+            //       $(DIFF) expected_something.ext "$(TMPDIR)"/actual_something.ext
+            //   endif
+        }
+
+        if self.config.target.contains("msvc") && !self.config.cc.is_empty() {
+            // We need to pass a path to `lib.exe`, so assume that `cc` is `cl.exe`
+            // and that `lib.exe` lives next to it.
+            let lib = Path::new(&self.config.cc).parent().unwrap().join("lib.exe");
+
+            // MSYS doesn't like passing flags of the form `/foo` as it thinks it's
+            // a path and instead passes `C:\msys64\foo`, so convert all
+            // `/`-arguments to MSVC here to `-` arguments.
+            let cflags = self
+                .config
+                .cflags
+                .split(' ')
+                .map(|s| s.replace("/", "-"))
+                .collect::<Vec<_>>()
+                .join(" ");
+            let cxxflags = self
+                .config
+                .cxxflags
+                .split(' ')
+                .map(|s| s.replace("/", "-"))
+                .collect::<Vec<_>>()
+                .join(" ");
+
+            cmd.env("IS_MSVC", "1")
+                .env("IS_WINDOWS", "1")
+                .env("MSVC_LIB", format!("'{}' -nologo", lib.display()))
+                .env("MSVC_LIB_PATH", format!("{}", lib.display()))
+                .env("CC", format!("'{}' {}", self.config.cc, cflags))
+                .env("CXX", format!("'{}' {}", &self.config.cxx, cxxflags));
+        } else {
+            cmd.env("CC", format!("{} {}", self.config.cc, self.config.cflags))
+                .env("CXX", format!("{} {}", self.config.cxx, self.config.cxxflags))
+                .env("AR", &self.config.ar);
+
+            if self.config.target.contains("windows") {
+                cmd.env("IS_WINDOWS", "1");
+            }
+        }
+
+        let (output, truncated) =
+            self.read2_abbreviated(cmd.spawn().expect("failed to spawn `make`"));
+        if !output.status.success() {
+            let res = ProcRes {
+                status: output.status,
+                stdout: String::from_utf8_lossy(&output.stdout).into_owned(),
+                stderr: String::from_utf8_lossy(&output.stderr).into_owned(),
+                truncated,
+                cmdline: format!("{:?}", cmd),
+            };
+            self.fatal_proc_rec("make failed", &res);
+        }
+    }
+
+    fn run_rmake_v2_test(&self) {
+        // For `run-make` V2, we need to perform 2 steps to build and run a `run-make` V2 recipe
+        // (`rmake.rs`) to run the actual tests. The support library is already built as a tool rust
+        // library and is available under `build/$TARGET/stageN-tools-bin/librun_make_support.rlib`.
+        //
+        // 1. We need to build the recipe `rmake.rs` as a binary and link in the `run_make_support`
+        //    library.
+        // 2. We need to run the recipe binary.
+
+        // So we assume the rust-lang/rust project setup looks like the following (our `.` is the
+        // top-level directory, irrelevant entries to our purposes omitted):
+        //
+        // ```
+        // .                               // <- `source_root`
+        // ├── build/                      // <- `build_root`
+        // ├── compiler/
+        // ├── library/
+        // ├── src/
+        // │  └── tools/
+        // │     └── run_make_support/
+        // └── tests
+        //    └── run-make/
+        // ```
+
+        // `source_root` is the top-level directory containing the rust-lang/rust checkout.
+        let source_root =
+            self.config.find_rust_src_root().expect("could not determine rust source root");
+        // `self.config.build_base` is actually the build base folder + "test" + test suite name, it
+        // looks like `build/<host_triple>/test/run-make`. But we want `build/<host_triple>/`. Note
+        // that the `build` directory does not need to be called `build`, nor does it need to be
+        // under `source_root`, so we must compute it based off of `self.config.build_base`.
+        let build_root =
+            self.config.build_base.parent().and_then(Path::parent).unwrap().to_path_buf();
+
+        // We construct the following directory tree for each rmake.rs test:
+        // ```
+        // <base_dir>/
+        //     rmake.exe
+        //     rmake_out/
+        // ```
+        // having the recipe executable separate from the output artifacts directory allows the
+        // recipes to `remove_dir_all($TMPDIR)` without running into issues related trying to remove
+        // a currently running executable because the recipe executable is not under the
+        // `rmake_out/` directory.
+        //
+        // This setup intentionally diverges from legacy Makefile run-make tests.
+        let base_dir = self.output_base_name();
+        if base_dir.exists() {
+            self.aggressive_rm_rf(&base_dir).unwrap();
+        }
+        let rmake_out_dir = base_dir.join("rmake_out");
+        fs::create_dir_all(&rmake_out_dir).unwrap();
+
+        // Copy all input files (apart from rmake.rs) to the temporary directory,
+        // so that the input directory structure from `tests/run-make/<test>` is mirrored
+        // to the `rmake_out` directory.
+        for path in walkdir::WalkDir::new(&self.testpaths.file).min_depth(1) {
+            let path = path.unwrap().path().to_path_buf();
+            if path.file_name().is_some_and(|s| s != "rmake.rs") {
+                let target = rmake_out_dir.join(path.strip_prefix(&self.testpaths.file).unwrap());
+                if path.is_dir() {
+                    copy_dir_all(&path, target).unwrap();
+                } else {
+                    fs::copy(&path, target).unwrap();
+                }
+            }
+        }
+
+        // `self.config.stage_id` looks like `stage1-<target_triple>`, but we only want
+        // the `stage1` part as that is what the output directories of bootstrap are prefixed with.
+        // Note that this *assumes* build layout from bootstrap is produced as:
+        //
+        // ```
+        // build/<target_triple>/          // <- this is `build_root`
+        // ├── stage0
+        // ├── stage0-bootstrap-tools
+        // ├── stage0-codegen
+        // ├── stage0-rustc
+        // ├── stage0-std
+        // ├── stage0-sysroot
+        // ├── stage0-tools
+        // ├── stage0-tools-bin
+        // ├── stage1
+        // ├── stage1-std
+        // ├── stage1-tools
+        // ├── stage1-tools-bin
+        // └── test
+        // ```
+        // FIXME(jieyouxu): improve the communication between bootstrap and compiletest here so
+        // we don't have to hack out a `stageN`.
+        let stage = self.config.stage_id.split('-').next().unwrap();
+
+        // In order to link in the support library as a rlib when compiling recipes, we need three
+        // paths:
+        // 1. Path of the built support library rlib itself.
+        // 2. Path of the built support library's dependencies directory.
+        // 3. Path of the built support library's dependencies' dependencies directory.
+        //
+        // The paths look like
+        //
+        // ```
+        // build/<target_triple>/
+        // ├── stageN-tools-bin/
+        // │   └── librun_make_support.rlib       // <- support rlib itself
+        // ├── stageN-tools/
+        // │   ├── release/deps/                  // <- deps of deps
+        // │   └── <host_triple>/release/deps/    // <- deps
+        // ```
+        //
+        // FIXME(jieyouxu): there almost certainly is a better way to do this (specifically how the
+        // support lib and its deps are organized, can't we copy them to the tools-bin dir as
+        // well?), but this seems to work for now.
+
+        let stage_tools_bin = build_root.join(format!("{stage}-tools-bin"));
+        let support_lib_path = stage_tools_bin.join("librun_make_support.rlib");
+
+        let stage_tools = build_root.join(format!("{stage}-tools"));
+        let support_lib_deps = stage_tools.join(&self.config.host).join("release").join("deps");
+        let support_lib_deps_deps = stage_tools.join("release").join("deps");
+
+        // To compile the recipe with rustc, we need to provide suitable dynamic library search
+        // paths to rustc. This includes both:
+        // 1. The "base" dylib search paths that was provided to compiletest, e.g. `LD_LIBRARY_PATH`
+        //    on some linux distros.
+        // 2. Specific library paths in `self.config.compile_lib_path` needed for running rustc.
+
+        let base_dylib_search_paths =
+            Vec::from_iter(env::split_paths(&env::var(dylib_env_var()).unwrap()));
+
+        let host_dylib_search_paths = {
+            let mut paths = vec![self.config.compile_lib_path.clone()];
+            paths.extend(base_dylib_search_paths.iter().cloned());
+            paths
+        };
+
+        // Calculate the paths of the recipe binary. As previously discussed, this is placed at
+        // `<base_dir>/<bin_name>` with `bin_name` being `rmake` or `rmake.exe` depending on
+        // platform.
+        let recipe_bin = {
+            let mut p = base_dir.join("rmake");
+            p.set_extension(env::consts::EXE_EXTENSION);
+            p
+        };
+
+        let mut rustc = Command::new(&self.config.rustc_path);
+        rustc
+            .arg("-o")
+            .arg(&recipe_bin)
+            // Specify library search paths for `run_make_support`.
+            .arg(format!("-Ldependency={}", &support_lib_path.parent().unwrap().to_string_lossy()))
+            .arg(format!("-Ldependency={}", &support_lib_deps.to_string_lossy()))
+            .arg(format!("-Ldependency={}", &support_lib_deps_deps.to_string_lossy()))
+            // Provide `run_make_support` as extern prelude, so test writers don't need to write
+            // `extern run_make_support;`.
+            .arg("--extern")
+            .arg(format!("run_make_support={}", &support_lib_path.to_string_lossy()))
+            .arg("--edition=2021")
+            .arg(&self.testpaths.file.join("rmake.rs"))
+            // Provide necessary library search paths for rustc.
+            .env(dylib_env_var(), &env::join_paths(host_dylib_search_paths).unwrap());
+
+        // In test code we want to be very pedantic about values being silently discarded that are
+        // annotated with `#[must_use]`.
+        rustc.arg("-Dunused_must_use");
+
+        // > `cg_clif` uses `COMPILETEST_FORCE_STAGE0=1 ./x.py test --stage 0` for running the rustc
+        // > test suite. With the introduction of rmake.rs this broke. `librun_make_support.rlib` is
+        // > compiled using the bootstrap rustc wrapper which sets `--sysroot
+        // > build/aarch64-unknown-linux-gnu/stage0-sysroot`, but then compiletest will compile
+        // > `rmake.rs` using the sysroot of the bootstrap compiler causing it to not find the
+        // > `libstd.rlib` against which `librun_make_support.rlib` is compiled.
+        //
+        // The gist here is that we have to pass the proper stage0 sysroot if we want
+        //
+        // ```
+        // $ COMPILETEST_FORCE_STAGE0=1 ./x test run-make --stage 0
+        // ```
+        //
+        // to work correctly.
+        //
+        // See <https://github.com/rust-lang/rust/pull/122248> for more background.
+        if std::env::var_os("COMPILETEST_FORCE_STAGE0").is_some() {
+            let stage0_sysroot = build_root.join("stage0-sysroot");
+            rustc.arg("--sysroot").arg(&stage0_sysroot);
+        }
+
+        // Now run rustc to build the recipe.
+        let res = self.run_command_to_procres(&mut rustc);
+        if !res.status.success() {
+            self.fatal_proc_rec("run-make test failed: could not build `rmake.rs` recipe", &res);
+        }
+
+        // To actually run the recipe, we have to provide the recipe with a bunch of information
+        // provided through env vars.
+
+        // Compute stage-specific standard library paths.
+        let stage_std_path = build_root.join(&stage).join("lib");
+
+        // Compute dynamic library search paths for recipes.
+        let recipe_dylib_search_paths = {
+            let mut paths = base_dylib_search_paths.clone();
+            paths.push(support_lib_path.parent().unwrap().to_path_buf());
+            paths.push(stage_std_path.join("rustlib").join(&self.config.host).join("lib"));
+            paths
+        };
+
+        // Compute runtime library search paths for recipes. This is target-specific.
+        let target_runtime_dylib_search_paths = {
+            let mut paths = vec![rmake_out_dir.clone()];
+            paths.extend(base_dylib_search_paths.iter().cloned());
+            paths
+        };
+
+        // FIXME(jieyouxu): please rename `TARGET_RPATH_ENV`, `HOST_RPATH_DIR` and
+        // `TARGET_RPATH_DIR`, it is **extremely** confusing!
+        let mut cmd = Command::new(&recipe_bin);
+        cmd.current_dir(&rmake_out_dir)
+            .stdout(Stdio::piped())
+            .stderr(Stdio::piped())
+            // Provide the target-specific env var that is used to record dylib search paths. For
+            // example, this could be `LD_LIBRARY_PATH` on some linux distros but `PATH` on Windows.
+            .env("LD_LIB_PATH_ENVVAR", dylib_env_var())
+            // Provide the dylib search paths.
+            .env(dylib_env_var(), &env::join_paths(recipe_dylib_search_paths).unwrap())
+            // Provide runtime dylib search paths.
+            .env("TARGET_RPATH_ENV", &env::join_paths(target_runtime_dylib_search_paths).unwrap())
+            // Provide the target.
+            .env("TARGET", &self.config.target)
+            // Some tests unfortunately still need Python, so provide path to a Python interpreter.
+            .env("PYTHON", &self.config.python)
+            // Provide path to checkout root. This is the top-level directory containing
+            // rust-lang/rust checkout.
+            .env("SOURCE_ROOT", &source_root)
+            // Provide path to stage-corresponding rustc.
+            .env("RUSTC", &self.config.rustc_path)
+            // Provide the directory to libraries that are needed to run the *compiler*. This is not
+            // to be confused with `TARGET_RPATH_ENV` or `TARGET_RPATH_DIR`. This is needed if the
+            // recipe wants to invoke rustc.
+            .env("HOST_RPATH_DIR", &self.config.compile_lib_path)
+            // Provide the directory to libraries that might be needed to run compiled binaries
+            // (further compiled by the recipe!).
+            .env("TARGET_RPATH_DIR", &self.config.run_lib_path)
+            // Provide which LLVM components are available (e.g. which LLVM components are provided
+            // through a specific CI runner).
+            .env("LLVM_COMPONENTS", &self.config.llvm_components);
+
+        if let Some(ref cargo) = self.config.cargo_path {
+            cmd.env("CARGO", source_root.join(cargo));
+        }
+
+        if let Some(ref rustdoc) = self.config.rustdoc_path {
+            cmd.env("RUSTDOC", source_root.join(rustdoc));
+        }
+
+        if let Some(ref node) = self.config.nodejs {
+            cmd.env("NODE", node);
+        }
+
+        if let Some(ref linker) = self.config.target_linker {
+            cmd.env("RUSTC_LINKER", linker);
+        }
+
+        if let Some(ref clang) = self.config.run_clang_based_tests_with {
+            cmd.env("CLANG", clang);
+        }
+
+        if let Some(ref filecheck) = self.config.llvm_filecheck {
+            cmd.env("LLVM_FILECHECK", filecheck);
+        }
+
+        if let Some(ref llvm_bin_dir) = self.config.llvm_bin_dir {
+            cmd.env("LLVM_BIN_DIR", llvm_bin_dir);
+        }
+
+        if let Some(ref remote_test_client) = self.config.remote_test_client {
+            cmd.env("REMOTE_TEST_CLIENT", remote_test_client);
+        }
+
+        // We don't want RUSTFLAGS set from the outside to interfere with
+        // compiler flags set in the test cases:
+        cmd.env_remove("RUSTFLAGS");
+
+        // Use dynamic musl for tests because static doesn't allow creating dylibs
+        if self.config.host.contains("musl") {
+            cmd.env("RUSTFLAGS", "-Ctarget-feature=-crt-static").env("IS_MUSL_HOST", "1");
+        }
+
+        if self.config.bless {
+            // If we're running in `--bless` mode, set an environment variable to tell
+            // `run_make_support` to bless snapshot files instead of checking them.
+            //
+            // The value is this test's source directory, because the support code
+            // will need that path in order to bless the _original_ snapshot files,
+            // not the copies in `rmake_out`.
+            // (See <https://github.com/rust-lang/rust/issues/129038>.)
+            cmd.env("RUSTC_BLESS_TEST", &self.testpaths.file);
+        }
+
+        if self.config.target.contains("msvc") && !self.config.cc.is_empty() {
+            // We need to pass a path to `lib.exe`, so assume that `cc` is `cl.exe`
+            // and that `lib.exe` lives next to it.
+            let lib = Path::new(&self.config.cc).parent().unwrap().join("lib.exe");
+
+            // MSYS doesn't like passing flags of the form `/foo` as it thinks it's
+            // a path and instead passes `C:\msys64\foo`, so convert all
+            // `/`-arguments to MSVC here to `-` arguments.
+            let cflags = self
+                .config
+                .cflags
+                .split(' ')
+                .map(|s| s.replace("/", "-"))
+                .collect::<Vec<_>>()
+                .join(" ");
+            let cxxflags = self
+                .config
+                .cxxflags
+                .split(' ')
+                .map(|s| s.replace("/", "-"))
+                .collect::<Vec<_>>()
+                .join(" ");
+
+            cmd.env("IS_MSVC", "1")
+                .env("IS_WINDOWS", "1")
+                .env("MSVC_LIB", format!("'{}' -nologo", lib.display()))
+                .env("MSVC_LIB_PATH", format!("{}", lib.display()))
+                // Note: we diverge from legacy run_make and don't lump `CC` the compiler and
+                // default flags together.
+                .env("CC_DEFAULT_FLAGS", &cflags)
+                .env("CC", &self.config.cc)
+                .env("CXX_DEFAULT_FLAGS", &cxxflags)
+                .env("CXX", &self.config.cxx);
+        } else {
+            cmd.env("CC_DEFAULT_FLAGS", &self.config.cflags)
+                .env("CC", &self.config.cc)
+                .env("CXX_DEFAULT_FLAGS", &self.config.cxxflags)
+                .env("CXX", &self.config.cxx)
+                .env("AR", &self.config.ar);
+
+            if self.config.target.contains("windows") {
+                cmd.env("IS_WINDOWS", "1");
+            }
+        }
+
+        let (Output { stdout, stderr, status }, truncated) =
+            self.read2_abbreviated(cmd.spawn().expect("failed to spawn `rmake`"));
+        if !status.success() {
+            let res = ProcRes {
+                status,
+                stdout: String::from_utf8_lossy(&stdout).into_owned(),
+                stderr: String::from_utf8_lossy(&stderr).into_owned(),
+                truncated,
+                cmdline: format!("{:?}", cmd),
+            };
+            self.fatal_proc_rec("rmake recipe failed to complete", &res);
+        }
+    }
+}
diff --git a/src/tools/compiletest/src/runtest/rustdoc.rs b/src/tools/compiletest/src/runtest/rustdoc.rs
new file mode 100644
index 00000000000..6a31888527e
--- /dev/null
+++ b/src/tools/compiletest/src/runtest/rustdoc.rs
@@ -0,0 +1,34 @@
+use std::process::Command;
+
+use super::{remove_and_create_dir_all, TestCx};
+
+impl TestCx<'_> {
+    pub(super) fn run_rustdoc_test(&self) {
+        assert!(self.revision.is_none(), "revisions not relevant here");
+
+        let out_dir = self.output_base_dir();
+        remove_and_create_dir_all(&out_dir);
+
+        let proc_res = self.document(&out_dir, &self.testpaths);
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("rustdoc failed!", &proc_res);
+        }
+
+        if self.props.check_test_line_numbers_match {
+            self.check_rustdoc_test_option(proc_res);
+        } else {
+            let root = self.config.find_rust_src_root().unwrap();
+            let mut cmd = Command::new(&self.config.python);
+            cmd.arg(root.join("src/etc/htmldocck.py")).arg(&out_dir).arg(&self.testpaths.file);
+            if self.config.bless {
+                cmd.arg("--bless");
+            }
+            let res = self.run_command_to_procres(&mut cmd);
+            if !res.status.success() {
+                self.fatal_proc_rec_with_ctx("htmldocck failed!", &res, |mut this| {
+                    this.compare_to_default_rustdoc(&out_dir)
+                });
+            }
+        }
+    }
+}
diff --git a/src/tools/compiletest/src/runtest/rustdoc_json.rs b/src/tools/compiletest/src/runtest/rustdoc_json.rs
new file mode 100644
index 00000000000..a39887ccd02
--- /dev/null
+++ b/src/tools/compiletest/src/runtest/rustdoc_json.rs
@@ -0,0 +1,48 @@
+use std::process::Command;
+
+use super::{remove_and_create_dir_all, TestCx};
+
+impl TestCx<'_> {
+    pub(super) fn run_rustdoc_json_test(&self) {
+        //FIXME: Add bless option.
+
+        assert!(self.revision.is_none(), "revisions not relevant here");
+
+        let out_dir = self.output_base_dir();
+        remove_and_create_dir_all(&out_dir);
+
+        let proc_res = self.document(&out_dir, &self.testpaths);
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("rustdoc failed!", &proc_res);
+        }
+
+        let root = self.config.find_rust_src_root().unwrap();
+        let mut json_out = out_dir.join(self.testpaths.file.file_stem().unwrap());
+        json_out.set_extension("json");
+        let res = self.run_command_to_procres(
+            Command::new(self.config.jsondocck_path.as_ref().unwrap())
+                .arg("--doc-dir")
+                .arg(root.join(&out_dir))
+                .arg("--template")
+                .arg(&self.testpaths.file),
+        );
+
+        if !res.status.success() {
+            self.fatal_proc_rec_with_ctx("jsondocck failed!", &res, |_| {
+                println!("Rustdoc Output:");
+                proc_res.print_info();
+            })
+        }
+
+        let mut json_out = out_dir.join(self.testpaths.file.file_stem().unwrap());
+        json_out.set_extension("json");
+
+        let res = self.run_command_to_procres(
+            Command::new(self.config.jsondoclint_path.as_ref().unwrap()).arg(&json_out),
+        );
+
+        if !res.status.success() {
+            self.fatal_proc_rec("jsondoclint failed!", &res);
+        }
+    }
+}
diff --git a/src/tools/compiletest/src/runtest/ui.rs b/src/tools/compiletest/src/runtest/ui.rs
new file mode 100644
index 00000000000..88a0ec3aa3b
--- /dev/null
+++ b/src/tools/compiletest/src/runtest/ui.rs
@@ -0,0 +1,233 @@
+use std::collections::HashSet;
+use std::fs::OpenOptions;
+use std::io::Write;
+
+use rustfix::{apply_suggestions, get_suggestions_from_json, Filter};
+use tracing::debug;
+
+use super::{
+    AllowUnused, Emit, ErrorKind, FailMode, LinkToAux, PassMode, TargetLocation, TestCx,
+    TestOutput, Truncated, WillExecute, UI_FIXED,
+};
+use crate::{errors, json};
+
+impl TestCx<'_> {
+    pub(super) fn run_ui_test(&self) {
+        if let Some(FailMode::Build) = self.props.fail_mode {
+            // Make sure a build-fail test cannot fail due to failing analysis (e.g. typeck).
+            let pm = Some(PassMode::Check);
+            let proc_res =
+                self.compile_test_general(WillExecute::No, Emit::Metadata, pm, Vec::new());
+            self.check_if_test_should_compile(&proc_res, pm);
+        }
+
+        let pm = self.pass_mode();
+        let should_run = self.should_run(pm);
+        let emit_metadata = self.should_emit_metadata(pm);
+        let proc_res = self.compile_test(should_run, emit_metadata);
+        self.check_if_test_should_compile(&proc_res, pm);
+        if matches!(proc_res.truncated, Truncated::Yes)
+            && !self.props.dont_check_compiler_stdout
+            && !self.props.dont_check_compiler_stderr
+        {
+            self.fatal_proc_rec(
+                "compiler output got truncated, cannot compare with reference file",
+                &proc_res,
+            );
+        }
+
+        // if the user specified a format in the ui test
+        // print the output to the stderr file, otherwise extract
+        // the rendered error messages from json and print them
+        let explicit = self.props.compile_flags.iter().any(|s| s.contains("--error-format"));
+
+        let expected_fixed = self.load_expected_output(UI_FIXED);
+
+        self.check_and_prune_duplicate_outputs(&proc_res, &[], &[]);
+
+        let mut errors = self.load_compare_outputs(&proc_res, TestOutput::Compile, explicit);
+        let rustfix_input = json::rustfix_diagnostics_only(&proc_res.stderr);
+
+        if self.config.compare_mode.is_some() {
+            // don't test rustfix with nll right now
+        } else if self.config.rustfix_coverage {
+            // Find out which tests have `MachineApplicable` suggestions but are missing
+            // `run-rustfix` or `run-rustfix-only-machine-applicable` headers.
+            //
+            // This will return an empty `Vec` in case the executed test file has a
+            // `compile-flags: --error-format=xxxx` header with a value other than `json`.
+            let suggestions = get_suggestions_from_json(
+                &rustfix_input,
+                &HashSet::new(),
+                Filter::MachineApplicableOnly,
+            )
+            .unwrap_or_default();
+            if !suggestions.is_empty()
+                && !self.props.run_rustfix
+                && !self.props.rustfix_only_machine_applicable
+            {
+                let mut coverage_file_path = self.config.build_base.clone();
+                coverage_file_path.push("rustfix_missing_coverage.txt");
+                debug!("coverage_file_path: {}", coverage_file_path.display());
+
+                let mut file = OpenOptions::new()
+                    .create(true)
+                    .append(true)
+                    .open(coverage_file_path.as_path())
+                    .expect("could not create or open file");
+
+                if let Err(e) = writeln!(file, "{}", self.testpaths.file.display()) {
+                    panic!("couldn't write to {}: {e:?}", coverage_file_path.display());
+                }
+            }
+        } else if self.props.run_rustfix {
+            // Apply suggestions from rustc to the code itself
+            let unfixed_code = self.load_expected_output_from_path(&self.testpaths.file).unwrap();
+            let suggestions = get_suggestions_from_json(
+                &rustfix_input,
+                &HashSet::new(),
+                if self.props.rustfix_only_machine_applicable {
+                    Filter::MachineApplicableOnly
+                } else {
+                    Filter::Everything
+                },
+            )
+            .unwrap();
+            let fixed_code = apply_suggestions(&unfixed_code, &suggestions).unwrap_or_else(|e| {
+                panic!(
+                    "failed to apply suggestions for {:?} with rustfix: {}",
+                    self.testpaths.file, e
+                )
+            });
+
+            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` \
+                 file was found"
+            );
+        }
+
+        if errors > 0 {
+            println!("To update references, rerun the tests and pass the `--bless` flag");
+            let relative_path_to_file =
+                self.testpaths.relative_dir.join(self.testpaths.file.file_name().unwrap());
+            println!(
+                "To only update this specific test, also pass `--test-args {}`",
+                relative_path_to_file.display(),
+            );
+            self.fatal_proc_rec(
+                &format!("{} errors occurred comparing output.", errors),
+                &proc_res,
+            );
+        }
+
+        let expected_errors = errors::load_errors(&self.testpaths.file, self.revision);
+
+        if let WillExecute::Yes = should_run {
+            let proc_res = self.exec_compiled_test();
+            let run_output_errors = if self.props.check_run_results {
+                self.load_compare_outputs(&proc_res, TestOutput::Run, explicit)
+            } else {
+                0
+            };
+            if run_output_errors > 0 {
+                self.fatal_proc_rec(
+                    &format!("{} errors occurred comparing run output.", run_output_errors),
+                    &proc_res,
+                );
+            }
+            if self.should_run_successfully(pm) {
+                if !proc_res.status.success() {
+                    self.fatal_proc_rec("test run failed!", &proc_res);
+                }
+            } else if proc_res.status.success() {
+                self.fatal_proc_rec("test run succeeded!", &proc_res);
+            }
+
+            if !self.props.error_patterns.is_empty() || !self.props.regex_error_patterns.is_empty()
+            {
+                // "// error-pattern" comments
+                let output_to_check = self.get_output(&proc_res);
+                self.check_all_error_patterns(&output_to_check, &proc_res, pm);
+            }
+        }
+
+        debug!(
+            "run_ui_test: explicit={:?} config.compare_mode={:?} expected_errors={:?} \
+               proc_res.status={:?} props.error_patterns={:?}",
+            explicit,
+            self.config.compare_mode,
+            expected_errors,
+            proc_res.status,
+            self.props.error_patterns
+        );
+
+        let check_patterns = should_run == WillExecute::No
+            && (!self.props.error_patterns.is_empty()
+                || !self.props.regex_error_patterns.is_empty());
+        if !explicit && self.config.compare_mode.is_none() {
+            let check_annotations = !check_patterns || !expected_errors.is_empty();
+
+            if check_annotations {
+                // "//~ERROR comments"
+                self.check_expected_errors(expected_errors, &proc_res);
+            }
+        } else if explicit && !expected_errors.is_empty() {
+            let msg = format!(
+                "line {}: cannot combine `--error-format` with {} annotations; use `error-pattern` instead",
+                expected_errors[0].line_num,
+                expected_errors[0].kind.unwrap_or(ErrorKind::Error),
+            );
+            self.fatal(&msg);
+        }
+        if check_patterns {
+            // "// error-pattern" comments
+            let output_to_check = self.get_output(&proc_res);
+            self.check_all_error_patterns(&output_to_check, &proc_res, pm);
+        }
+
+        if self.props.run_rustfix && self.config.compare_mode.is_none() {
+            // And finally, compile the fixed code and make sure it both
+            // succeeds and has no diagnostics.
+            let mut rustc = self.make_compile_args(
+                &self.expected_output_path(UI_FIXED),
+                TargetLocation::ThisFile(self.make_exe_name()),
+                emit_metadata,
+                AllowUnused::No,
+                LinkToAux::Yes,
+                Vec::new(),
+            );
+
+            // If a test is revisioned, it's fixed source file can be named "a.foo.fixed", which,
+            // well, "a.foo" isn't a valid crate name. So we explicitly mangle the test name
+            // (including the revision) here to avoid the test writer having to manually specify a
+            // `#![crate_name = "..."]` as a workaround. This is okay since we're only checking if
+            // the fixed code is compilable.
+            if self.revision.is_some() {
+                let crate_name =
+                    self.testpaths.file.file_stem().expect("test must have a file stem");
+                // crate name must be alphanumeric or `_`.
+                let crate_name =
+                    crate_name.to_str().expect("crate name implies file name must be valid UTF-8");
+                // replace `a.foo` -> `a__foo` for crate name purposes.
+                // replace `revision-name-with-dashes` -> `revision_name_with_underscore`
+                let crate_name = crate_name.replace('.', "__");
+                let crate_name = crate_name.replace('-', "_");
+                rustc.arg("--crate-name");
+                rustc.arg(crate_name);
+            }
+
+            let res = self.compose_and_run_compiler(rustc, None, self.testpaths);
+            if !res.status.success() {
+                self.fatal_proc_rec("failed to compile fixed code", &res);
+            }
+            if !res.stderr.is_empty()
+                && !self.props.rustfix_only_machine_applicable
+                && !json::rustfix_diagnostics_only(&res.stderr).is_empty()
+            {
+                self.fatal_proc_rec("fixed code is still producing diagnostics", &res);
+            }
+        }
+    }
+}
diff --git a/src/tools/compiletest/src/runtest/valgrind.rs b/src/tools/compiletest/src/runtest/valgrind.rs
new file mode 100644
index 00000000000..8d72c4be9ff
--- /dev/null
+++ b/src/tools/compiletest/src/runtest/valgrind.rs
@@ -0,0 +1,34 @@
+use super::{Emit, TestCx, WillExecute};
+
+impl TestCx<'_> {
+    pub(super) fn run_valgrind_test(&self) {
+        assert!(self.revision.is_none(), "revisions not relevant here");
+
+        // FIXME(jieyouxu): does this really make any sense? If a valgrind test isn't testing
+        // valgrind, what is it even testing?
+        if self.config.valgrind_path.is_none() {
+            assert!(!self.config.force_valgrind);
+            return self.run_rpass_test();
+        }
+
+        let should_run = self.run_if_enabled();
+        let mut proc_res = self.compile_test(should_run, Emit::None);
+
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("compilation failed!", &proc_res);
+        }
+
+        if let WillExecute::Disabled = should_run {
+            return;
+        }
+
+        let mut new_config = self.config.clone();
+        new_config.runner = new_config.valgrind_path.clone();
+        let new_cx = TestCx { config: &new_config, ..*self };
+        proc_res = new_cx.exec_compiled_test();
+
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("test run failed!", &proc_res);
+        }
+    }
+}
diff --git a/src/tools/miri/tests/fail/type-too-large.stderr b/src/tools/miri/tests/fail/type-too-large.stderr
index 15ad8f1764d..cd27b246389 100644
--- a/src/tools/miri/tests/fail/type-too-large.stderr
+++ b/src/tools/miri/tests/fail/type-too-large.stderr
@@ -1,8 +1,8 @@
-error: post-monomorphization error: values of the type `[u8; 2305843011361177600]` are too big for the current architecture
+error: post-monomorphization error: values of the type `[u8; 2305843011361177600]` are too big for the target architecture
   --> tests/fail/type-too-large.rs:LL:CC
    |
 LL |     _fat = [0; (1u64 << 61) as usize + (1u64 << 31) as usize];
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ values of the type `[u8; 2305843011361177600]` are too big for the current architecture
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ values of the type `[u8; 2305843011361177600]` are too big for the target architecture
    |
    = note: BACKTRACE:
    = note: inside `main` at tests/fail/type-too-large.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/uninit/padding-enum.rs b/src/tools/miri/tests/fail/uninit/padding-enum.rs
index a9628799b7d..e1a16bea23c 100644
--- a/src/tools/miri/tests/fail/uninit/padding-enum.rs
+++ b/src/tools/miri/tests/fail/uninit/padding-enum.rs
@@ -17,10 +17,11 @@ fn main() {
         assert!(matches!(*p.as_ptr(), E::None));
 
         // Turns out the discriminant is (currently) stored
-        // in the 2nd pointer, so the first half is padding.
+        // in the 1st pointer, so the second half is padding.
         let c = &p as *const _ as *const u8;
+        let padding_offset = mem::size_of::<&'static ()>();
         // Read a padding byte.
-        let _val = *c.add(0);
+        let _val = *c.add(padding_offset);
         //~^ERROR: uninitialized
     }
 }
diff --git a/src/tools/miri/tests/fail/uninit/padding-enum.stderr b/src/tools/miri/tests/fail/uninit/padding-enum.stderr
index 66d3092c9ba..765e7cc4e63 100644
--- a/src/tools/miri/tests/fail/uninit/padding-enum.stderr
+++ b/src/tools/miri/tests/fail/uninit/padding-enum.stderr
@@ -1,8 +1,8 @@
 error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
   --> tests/fail/uninit/padding-enum.rs:LL:CC
    |
-LL |         let _val = *c.add(0);
-   |                    ^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
+LL |         let _val = *c.add(padding_offset);
+   |                    ^^^^^^^^^^^^^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs b/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs
index e84ffee367f..255a93226a9 100644
--- a/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs
+++ b/src/tools/miri/tests/pass-dep/concurrency/linux-futex.rs
@@ -1,6 +1,9 @@
 //@only-target: linux
 //@compile-flags: -Zmiri-disable-isolation
 
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
 use std::mem::MaybeUninit;
 use std::ptr::{self, addr_of};
 use std::sync::atomic::AtomicI32;
diff --git a/src/tools/miri/tests/pass-dep/concurrency/tls_pthread_drop_order.rs b/src/tools/miri/tests/pass-dep/concurrency/tls_pthread_drop_order.rs
index 87c8a2e1063..2dc09709b8e 100644
--- a/src/tools/miri/tests/pass-dep/concurrency/tls_pthread_drop_order.rs
+++ b/src/tools/miri/tests/pass-dep/concurrency/tls_pthread_drop_order.rs
@@ -5,6 +5,9 @@
 //! the fallback path in `guard::key::enable`, which uses a *single* pthread_key
 //! to manage a thread-local list of dtors to call.
 
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
 use std::mem;
 use std::ptr;
 
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs b/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs
index 1e3d486233a..1d084194658 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-eventfd.rs
@@ -2,6 +2,9 @@
 // test_race depends on a deterministic schedule.
 //@compile-flags: -Zmiri-preemption-rate=0
 
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
 use std::thread;
 
 fn main() {
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs b/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs
index c6e8355c3f5..76f883e5d8d 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs
@@ -72,6 +72,8 @@ fn test_pipe_threaded() {
     thread2.join().unwrap();
 }
 
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#[allow(static_mut_refs)]
 fn test_race() {
     static mut VAL: u8 = 0;
     let mut fds = [-1, -1];
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs b/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs
index c3d6af5a1ef..64819e57679 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-socketpair.rs
@@ -1,6 +1,10 @@
 //@ignore-target: windows # No libc socketpair on Windows
 // test_race depends on a deterministic schedule.
 //@compile-flags: -Zmiri-preemption-rate=0
+
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
 use std::thread;
 fn main() {
     test_socketpair();
diff --git a/src/tools/miri/tests/pass/atomic.rs b/src/tools/miri/tests/pass/atomic.rs
index dfdc9b42f81..c03023ee693 100644
--- a/src/tools/miri/tests/pass/atomic.rs
+++ b/src/tools/miri/tests/pass/atomic.rs
@@ -1,7 +1,11 @@
 //@revisions: stack tree
 //@[tree]compile-flags: -Zmiri-tree-borrows
 //@compile-flags: -Zmiri-strict-provenance
+
 #![feature(strict_provenance, strict_provenance_atomic_ptr)]
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
 use std::sync::atomic::{
     compiler_fence, fence, AtomicBool, AtomicIsize, AtomicPtr, AtomicU64, Ordering::*,
 };
diff --git a/src/tools/miri/tests/pass/drop_on_array_elements.rs b/src/tools/miri/tests/pass/drop_on_array_elements.rs
index ae1ef036267..4bf241fee2b 100644
--- a/src/tools/miri/tests/pass/drop_on_array_elements.rs
+++ b/src/tools/miri/tests/pass/drop_on_array_elements.rs
@@ -1,3 +1,5 @@
+#![allow(static_mut_refs)]
+
 struct Bar(u16); // ZSTs are tested separately
 
 static mut DROP_COUNT: usize = 0;
diff --git a/src/tools/miri/tests/pass/drop_on_fat_ptr_array_elements.rs b/src/tools/miri/tests/pass/drop_on_fat_ptr_array_elements.rs
index 40025cd07f7..04723af94c3 100644
--- a/src/tools/miri/tests/pass/drop_on_fat_ptr_array_elements.rs
+++ b/src/tools/miri/tests/pass/drop_on_fat_ptr_array_elements.rs
@@ -1,3 +1,5 @@
+#![allow(static_mut_refs)]
+
 trait Foo {}
 
 struct Bar;
diff --git a/src/tools/miri/tests/pass/drop_on_zst_array_elements.rs b/src/tools/miri/tests/pass/drop_on_zst_array_elements.rs
index babe098e4e6..71398724f2c 100644
--- a/src/tools/miri/tests/pass/drop_on_zst_array_elements.rs
+++ b/src/tools/miri/tests/pass/drop_on_zst_array_elements.rs
@@ -1,3 +1,5 @@
+#![allow(static_mut_refs)]
+
 struct Bar;
 
 static mut DROP_COUNT: usize = 0;
diff --git a/src/tools/miri/tests/pass/drop_through_owned_slice.rs b/src/tools/miri/tests/pass/drop_through_owned_slice.rs
index 8cdeb57d02f..2d1d876e6f2 100644
--- a/src/tools/miri/tests/pass/drop_through_owned_slice.rs
+++ b/src/tools/miri/tests/pass/drop_through_owned_slice.rs
@@ -1,3 +1,5 @@
+#![allow(static_mut_refs)]
+
 struct Bar;
 
 static mut DROP_COUNT: usize = 0;
diff --git a/src/tools/miri/tests/pass/static_memory_modification.rs b/src/tools/miri/tests/pass/static_memory_modification.rs
index 84a524b1ed1..1900250bf4f 100644
--- a/src/tools/miri/tests/pass/static_memory_modification.rs
+++ b/src/tools/miri/tests/pass/static_memory_modification.rs
@@ -1,3 +1,6 @@
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
 use std::sync::atomic::{AtomicUsize, Ordering};
 
 static mut X: usize = 5;
diff --git a/src/tools/miri/tests/pass/static_mut.rs b/src/tools/miri/tests/pass/static_mut.rs
index 4488b5a09d5..f88c7a16e6d 100644
--- a/src/tools/miri/tests/pass/static_mut.rs
+++ b/src/tools/miri/tests/pass/static_mut.rs
@@ -1,3 +1,6 @@
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
 use std::ptr::addr_of;
 
 static mut FOO: i32 = 42;
diff --git a/src/tools/miri/tests/pass/tls/tls_static.rs b/src/tools/miri/tests/pass/tls/tls_static.rs
index 8d0e5089d40..cc4eaca72ab 100644
--- a/src/tools/miri/tests/pass/tls/tls_static.rs
+++ b/src/tools/miri/tests/pass/tls/tls_static.rs
@@ -7,6 +7,8 @@
 //! dereferencing the pointer on `t2` resolves to `t1`'s thread-local. In this
 //! test, we also check that thread-locals act as per-thread statics.
 
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
 #![feature(thread_local)]
 
 use std::ptr::addr_of_mut;
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
index 2f4e764f4ce..26ab02558a1 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
@@ -377,6 +377,7 @@ pub enum FnAbi {
     AvrNonBlockingInterrupt,
     C,
     CCmseNonsecureCall,
+    CCmseNonsecureEntry,
     CDecl,
     CDeclUnwind,
     CUnwind,
@@ -434,6 +435,7 @@ impl FnAbi {
             s if *s == sym::avr_dash_interrupt => FnAbi::AvrInterrupt,
             s if *s == sym::avr_dash_non_dash_blocking_dash_interrupt => FnAbi::AvrNonBlockingInterrupt,
             s if *s == sym::C_dash_cmse_dash_nonsecure_dash_call => FnAbi::CCmseNonsecureCall,
+            s if *s == sym::C_dash_cmse_dash_nonsecure_dash_entry => FnAbi::CCmseNonsecureEntry,
             s if *s == sym::C_dash_unwind => FnAbi::CUnwind,
             s if *s == sym::C => FnAbi::C,
             s if *s == sym::cdecl_dash_unwind => FnAbi::CDeclUnwind,
@@ -477,6 +479,7 @@ impl FnAbi {
             FnAbi::AvrNonBlockingInterrupt => "avr-non-blocking-interrupt",
             FnAbi::C => "C",
             FnAbi::CCmseNonsecureCall => "C-cmse-nonsecure-call",
+            FnAbi::CCmseNonsecureEntry => "C-cmse-nonsecure-entry",
             FnAbi::CDecl => "C-decl",
             FnAbi::CDeclUnwind => "cdecl-unwind",
             FnAbi::CUnwind => "C-unwind",
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs
index 1a06e0a3a0e..b0e417e6b33 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_abi.rs
@@ -32,6 +32,7 @@ const SUPPORTED_CALLING_CONVENTIONS: &[&str] = &[
     "riscv-interrupt-m",
     "riscv-interrupt-s",
     "C-cmse-nonsecure-call",
+    "C-cmse-nonsecure-entry",
     "wasm",
     "system",
     "system-unwind",
diff --git a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
index 7eb8e4a5e2e..c066f504891 100644
--- a/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
+++ b/src/tools/rust-analyzer/crates/intern/src/symbol/symbols.rs
@@ -94,6 +94,7 @@ define_symbols! {
     avr_dash_interrupt = "avr-interrupt",
     avr_dash_non_dash_blocking_dash_interrupt = "avr-non-blocking-interrupt",
     C_dash_cmse_dash_nonsecure_dash_call = "C-cmse-nonsecure-call",
+    C_dash_cmse_dash_nonsecure_dash_entry = "C-cmse-nonsecure-entry",
     C_dash_unwind = "C-unwind",
     cdecl_dash_unwind = "cdecl-unwind",
     fastcall_dash_unwind = "fastcall-unwind",
diff --git a/src/tools/rustfmt/.github/workflows/check_diff.yml b/src/tools/rustfmt/.github/workflows/check_diff.yml
index 2f2beb76915..99daa0addf5 100644
--- a/src/tools/rustfmt/.github/workflows/check_diff.yml
+++ b/src/tools/rustfmt/.github/workflows/check_diff.yml
@@ -21,7 +21,7 @@ jobs:
 
     steps:
     - name: checkout
-      uses: actions/checkout@v3
+      uses: actions/checkout@v4
 
     - name: install rustup
       run: |
diff --git a/src/tools/rustfmt/.github/workflows/integration.yml b/src/tools/rustfmt/.github/workflows/integration.yml
index f0dd0cf73bb..bda374562bc 100644
--- a/src/tools/rustfmt/.github/workflows/integration.yml
+++ b/src/tools/rustfmt/.github/workflows/integration.yml
@@ -64,7 +64,7 @@ jobs:
 
     steps:
     - name: checkout
-      uses: actions/checkout@v3
+      uses: actions/checkout@v4
 
       # Run build
     - name: install rustup
diff --git a/src/tools/rustfmt/.github/workflows/linux.yml b/src/tools/rustfmt/.github/workflows/linux.yml
index bce9b0c8d5a..3a5e6ab5404 100644
--- a/src/tools/rustfmt/.github/workflows/linux.yml
+++ b/src/tools/rustfmt/.github/workflows/linux.yml
@@ -26,7 +26,7 @@ jobs:
 
     steps:
     - name: checkout
-      uses: actions/checkout@v3
+      uses: actions/checkout@v4
 
       # Run build
     - name: install rustup
diff --git a/src/tools/rustfmt/.github/workflows/mac.yml b/src/tools/rustfmt/.github/workflows/mac.yml
index 89a980c42c5..2c766d0573b 100644
--- a/src/tools/rustfmt/.github/workflows/mac.yml
+++ b/src/tools/rustfmt/.github/workflows/mac.yml
@@ -8,7 +8,6 @@ on:
 jobs:
   test:
     # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/virtual-environments-for-github-hosted-runners#supported-runners-and-hardware-resources
-    # macOS Catalina 10.15
     runs-on: macos-latest
     name: (${{ matrix.target }}, ${{ matrix.cfg_release_channel }})
     env:
@@ -23,7 +22,7 @@ jobs:
 
     steps:
     - name: checkout
-      uses: actions/checkout@v3
+      uses: actions/checkout@v4
 
       # Run build
     - name: install rustup
diff --git a/src/tools/rustfmt/.github/workflows/rustdoc_check.yml b/src/tools/rustfmt/.github/workflows/rustdoc_check.yml
index cd0c3218971..6e8a7ecd7ad 100644
--- a/src/tools/rustfmt/.github/workflows/rustdoc_check.yml
+++ b/src/tools/rustfmt/.github/workflows/rustdoc_check.yml
@@ -11,7 +11,7 @@ jobs:
     name: rustdoc check
     steps:
     - name: checkout
-      uses: actions/checkout@v3
+      uses: actions/checkout@v4
 
     - name: install rustup
       run: |
diff --git a/src/tools/rustfmt/.github/workflows/upload-assets.yml b/src/tools/rustfmt/.github/workflows/upload-assets.yml
index 7dfaa4b9204..7a639b469e8 100644
--- a/src/tools/rustfmt/.github/workflows/upload-assets.yml
+++ b/src/tools/rustfmt/.github/workflows/upload-assets.yml
@@ -31,7 +31,7 @@ jobs:
             target: x86_64-pc-windows-msvc
     runs-on: ${{ matrix.os }}
     steps:
-      - uses: actions/checkout@v3
+      - uses: actions/checkout@v4
 
         # Run build
       - name: install rustup
diff --git a/src/tools/rustfmt/.github/workflows/windows.yml b/src/tools/rustfmt/.github/workflows/windows.yml
index ec37c714b08..728f1b90b13 100644
--- a/src/tools/rustfmt/.github/workflows/windows.yml
+++ b/src/tools/rustfmt/.github/workflows/windows.yml
@@ -33,7 +33,7 @@ jobs:
     - name: disable git eol translation
       run: git config --global core.autocrlf false
     - name: checkout
-      uses: actions/checkout@v3
+      uses: actions/checkout@v4
 
       # Run build
     - name: Install Rustup using win.rustup.rs
diff --git a/src/tools/rustfmt/CHANGELOG.md b/src/tools/rustfmt/CHANGELOG.md
index 89e90fb17dd..8af60f60dc6 100644
--- a/src/tools/rustfmt/CHANGELOG.md
+++ b/src/tools/rustfmt/CHANGELOG.md
@@ -1,6 +1,66 @@
 # Changelog
 
-## [Unreleased]
+## [1.8.0] 2024-09-20
+
+### Fixed
+- Fix issue where rustfmt would crash on Windows when using the `ignore` option [#6178](https://github.com/rust-lang/rustfmt/issues/6178)
+
+### Changed
+- `rustfmt --version` now prints a commit hash that is 10 characters long [#6258](https://github.com/rust-lang/rustfmt/pull/6258)
+- `rustfmt --version` will no longer print empty git information when git information isn't available at build time.
+  For example, git information is not available when building rustfmt from a source tarball [#6266](https://github.com/rust-lang/rustfmt/pull/6266)
+- `version` has been soft deprecated and replaced by `style_edition`.
+  `style_edition=2024` is equivalent to `version=Two` and `style_edition={2015|2018|2021}`
+  are equivalent to `version=One` [#6247](https://github.com/rust-lang/rustfmt/pull/6247)
+- When `style_edition=2024` is configured `overflow_delimited_expr` will default to `true` [#6260](https://github.com/rust-lang/rustfmt/pull/6260).
+  ```rust
+  // with style_edition=2015
+  do_thing(
+      x,
+      Bar {
+          x: value,
+          y: value2,
+      },
+  );
+
+  // with style_edition=2024
+  do_thing(x, Bar {
+      x: value,
+      y: value2,
+  });
+  ```
+- When `style_edition=2024` is configured rustfmt will apply the [style guide's version sorting algorithm]
+  when sorting imports [#6284](https://github.com/rust-lang/rustfmt/pull/6284)
+  ```rust
+  // with style_edition=2015
+  use std::num::{NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8};
+
+  // with style_edition=2024
+  use std::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64};
+  ```
+  [style guide's version sorting algorithm]: https://doc.rust-lang.org/nightly/style-guide/#sorting
+- When parsing rustfmt configurations fails, rustfmt will now include the path to the toml file in the erorr message [#6302](https://github.com/rust-lang/rustfmt/issues/6302)
+
+### Added
+- rustfmt now formats trailing where clauses in type aliases [#5887](https://github.com/rust-lang/rustfmt/pull/5887)
+  ```rust
+  type Foo
+      = Bar
+  where
+      A: B,
+      C: D;
+  ```
+- Users can now configure which `style_edition` rustfmt uses when formatting their code as specified
+  in [RFC 3338](https://rust-lang.github.io/rfcs/3338-style-evolution.html). Users are encouraged to configure `style_edition`
+  in their `rustfmt.toml` files, but the value can also be specified via the cli with `--unstable-features --style-edition={style_edition}`.
+  When `style_edition` is not explicitly configured it will be inferred from the `edition` configuration.
+  When neither `style_edition` nor `edition` are configured `style_edition` defaults to `2015` [#6247](https://github.com/rust-lang/rustfmt/pull/6247)
+
+### Misc
+- Removed `tracing-attributes` dependency [#6208](https://github.com/rust-lang/rustfmt/pull/6208)
+- Reduced syn's features in the internal `config_proc_macro` crate [#6237](https://github.com/rust-lang/rustfmt/pull/6237)
+
+## [1.7.1] 2024-06-24
 
 ### Fixed
 
@@ -238,7 +298,7 @@
 
 ### Added
 
-- New configuration option (`skip_macro_invocations`)[https://rust-lang.github.io/rustfmt/?version=master&search=#skip_macro_invocations] [#5347](https://github.com/rust-lang/rustfmt/pull/5347) that can be used to globally define a single enumerated list of macro calls that rustfmt should skip formatting. rustfmt [currently also supports this via a custom tool attribute](https://github.com/rust-lang/rustfmt#tips), however, these cannot be used in all contexts because [custom inner attributes are unstable](https://github.com/rust-lang/rust/issues/54726)
+- New configuration option [`skip_macro_invocations`](https://rust-lang.github.io/rustfmt/?version=master&search=#skip_macro_invocations) [#5347](https://github.com/rust-lang/rustfmt/pull/5347) that can be used to globally define a single enumerated list of macro calls that rustfmt should skip formatting. rustfmt [currently also supports this via a custom tool attribute](https://github.com/rust-lang/rustfmt#tips), however, these cannot be used in all contexts because [custom inner attributes are unstable](https://github.com/rust-lang/rust/issues/54726)
 
 ### Misc
 
diff --git a/src/tools/rustfmt/Cargo.lock b/src/tools/rustfmt/Cargo.lock
index 2a1fffa50fe..e2ceb668ebd 100644
--- a/src/tools/rustfmt/Cargo.lock
+++ b/src/tools/rustfmt/Cargo.lock
@@ -499,7 +499,7 @@ dependencies = [
 
 [[package]]
 name = "rustfmt-nightly"
-version = "1.7.1"
+version = "1.8.0"
 dependencies = [
  "annotate-snippets",
  "anyhow",
@@ -710,22 +710,10 @@ checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
 dependencies = [
  "cfg-if",
  "pin-project-lite",
- "tracing-attributes",
  "tracing-core",
 ]
 
 [[package]]
-name = "tracing-attributes"
-version = "0.1.26"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
 name = "tracing-core"
 version = "0.1.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/tools/rustfmt/Cargo.toml b/src/tools/rustfmt/Cargo.toml
index a16620ed99b..e497b792342 100644
--- a/src/tools/rustfmt/Cargo.toml
+++ b/src/tools/rustfmt/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 
 name = "rustfmt-nightly"
-version = "1.7.1"
+version = "1.8.0"
 description = "Tool to find and fix Rust formatting issues"
 repository = "https://github.com/rust-lang/rustfmt"
 readme = "README.md"
@@ -50,7 +50,7 @@ serde_json = "1.0"
 term = "0.7"
 thiserror = "1.0.40"
 toml = "0.7.4"
-tracing = "0.1.37"
+tracing = { version = "0.1.37", default-features = false, features = ["std"] }
 tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
 unicode-segmentation = "1.9"
 unicode-width = "0.1"
diff --git a/src/tools/rustfmt/Configurations.md b/src/tools/rustfmt/Configurations.md
index f52c2573154..b1f54060392 100644
--- a/src/tools/rustfmt/Configurations.md
+++ b/src/tools/rustfmt/Configurations.md
@@ -534,7 +534,7 @@ Note that this option may be soft-deprecated in the future once the [ignore](#ig
 Specifies which edition is used by the parser.
 
 - **Default value**: `"2015"`
-- **Possible values**: `"2015"`, `"2018"`, `"2021"`
+- **Possible values**: `"2015"`, `"2018"`, `"2021"`, `"2024"`
 - **Stable**: Yes
 
 Rustfmt is able to pick up the edition used by reading the `Cargo.toml` file if executed
@@ -2692,6 +2692,17 @@ By default this option is set as a percentage of [`max_width`](#max_width) provi
 
 See also [`max_width`](#max_width) and [`use_small_heuristics`](#use_small_heuristics)
 
+## `style_edition`
+
+Controls the edition of the [Rust Style Guide] to use for formatting ([RFC 3338])
+
+- **Default value**: `"2015"`
+- **Possible values**: `"2015"`, `"2018"`, `"2021"`, `"2024"` (unstable variant)
+- **Stable**: No
+
+[Rust Style Guide]: https://doc.rust-lang.org/nightly/style-guide/
+[RFC 3338]: https://rust-lang.github.io/rfcs/3338-style-evolution.html
+
 ## `tab_spaces`
 
 Number of spaces per tab
@@ -3051,9 +3062,7 @@ fn main() {
 
 ## `version`
 
-Which version of the formatting rules to use. `Version::One` is backwards-compatible
-with Rustfmt 1.0. Other versions are only backwards compatible within a major
-version number.
+This option is deprecated and has been replaced by [`style_edition`](#style_edition)
 
 - **Default value**: `One`
 - **Possible values**: `One`, `Two`
diff --git a/src/tools/rustfmt/Contributing.md b/src/tools/rustfmt/Contributing.md
index 2f2ccfb175a..85754a8658a 100644
--- a/src/tools/rustfmt/Contributing.md
+++ b/src/tools/rustfmt/Contributing.md
@@ -109,17 +109,17 @@ If you want to test modified `cargo-fmt`, or run `rustfmt` on the whole project
 RUSTFMT="./target/debug/rustfmt" cargo run --bin cargo-fmt -- --manifest-path path/to/project/you/want2test/Cargo.toml
 ```
 
-### Version-gate formatting changes
+### Gate formatting changes
 
-A change that introduces a different code-formatting should be gated on the
-`version` configuration. This is to ensure the formatting of the current major
-release is preserved, while allowing fixes to be implemented for the next
-release.
+A change that introduces a different code-formatting must be gated on the
+`style_edition` configuration. This is to ensure rustfmt upholds its formatting
+stability guarantees and adheres to the Style Edition process set in [RFC 3338]
 
-This is done by conditionally guarding the change like so:
+This can be done by conditionally guarding the formatting change, e.g.:
 
 ```rust
-if config.version() == Version::One { // if the current major release is 1.x
+// if the current stable Style Edition is Edition 2024
+if config.style_edition() <= StyleEdition::Edition2024 {
     // current formatting
 } else {
     // new formatting
@@ -129,13 +129,14 @@ if config.version() == Version::One { // if the current major release is 1.x
 This allows the user to apply the next formatting explicitly via the
 configuration, while being stable by default.
 
-When the next major release is done, the code block of the previous formatting
-can be deleted, e.g., the first block in the example above when going from `1.x`
-to `2.x`.
+This can then be enhanced as needed if and when there are
+new Style Editions with differing formatting prescriptions.
 
 | Note: Only formatting changes with default options need to be gated. |
 | --- |
 
+[RFC 3338]: https://rust-lang.github.io/rfcs/3338-style-evolution.html
+
 ### A quick tour of Rustfmt
 
 Rustfmt is basically a pretty printer - that is, its mode of operation is to
diff --git a/src/tools/rustfmt/build.rs b/src/tools/rustfmt/build.rs
index 9a8bb77a8ed..696c713d726 100644
--- a/src/tools/rustfmt/build.rs
+++ b/src/tools/rustfmt/build.rs
@@ -25,7 +25,7 @@ fn main() {
 // (git not installed or if this is not a git repository) just return an empty string.
 fn commit_info() -> String {
     match (channel(), commit_hash(), commit_date()) {
-        (channel, Some(hash), Some(date)) => format!("{} ({} {})", channel, hash.trim_end(), date),
+        (channel, Some(hash), Some(date)) => format!("{} ({} {})", channel, hash, date),
         _ => String::new(),
     }
 }
@@ -39,17 +39,20 @@ fn channel() -> String {
 }
 
 fn commit_hash() -> Option<String> {
-    Command::new("git")
-        .args(["rev-parse", "--short", "HEAD"])
+    let output = Command::new("git")
+        .args(["rev-parse", "HEAD"])
         .output()
-        .ok()
-        .and_then(|r| String::from_utf8(r.stdout).ok())
+        .ok()?;
+    let mut stdout = output.status.success().then_some(output.stdout)?;
+    stdout.truncate(10);
+    String::from_utf8(stdout).ok()
 }
 
 fn commit_date() -> Option<String> {
-    Command::new("git")
+    let output = Command::new("git")
         .args(["log", "-1", "--date=short", "--pretty=format:%cd"])
         .output()
-        .ok()
-        .and_then(|r| String::from_utf8(r.stdout).ok())
+        .ok()?;
+    let stdout = output.status.success().then_some(output.stdout)?;
+    String::from_utf8(stdout).ok()
 }
diff --git a/src/tools/rustfmt/check_diff/Cargo.lock b/src/tools/rustfmt/check_diff/Cargo.lock
index 6716ccdf9a0..2abf5af2f98 100644
--- a/src/tools/rustfmt/check_diff/Cargo.lock
+++ b/src/tools/rustfmt/check_diff/Cargo.lock
@@ -3,6 +3,15 @@
 version = 3
 
 [[package]]
+name = "aho-corasick"
+version = "1.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
 name = "anstream"
 version = "0.6.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -52,10 +61,25 @@ dependencies = [
 ]
 
 [[package]]
+name = "bitflags"
+version = "2.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
 name = "check_diff"
 version = "0.1.0"
 dependencies = [
  "clap",
+ "tempfile",
+ "tracing",
+ "tracing-subscriber",
 ]
 
 [[package]]
@@ -105,6 +129,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422"
 
 [[package]]
+name = "errno"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
+dependencies = [
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "fastrand"
+version = "2.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a"
+
+[[package]]
 name = "heck"
 version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -117,6 +157,73 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800"
 
 [[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
+name = "libc"
+version = "0.2.155"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.4.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
+
+[[package]]
+name = "log"
+version = "0.4.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
+
+[[package]]
+name = "matchers"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
+dependencies = [
+ "regex-automata 0.1.10",
+]
+
+[[package]]
+name = "memchr"
+version = "2.7.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
+
+[[package]]
+name = "nu-ansi-term"
+version = "0.46.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
+dependencies = [
+ "overload",
+ "winapi",
+]
+
+[[package]]
+name = "once_cell"
+version = "1.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
+
+[[package]]
+name = "overload"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
+
+[[package]]
 name = "proc-macro2"
 version = "1.0.83"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -135,6 +242,78 @@ dependencies = [
 ]
 
 [[package]]
+name = "regex"
+version = "1.10.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata 0.4.7",
+ "regex-syntax 0.8.4",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
+dependencies = [
+ "regex-syntax 0.6.29",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax 0.8.4",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
+
+[[package]]
+name = "regex-syntax"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
+
+[[package]]
+name = "rustix"
+version = "0.38.34"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f"
+dependencies = [
+ "bitflags",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys",
+]
+
+[[package]]
+name = "sharded-slab"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
+dependencies = [
+ "lazy_static",
+]
+
+[[package]]
+name = "smallvec"
+version = "1.13.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
+
+[[package]]
 name = "strsim"
 version = "0.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -152,6 +331,89 @@ dependencies = [
 ]
 
 [[package]]
+name = "tempfile"
+version = "3.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1"
+dependencies = [
+ "cfg-if",
+ "fastrand",
+ "rustix",
+ "windows-sys",
+]
+
+[[package]]
+name = "thread_local"
+version = "1.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+]
+
+[[package]]
+name = "tracing"
+version = "0.1.40"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
+dependencies = [
+ "pin-project-lite",
+ "tracing-attributes",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-attributes"
+version = "0.1.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "tracing-core"
+version = "0.1.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
+dependencies = [
+ "once_cell",
+ "valuable",
+]
+
+[[package]]
+name = "tracing-log"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
+dependencies = [
+ "log",
+ "once_cell",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-subscriber"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
+dependencies = [
+ "matchers",
+ "nu-ansi-term",
+ "once_cell",
+ "regex",
+ "sharded-slab",
+ "smallvec",
+ "thread_local",
+ "tracing",
+ "tracing-core",
+ "tracing-log",
+]
+
+[[package]]
 name = "unicode-ident"
 version = "1.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -164,6 +426,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
 
 [[package]]
+name = "valuable"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
 name = "windows-sys"
 version = "0.52.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/tools/rustfmt/check_diff/Cargo.toml b/src/tools/rustfmt/check_diff/Cargo.toml
index a1ed154481a..4ae8a5f1f3a 100644
--- a/src/tools/rustfmt/check_diff/Cargo.toml
+++ b/src/tools/rustfmt/check_diff/Cargo.toml
@@ -7,3 +7,7 @@ edition = "2021"
 
 [dependencies]
 clap = { version = "4.4.2", features = ["derive"] }
+tracing = "0.1.37"
+tracing-subscriber = { version = "0.3.17", features = ["env-filter"] }
+[dev-dependencies]
+tempfile = "3"
diff --git a/src/tools/rustfmt/check_diff/src/lib.rs b/src/tools/rustfmt/check_diff/src/lib.rs
new file mode 100644
index 00000000000..b83d67c8b6e
--- /dev/null
+++ b/src/tools/rustfmt/check_diff/src/lib.rs
@@ -0,0 +1,58 @@
+use std::env;
+use std::io;
+use std::path::Path;
+use std::process::Command;
+use tracing::info;
+
+pub enum GitError {
+    FailedClone { stdout: Vec<u8>, stderr: Vec<u8> },
+    IO(std::io::Error),
+}
+
+impl From<io::Error> for GitError {
+    fn from(error: io::Error) -> Self {
+        GitError::IO(error)
+    }
+}
+
+/// Clone a git repository
+///
+/// Parameters:
+/// url: git clone url
+/// dest: directory where the repo should be cloned
+pub fn clone_git_repo(url: &str, dest: &Path) -> Result<(), GitError> {
+    let git_cmd = Command::new("git")
+        .env("GIT_TERMINAL_PROMPT", "0")
+        .args([
+            "clone",
+            "--quiet",
+            url,
+            "--depth",
+            "1",
+            dest.to_str().unwrap(),
+        ])
+        .output()?;
+
+    // if the git command does not return successfully,
+    // any command on the repo will fail. So fail fast.
+    if !git_cmd.status.success() {
+        let error = GitError::FailedClone {
+            stdout: git_cmd.stdout,
+            stderr: git_cmd.stderr,
+        };
+        return Err(error);
+    }
+
+    info!("Successfully clone repository.");
+    return Ok(());
+}
+
+pub fn change_directory_to_path(dest: &Path) -> io::Result<()> {
+    let dest_path = Path::new(&dest);
+    env::set_current_dir(&dest_path)?;
+    info!(
+        "Current directory: {}",
+        env::current_dir().unwrap().display()
+    );
+    return Ok(());
+}
diff --git a/src/tools/rustfmt/check_diff/src/main.rs b/src/tools/rustfmt/check_diff/src/main.rs
index 6d07c1b0df6..01c5926c490 100644
--- a/src/tools/rustfmt/check_diff/src/main.rs
+++ b/src/tools/rustfmt/check_diff/src/main.rs
@@ -1,4 +1,5 @@
 use clap::Parser;
+
 /// Inputs for the check_diff script
 #[derive(Parser)]
 struct CliInputs {
@@ -16,10 +17,5 @@ struct CliInputs {
 }
 
 fn main() {
-    let args = CliInputs::parse();
-    println!(
-        "remote_repo_url: {:?}, feature_branch: {:?},
-        optional_commit_hash: {:?}, optional_rustfmt_config: {:?}",
-        args.remote_repo_url, args.feature_branch, args.commit_hash, args.rustfmt_config
-    );
+    let _args = CliInputs::parse();
 }
diff --git a/src/tools/rustfmt/check_diff/tests/bash_commands.rs b/src/tools/rustfmt/check_diff/tests/bash_commands.rs
new file mode 100644
index 00000000000..38ee34ef503
--- /dev/null
+++ b/src/tools/rustfmt/check_diff/tests/bash_commands.rs
@@ -0,0 +1,12 @@
+use check_diff::change_directory_to_path;
+use std::env;
+use tempfile::Builder;
+
+#[test]
+fn cd_test() {
+    // Creates an empty directory in the current working directory
+    let dir = Builder::new().tempdir_in("").unwrap();
+    let dest_path = dir.path();
+    change_directory_to_path(dest_path).unwrap();
+    assert_eq!(env::current_dir().unwrap(), dest_path);
+}
diff --git a/src/tools/rustfmt/check_diff/tests/git.rs b/src/tools/rustfmt/check_diff/tests/git.rs
new file mode 100644
index 00000000000..677c3840e1e
--- /dev/null
+++ b/src/tools/rustfmt/check_diff/tests/git.rs
@@ -0,0 +1,16 @@
+use check_diff::clone_git_repo;
+
+use tempfile::Builder;
+
+#[test]
+fn clone_repo_test() {
+    // Creates an empty directory in the current working directory
+    let dir = Builder::new().tempdir_in("").unwrap();
+    let sample_repo = "https://github.com/rust-lang/rustfmt.git";
+    let dest_path = dir.path();
+    let result = clone_git_repo(sample_repo, dest_path);
+    assert!(result.is_ok());
+    // check whether a .git folder exists after cloning the repo
+    let git_repo = dest_path.join(".git");
+    assert!(git_repo.exists());
+}
diff --git a/src/tools/rustfmt/ci/build_and_test.bat b/src/tools/rustfmt/ci/build_and_test.bat
index 16608a4aaa7..b6b5ca21364 100755
--- a/src/tools/rustfmt/ci/build_and_test.bat
+++ b/src/tools/rustfmt/ci/build_and_test.bat
@@ -13,7 +13,13 @@ if "%CFG_RELEASE_CHANNEL%"=="nightly" (
 )
 cargo test || exit /b 1
 
-:: Build and test other crates
+:: Build and test config_proc_macro
 cd config_proc_macro || exit /b 1
 cargo build --locked || exit /b 1
 cargo test || exit /b 1
+
+:: Build and test check_diff
+cd ..
+cd check_diff || exit /b 1
+cargo build --locked || exit /b 1
+cargo test || exit /b 1
diff --git a/src/tools/rustfmt/ci/build_and_test.sh b/src/tools/rustfmt/ci/build_and_test.sh
index 207da362fd6..dd9a0c0fd9b 100755
--- a/src/tools/rustfmt/ci/build_and_test.sh
+++ b/src/tools/rustfmt/ci/build_and_test.sh
@@ -17,7 +17,13 @@ else
 fi
 cargo test
 
-# Build and test other crates
+# Build and test config_proc_macro
 cd config_proc_macro
 cargo build --locked
 cargo test
+
+# Build and test check_diff
+cd ..
+cd check_diff
+cargo build --locked
+cargo test
diff --git a/src/tools/rustfmt/config_proc_macro/Cargo.toml b/src/tools/rustfmt/config_proc_macro/Cargo.toml
index eda8a7fce81..ec0db49d71c 100644
--- a/src/tools/rustfmt/config_proc_macro/Cargo.toml
+++ b/src/tools/rustfmt/config_proc_macro/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "rustfmt-config_proc_macro"
 version = "0.3.0"
-edition = "2018"
+edition = "2021"
 description = "A collection of procedural macros for rustfmt"
 license = "Apache-2.0 OR MIT"
 categories = ["development-tools::procedural-macro-helpers"]
@@ -13,7 +13,7 @@ proc-macro = true
 [dependencies]
 proc-macro2 = "1.0"
 quote = "1.0"
-syn = { version = "2.0", features = ["full", "visit"] }
+syn = { version = "2.0", default-features = false, features = ["full", "parsing", "proc-macro", "printing"] }
 
 [dev-dependencies]
 serde = { version = "1.0.160", features = ["derive"] }
diff --git a/src/tools/rustfmt/config_proc_macro/src/utils.rs b/src/tools/rustfmt/config_proc_macro/src/utils.rs
index f5cba87b07b..1f5b5cdb604 100644
--- a/src/tools/rustfmt/config_proc_macro/src/utils.rs
+++ b/src/tools/rustfmt/config_proc_macro/src/utils.rs
@@ -1,5 +1,5 @@
 use proc_macro2::TokenStream;
-use quote::{quote, ToTokens};
+use quote::{ToTokens, quote};
 
 pub fn fold_quote<F, I, T>(input: impl Iterator<Item = I>, f: F) -> TokenStream
 where
diff --git a/src/tools/rustfmt/rust-toolchain b/src/tools/rustfmt/rust-toolchain
index 25e3961d32a..80723123274 100644
--- a/src/tools/rustfmt/rust-toolchain
+++ b/src/tools/rustfmt/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2024-06-13"
+channel = "nightly-2024-09-10"
 components = ["llvm-tools", "rustc-dev"]
diff --git a/src/tools/rustfmt/rustfmt.toml b/src/tools/rustfmt/rustfmt.toml
index eccd5f9bd19..86447eac2e6 100644
--- a/src/tools/rustfmt/rustfmt.toml
+++ b/src/tools/rustfmt/rustfmt.toml
@@ -1,3 +1,4 @@
 error_on_line_overflow = true
 error_on_unformatted = true
-version = "Two"
+style_edition = "2024"
+overflow_delimited_expr = false
diff --git a/src/tools/rustfmt/src/attr.rs b/src/tools/rustfmt/src/attr.rs
index a2c0a28d66e..5c2068b6a22 100644
--- a/src/tools/rustfmt/src/attr.rs
+++ b/src/tools/rustfmt/src/attr.rs
@@ -1,21 +1,21 @@
 //! Format attributes and meta items.
 
-use rustc_ast::ast;
 use rustc_ast::HasAttrs;
-use rustc_span::{symbol::sym, Span};
+use rustc_ast::ast;
+use rustc_span::{Span, symbol::sym};
 use tracing::debug;
 
 use self::doc_comment::DocCommentFormatter;
-use crate::comment::{contains_comment, rewrite_doc_comment, CommentStyle};
-use crate::config::lists::*;
+use crate::comment::{CommentStyle, contains_comment, rewrite_doc_comment};
 use crate::config::IndentStyle;
+use crate::config::lists::*;
 use crate::expr::rewrite_literal;
-use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator};
+use crate::lists::{ListFormatting, Separator, definitive_tactic, itemize_list, write_list};
 use crate::overflow;
-use crate::rewrite::{Rewrite, RewriteContext};
+use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult};
 use crate::shape::Shape;
 use crate::source_map::SpanUtils;
-use crate::types::{rewrite_path, PathContext};
+use crate::types::{PathContext, rewrite_path};
 use crate::utils::{count_newlines, mk_sp};
 
 mod doc_comment;
@@ -100,7 +100,7 @@ fn format_derive(
                 ",",
                 |span| span.lo(),
                 |span| span.hi(),
-                |span| Some(context.snippet(*span).to_owned()),
+                |span| Ok(context.snippet(*span).to_owned()),
                 // We update derive attribute spans to start after the opening '('
                 // This helps us focus parsing to just what's inside #[derive(...)]
                 context.snippet_provider.span_after(attr.span, "("),
@@ -148,7 +148,7 @@ fn format_derive(
         .tactic(tactic)
         .trailing_separator(trailing_separator)
         .ends_with_newline(false);
-    let item_str = write_list(&all_items, &fmt)?;
+    let item_str = write_list(&all_items, &fmt).ok()?;
 
     debug!("item_str: '{}'", item_str);
 
@@ -218,9 +218,9 @@ fn rewrite_initial_doc_comments(
     context: &RewriteContext<'_>,
     attrs: &[ast::Attribute],
     shape: Shape,
-) -> Option<(usize, Option<String>)> {
+) -> Result<(usize, Option<String>), RewriteError> {
     if attrs.is_empty() {
-        return Some((0, None));
+        return Ok((0, None));
     }
     // Rewrite doc comments
     let sugared_docs = take_while_with_pred(context, attrs, |a| a.is_doc_comment());
@@ -230,7 +230,7 @@ fn rewrite_initial_doc_comments(
             .map(|a| context.snippet(a.span))
             .collect::<Vec<_>>()
             .join("\n");
-        return Some((
+        return Ok((
             sugared_docs.len(),
             Some(rewrite_doc_comment(
                 &snippet,
@@ -240,13 +240,19 @@ fn rewrite_initial_doc_comments(
         ));
     }
 
-    Some((0, None))
+    Ok((0, None))
 }
 
 impl Rewrite for ast::NestedMetaItem {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         match self {
-            ast::NestedMetaItem::MetaItem(ref meta_item) => meta_item.rewrite(context, shape),
+            ast::NestedMetaItem::MetaItem(ref meta_item) => {
+                meta_item.rewrite_result(context, shape)
+            }
             ast::NestedMetaItem::Lit(ref l) => {
                 rewrite_literal(context, l.as_token_lit(), l.span, shape)
             }
@@ -275,7 +281,11 @@ fn has_newlines_before_after_comment(comment: &str) -> (&str, &str) {
 
 impl Rewrite for ast::MetaItem {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
-        Some(match self.kind {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
+        Ok(match self.kind {
             ast::MetaItemKind::Word => {
                 rewrite_path(context, PathContext::Type, &None, &self.path, shape)?
             }
@@ -287,7 +297,7 @@ impl Rewrite for ast::MetaItem {
                     &path,
                     list.iter(),
                     // 1 = "]"
-                    shape.sub_width(1)?,
+                    shape.sub_width(1).max_width_error(shape.width, self.span)?,
                     self.span,
                     context.config.attr_fn_like_width(),
                     Some(if has_trailing_comma {
@@ -300,7 +310,9 @@ impl Rewrite for ast::MetaItem {
             ast::MetaItemKind::NameValue(ref lit) => {
                 let path = rewrite_path(context, PathContext::Type, &None, &self.path, shape)?;
                 // 3 = ` = `
-                let lit_shape = shape.shrink_left(path.len() + 3)?;
+                let lit_shape = shape
+                    .shrink_left(path.len() + 3)
+                    .max_width_error(shape.width, self.span)?;
                 // `rewrite_literal` returns `None` when `lit` exceeds max
                 // width. Since a literal is basically unformattable unless it
                 // is a string literal (and only if `format_strings` is set),
@@ -308,7 +320,7 @@ impl Rewrite for ast::MetaItem {
                 // is longer than the max width and continue on formatting.
                 // See #2479 for example.
                 let value = rewrite_literal(context, lit.as_token_lit(), lit.span, lit_shape)
-                    .unwrap_or_else(|| context.snippet(lit.span).to_owned());
+                    .unwrap_or_else(|_| context.snippet(lit.span).to_owned());
                 format!("{path} = {value}")
             }
         })
@@ -317,6 +329,10 @@ impl Rewrite for ast::MetaItem {
 
 impl Rewrite for ast::Attribute {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         let snippet = context.snippet(self.span);
         if self.is_doc_comment() {
             rewrite_doc_comment(snippet, shape.comment(context.config), context.config)
@@ -328,7 +344,7 @@ impl Rewrite for ast::Attribute {
             let prefix = attr_prefix(self);
 
             if should_skip || contains_comment(snippet) {
-                return Some(snippet.to_owned());
+                return Ok(snippet.to_owned());
             }
 
             if let Some(ref meta) = self.meta() {
@@ -353,9 +369,11 @@ impl Rewrite for ast::Attribute {
                 }
 
                 // 1 = `[`
-                let shape = shape.offset_left(prefix.len() + 1)?;
-                Some(meta.rewrite(context, shape).map_or_else(
-                    || snippet.to_owned(),
+                let shape = shape
+                    .offset_left(prefix.len() + 1)
+                    .max_width_error(shape.width, self.span)?;
+                Ok(meta.rewrite_result(context, shape).map_or_else(
+                    |_| snippet.to_owned(),
                     |rw| match &self.kind {
                         ast::AttrKind::Normal(normal_attr) => match normal_attr.item.unsafety {
                             // For #![feature(unsafe_attributes)]
@@ -367,7 +385,7 @@ impl Rewrite for ast::Attribute {
                     },
                 ))
             } else {
-                Some(snippet.to_owned())
+                Ok(snippet.to_owned())
             }
         }
     }
@@ -375,8 +393,12 @@ impl Rewrite for ast::Attribute {
 
 impl Rewrite for [ast::Attribute] {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         if self.is_empty() {
-            return Some(String::new());
+            return Ok(String::new());
         }
 
         // The current remaining attributes.
@@ -392,7 +414,7 @@ impl Rewrite for [ast::Attribute] {
         // merging derives into a single attribute.
         loop {
             if attrs.is_empty() {
-                return Some(result);
+                return Ok(result);
             }
 
             // Handle doc comments.
@@ -431,7 +453,7 @@ impl Rewrite for [ast::Attribute] {
             // Handle derives if we will merge them.
             if !skip_derives && context.config.merge_derives() && is_derive(&attrs[0]) {
                 let derives = take_while_with_pred(context, attrs, is_derive);
-                let derive_str = format_derive(derives, shape, context)?;
+                let derive_str = format_derive(derives, shape, context).unknown_error()?;
                 result.push_str(&derive_str);
 
                 let missing_span = attrs
@@ -464,7 +486,7 @@ impl Rewrite for [ast::Attribute] {
             // If we get here, then we have a regular attribute, just handle one
             // at a time.
 
-            let formatted_attr = attrs[0].rewrite(context, shape)?;
+            let formatted_attr = attrs[0].rewrite_result(context, shape)?;
             result.push_str(&formatted_attr);
 
             let missing_span = attrs
diff --git a/src/tools/rustfmt/src/bin/main.rs b/src/tools/rustfmt/src/bin/main.rs
index 88281d296be..c7d3a060d54 100644
--- a/src/tools/rustfmt/src/bin/main.rs
+++ b/src/tools/rustfmt/src/bin/main.rs
@@ -1,6 +1,6 @@
 #![feature(rustc_private)]
 
-use anyhow::{format_err, Result};
+use anyhow::{Result, format_err};
 
 use io::Error as IoError;
 use thiserror::Error;
@@ -11,15 +11,15 @@ use tracing_subscriber::EnvFilter;
 use std::collections::HashMap;
 use std::env;
 use std::fs::File;
-use std::io::{self, stdout, Read, Write};
+use std::io::{self, Read, Write, stdout};
 use std::path::{Path, PathBuf};
 use std::str::FromStr;
 
 use getopts::{Matches, Options};
 
 use crate::rustfmt::{
-    load_config, CliOptions, Color, Config, Edition, EmitMode, FileLines, FileName,
-    FormatReportFormatterBuilder, Input, Session, Verbosity,
+    CliOptions, Color, Config, Edition, EmitMode, FileLines, FileName,
+    FormatReportFormatterBuilder, Input, Session, StyleEdition, Verbosity, Version, load_config,
 };
 
 const BUG_REPORT_URL: &str = "https://github.com/rust-lang/rustfmt/issues/new?labels=bug";
@@ -129,7 +129,12 @@ fn make_opts() -> Options {
          found reverts to the input file path",
         "[Path for the configuration file]",
     );
-    opts.optopt("", "edition", "Rust edition to use", "[2015|2018|2021]");
+    opts.optopt(
+        "",
+        "edition",
+        "Rust edition to use",
+        "[2015|2018|2021|2024]",
+    );
     opts.optopt(
         "",
         "color",
@@ -181,6 +186,12 @@ fn make_opts() -> Options {
             "skip-children",
             "Don't reformat child modules (unstable).",
         );
+        opts.optopt(
+            "",
+            "style-edition",
+            "The edition of the Style Guide (unstable).",
+            "[2015|2018|2021|2024]",
+        );
     }
 
     opts.optflag("v", "verbose", "Print verbose output");
@@ -263,24 +274,35 @@ fn format_string(input: String, options: GetOptsOptions) -> Result<i32> {
     let (mut config, _) = load_config(Some(Path::new(".")), Some(options.clone()))?;
 
     if options.check {
-        config.set().emit_mode(EmitMode::Diff);
+        config.set_cli().emit_mode(EmitMode::Diff);
     } else {
         match options.emit_mode {
             // Emit modes which work with standard input
             // None means default, which is Stdout.
-            None | Some(EmitMode::Stdout) | Some(EmitMode::Checkstyle) | Some(EmitMode::Json) => {}
+            None => {
+                config
+                    .set()
+                    .emit_mode(options.emit_mode.unwrap_or(EmitMode::Stdout));
+            }
+            Some(EmitMode::Stdout) | Some(EmitMode::Checkstyle) | Some(EmitMode::Json) => {
+                config
+                    .set_cli()
+                    .emit_mode(options.emit_mode.unwrap_or(EmitMode::Stdout));
+            }
             Some(emit_mode) => {
                 return Err(OperationError::StdinBadEmit(emit_mode).into());
             }
         }
-        config
-            .set()
-            .emit_mode(options.emit_mode.unwrap_or(EmitMode::Stdout));
     }
     config.set().verbose(Verbosity::Quiet);
 
     // parse file_lines
-    config.set().file_lines(options.file_lines);
+    if options.file_lines.is_all() {
+        config.set().file_lines(options.file_lines);
+    } else {
+        config.set_cli().file_lines(options.file_lines);
+    }
+
     for f in config.file_lines().files() {
         match *f {
             FileName::Stdin => {}
@@ -319,10 +341,10 @@ fn format(
 
     for file in files {
         if !file.exists() {
-            eprintln!("Error: file `{}` does not exist", file.to_str().unwrap());
+            eprintln!("Error: file `{}` does not exist", file.display());
             session.add_operational_error();
         } else if file.is_dir() {
-            eprintln!("Error: `{}` is a directory", file.to_str().unwrap());
+            eprintln!("Error: `{}` is a directory", file.display());
             session.add_operational_error();
         } else {
             // Check the file directory if the config-path could not be read or not provided
@@ -428,27 +450,27 @@ are included as out of line modules from `src/lib.rs`."
 }
 
 fn print_version() {
-    let version_info = format!(
-        "{}-{}",
-        option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"),
-        include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt"))
-    );
+    let version_number = option_env!("CARGO_PKG_VERSION").unwrap_or("unknown");
+    let commit_info = include_str!(concat!(env!("OUT_DIR"), "/commit-info.txt"));
 
-    println!("rustfmt {version_info}");
+    if commit_info.is_empty() {
+        println!("rustfmt {version_number}");
+    } else {
+        println!("rustfmt {version_number}-{commit_info}");
+    }
 }
 
 fn determine_operation(matches: &Matches) -> Result<Operation, OperationError> {
     if matches.opt_present("h") {
-        let topic = matches.opt_str("h");
-        if topic.is_none() {
+        let Some(topic) = matches.opt_str("h") else {
             return Ok(Operation::Help(HelpOp::None));
-        } else if topic == Some("config".to_owned()) {
-            return Ok(Operation::Help(HelpOp::Config));
-        } else if topic == Some("file-lines".to_owned()) && is_nightly() {
-            return Ok(Operation::Help(HelpOp::FileLines));
-        } else {
-            return Err(OperationError::UnknownHelpTopic(topic.unwrap()));
-        }
+        };
+
+        return match topic.as_str() {
+            "config" => Ok(Operation::Help(HelpOp::Config)),
+            "file-lines" if is_nightly() => Ok(Operation::Help(HelpOp::FileLines)),
+            _ => Err(OperationError::UnknownHelpTopic(topic)),
+        };
     }
     let mut free_matches = matches.free.iter();
 
@@ -514,6 +536,7 @@ struct GetOptsOptions {
     backup: bool,
     check: bool,
     edition: Option<Edition>,
+    style_edition: Option<StyleEdition>,
     color: Option<Color>,
     file_lines: FileLines, // Default is all lines in all files.
     unstable_features: bool,
@@ -545,6 +568,10 @@ impl GetOptsOptions {
                 if let Some(ref file_lines) = matches.opt_str("file-lines") {
                     options.file_lines = file_lines.parse()?;
                 }
+                if let Some(ref edition_str) = matches.opt_str("style-edition") {
+                    options.style_edition =
+                        Some(style_edition_from_style_edition_str(edition_str)?);
+                }
             } else {
                 let mut unstable_options = vec![];
                 if matches.opt_present("skip-children") {
@@ -556,6 +583,9 @@ impl GetOptsOptions {
                 if matches.opt_present("file-lines") {
                     unstable_options.push("`--file-lines`");
                 }
+                if matches.opt_present("style-edition") {
+                    unstable_options.push("`--style-edition`");
+                }
                 if !unstable_options.is_empty() {
                     let s = if unstable_options.len() == 1 { "" } else { "s" };
                     return Err(format_err!(
@@ -650,36 +680,49 @@ impl GetOptsOptions {
 impl CliOptions for GetOptsOptions {
     fn apply_to(self, config: &mut Config) {
         if self.verbose {
-            config.set().verbose(Verbosity::Verbose);
+            config.set_cli().verbose(Verbosity::Verbose);
         } else if self.quiet {
-            config.set().verbose(Verbosity::Quiet);
+            config.set_cli().verbose(Verbosity::Quiet);
         } else {
             config.set().verbose(Verbosity::Normal);
         }
-        config.set().file_lines(self.file_lines);
-        config.set().unstable_features(self.unstable_features);
+
+        if self.file_lines.is_all() {
+            config.set().file_lines(self.file_lines);
+        } else {
+            config.set_cli().file_lines(self.file_lines);
+        }
+
+        if self.unstable_features {
+            config.set_cli().unstable_features(self.unstable_features);
+        } else {
+            config.set().unstable_features(self.unstable_features);
+        }
         if let Some(skip_children) = self.skip_children {
-            config.set().skip_children(skip_children);
+            config.set_cli().skip_children(skip_children);
         }
         if let Some(error_on_unformatted) = self.error_on_unformatted {
-            config.set().error_on_unformatted(error_on_unformatted);
+            config.set_cli().error_on_unformatted(error_on_unformatted);
         }
         if let Some(edition) = self.edition {
-            config.set().edition(edition);
+            config.set_cli().edition(edition);
+        }
+        if let Some(edition) = self.style_edition {
+            config.set_cli().style_edition(edition);
         }
         if self.check {
-            config.set().emit_mode(EmitMode::Diff);
+            config.set_cli().emit_mode(EmitMode::Diff);
         } else if let Some(emit_mode) = self.emit_mode {
-            config.set().emit_mode(emit_mode);
+            config.set_cli().emit_mode(emit_mode);
         }
         if self.backup {
-            config.set().make_backup(true);
+            config.set_cli().make_backup(true);
         }
         if let Some(color) = self.color {
-            config.set().color(color);
+            config.set_cli().color(color);
         }
         if self.print_misformatted_file_names {
-            config.set().print_misformatted_file_names(true);
+            config.set_cli().print_misformatted_file_names(true);
         }
 
         for (key, val) in self.inline_config {
@@ -690,6 +733,25 @@ impl CliOptions for GetOptsOptions {
     fn config_path(&self) -> Option<&Path> {
         self.config_path.as_deref()
     }
+
+    fn edition(&self) -> Option<Edition> {
+        self.inline_config
+            .get("edition")
+            .map_or(self.edition, |e| Edition::from_str(e).ok())
+    }
+
+    fn style_edition(&self) -> Option<StyleEdition> {
+        self.inline_config
+            .get("style_edition")
+            .map_or(self.style_edition, |se| StyleEdition::from_str(se).ok())
+    }
+
+    fn version(&self) -> Option<Version> {
+        self.inline_config
+            .get("version")
+            .map(|version| Version::from_str(version).ok())
+            .flatten()
+    }
 }
 
 fn edition_from_edition_str(edition_str: &str) -> Result<Edition> {
@@ -702,6 +764,16 @@ fn edition_from_edition_str(edition_str: &str) -> Result<Edition> {
     }
 }
 
+fn style_edition_from_style_edition_str(edition_str: &str) -> Result<StyleEdition> {
+    match edition_str {
+        "2015" => Ok(StyleEdition::Edition2015),
+        "2018" => Ok(StyleEdition::Edition2018),
+        "2021" => Ok(StyleEdition::Edition2021),
+        "2024" => Ok(StyleEdition::Edition2024),
+        _ => Err(format_err!("Invalid value for `--style-edition`")),
+    }
+}
+
 fn emit_mode_from_emit_str(emit_str: &str) -> Result<EmitMode> {
     match emit_str {
         "files" => Ok(EmitMode::Files),
@@ -712,3 +784,185 @@ fn emit_mode_from_emit_str(emit_str: &str) -> Result<EmitMode> {
         _ => Err(format_err!("Invalid value for `--emit`")),
     }
 }
+
+#[cfg(test)]
+#[allow(dead_code)]
+mod test {
+    use super::*;
+    use rustfmt_config_proc_macro::nightly_only_test;
+
+    fn get_config<O: CliOptions>(path: Option<&Path>, options: Option<O>) -> Config {
+        load_config(path, options).unwrap().0
+    }
+
+    #[nightly_only_test]
+    #[test]
+    fn flag_sets_style_edition_override_correctly() {
+        let mut options = GetOptsOptions::default();
+        options.style_edition = Some(StyleEdition::Edition2024);
+        let config = get_config(None, Some(options));
+        assert_eq!(config.style_edition(), StyleEdition::Edition2024);
+    }
+
+    #[nightly_only_test]
+    #[test]
+    fn edition_sets_style_edition_override_correctly() {
+        let mut options = GetOptsOptions::default();
+        options.edition = Some(Edition::Edition2024);
+        let config = get_config(None, Some(options));
+        assert_eq!(config.style_edition(), StyleEdition::Edition2024);
+    }
+
+    #[nightly_only_test]
+    #[test]
+    fn version_sets_style_edition_override_correctly() {
+        let mut options = GetOptsOptions::default();
+        options.inline_config = HashMap::from([("version".to_owned(), "Two".to_owned())]);
+        let config = get_config(None, Some(options));
+        assert_eq!(config.style_edition(), StyleEdition::Edition2024);
+        assert_eq!(config.overflow_delimited_expr(), true);
+    }
+
+    #[nightly_only_test]
+    #[test]
+    fn version_config_file_sets_style_edition_override_correctly() {
+        let options = GetOptsOptions::default();
+        let config_file = Some(Path::new("tests/config/style-edition/just-version"));
+        let config = get_config(config_file, Some(options));
+        assert_eq!(config.style_edition(), StyleEdition::Edition2024);
+        assert_eq!(config.overflow_delimited_expr(), true);
+    }
+
+    #[nightly_only_test]
+    #[test]
+    fn style_edition_flag_has_correct_precedence_over_edition() {
+        let mut options = GetOptsOptions::default();
+        options.style_edition = Some(StyleEdition::Edition2021);
+        options.edition = Some(Edition::Edition2024);
+        let config = get_config(None, Some(options));
+        assert_eq!(config.style_edition(), StyleEdition::Edition2021);
+    }
+
+    #[nightly_only_test]
+    #[test]
+    fn style_edition_flag_has_correct_precedence_over_version() {
+        let mut options = GetOptsOptions::default();
+        options.style_edition = Some(StyleEdition::Edition2018);
+        options.inline_config = HashMap::from([("version".to_owned(), "Two".to_owned())]);
+        let config = get_config(None, Some(options));
+        assert_eq!(config.style_edition(), StyleEdition::Edition2018);
+    }
+
+    #[nightly_only_test]
+    #[test]
+    fn style_edition_flag_has_correct_precedence_over_edition_version() {
+        let mut options = GetOptsOptions::default();
+        options.style_edition = Some(StyleEdition::Edition2021);
+        options.edition = Some(Edition::Edition2018);
+        options.inline_config = HashMap::from([("version".to_owned(), "Two".to_owned())]);
+        let config = get_config(None, Some(options));
+        assert_eq!(config.style_edition(), StyleEdition::Edition2021);
+    }
+
+    #[nightly_only_test]
+    #[test]
+    fn style_edition_inline_has_correct_precedence_over_edition_version() {
+        let mut options = GetOptsOptions::default();
+        options.edition = Some(Edition::Edition2018);
+        options.inline_config = HashMap::from([
+            ("version".to_owned(), "One".to_owned()),
+            ("style_edition".to_owned(), "2024".to_owned()),
+        ]);
+        let config = get_config(None, Some(options));
+        assert_eq!(config.style_edition(), StyleEdition::Edition2024);
+        assert_eq!(config.overflow_delimited_expr(), true);
+    }
+
+    #[nightly_only_test]
+    #[test]
+    fn style_edition_config_file_trumps_edition_flag_version_inline() {
+        let mut options = GetOptsOptions::default();
+        let config_file = Some(Path::new("tests/config/style-edition/just-style-edition"));
+        options.edition = Some(Edition::Edition2018);
+        options.inline_config = HashMap::from([("version".to_owned(), "One".to_owned())]);
+        let config = get_config(config_file, Some(options));
+        assert_eq!(config.style_edition(), StyleEdition::Edition2024);
+    }
+
+    #[nightly_only_test]
+    #[test]
+    fn style_edition_config_file_trumps_edition_config_and_version_inline() {
+        let mut options = GetOptsOptions::default();
+        let config_file = Some(Path::new(
+            "tests/config/style-edition/style-edition-and-edition",
+        ));
+        options.inline_config = HashMap::from([("version".to_owned(), "Two".to_owned())]);
+        let config = get_config(config_file, Some(options));
+        assert_eq!(config.style_edition(), StyleEdition::Edition2021);
+        assert_eq!(config.edition(), Edition::Edition2024);
+    }
+
+    #[nightly_only_test]
+    #[test]
+    fn version_config_trumps_edition_config_and_flag() {
+        let mut options = GetOptsOptions::default();
+        let config_file = Some(Path::new("tests/config/style-edition/version-edition"));
+        options.edition = Some(Edition::Edition2018);
+        let config = get_config(config_file, Some(options));
+        assert_eq!(config.style_edition(), StyleEdition::Edition2024);
+    }
+
+    #[nightly_only_test]
+    #[test]
+    fn style_edition_config_file_trumps_version_config() {
+        let options = GetOptsOptions::default();
+        let config_file = Some(Path::new(
+            "tests/config/style-edition/version-style-edition",
+        ));
+        let config = get_config(config_file, Some(options));
+        assert_eq!(config.style_edition(), StyleEdition::Edition2021);
+    }
+
+    #[nightly_only_test]
+    #[test]
+    fn style_edition_config_file_trumps_edition_version_config() {
+        let options = GetOptsOptions::default();
+        let config_file = Some(Path::new(
+            "tests/config/style-edition/version-style-edition-and-edition",
+        ));
+        let config = get_config(config_file, Some(options));
+        assert_eq!(config.style_edition(), StyleEdition::Edition2021);
+    }
+
+    #[nightly_only_test]
+    #[test]
+    fn correct_defaults_for_style_edition_loaded() {
+        let mut options = GetOptsOptions::default();
+        options.style_edition = Some(StyleEdition::Edition2024);
+        let config = get_config(None, Some(options));
+        assert_eq!(config.style_edition(), StyleEdition::Edition2024);
+        assert_eq!(config.overflow_delimited_expr(), true);
+    }
+
+    #[nightly_only_test]
+    #[test]
+    fn style_edition_defaults_overridden_from_config() {
+        let options = GetOptsOptions::default();
+        let config_file = Some(Path::new("tests/config/style-edition/overrides"));
+        let config = get_config(config_file, Some(options));
+        assert_eq!(config.style_edition(), StyleEdition::Edition2024);
+        assert_eq!(config.overflow_delimited_expr(), false);
+    }
+
+    #[nightly_only_test]
+    #[test]
+    fn style_edition_defaults_overridden_from_cli() {
+        let mut options = GetOptsOptions::default();
+        let config_file = Some(Path::new("tests/config/style-edition/just-style-edition"));
+        options.inline_config =
+            HashMap::from([("overflow_delimited_expr".to_owned(), "false".to_owned())]);
+        let config = get_config(config_file, Some(options));
+        assert_eq!(config.style_edition(), StyleEdition::Edition2024);
+        assert_eq!(config.overflow_delimited_expr(), false);
+    }
+}
diff --git a/src/tools/rustfmt/src/chains.rs b/src/tools/rustfmt/src/chains.rs
index 96fbe7a963a..fd2ef9cb1db 100644
--- a/src/tools/rustfmt/src/chains.rs
+++ b/src/tools/rustfmt/src/chains.rs
@@ -59,15 +59,15 @@ use std::borrow::Cow;
 use std::cmp::min;
 
 use rustc_ast::{ast, ptr};
-use rustc_span::{symbol, BytePos, Span};
+use rustc_span::{BytePos, Span, symbol};
 use tracing::debug;
 
-use crate::comment::{rewrite_comment, CharClasses, FullCodeCharKind, RichChar};
-use crate::config::{IndentStyle, Version};
+use crate::comment::{CharClasses, FullCodeCharKind, RichChar, rewrite_comment};
+use crate::config::{IndentStyle, StyleEdition};
 use crate::expr::rewrite_call;
 use crate::lists::extract_pre_comment;
 use crate::macros::convert_try_mac;
-use crate::rewrite::{Rewrite, RewriteContext};
+use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult};
 use crate::shape::Shape;
 use crate::source_map::SpanUtils;
 use crate::utils::{
@@ -80,6 +80,9 @@ use thin_vec::ThinVec;
 /// Provides the original input contents from the span
 /// of a chain element with trailing spaces trimmed.
 fn format_overflow_style(span: Span, context: &RewriteContext<'_>) -> Option<String> {
+    // TODO(ding-young): Currently returning None when the given span is out of the range
+    // covered by the snippet provider. If this is a common cause for internal
+    // rewrite failure, add a new enum variant and return RewriteError instead of None
     context.snippet_provider.span_to_snippet(span).map(|s| {
         s.lines()
             .map(|l| l.trim_end())
@@ -93,12 +96,16 @@ fn format_chain_item(
     context: &RewriteContext<'_>,
     rewrite_shape: Shape,
     allow_overflow: bool,
-) -> Option<String> {
+) -> RewriteResult {
     if allow_overflow {
-        item.rewrite(context, rewrite_shape)
-            .or_else(|| format_overflow_style(item.span, context))
+        // TODO(ding-young): Consider calling format_overflow_style()
+        // only when item.rewrite_result() returns RewriteError::ExceedsMaxWidth.
+        // It may be inappropriate to call format_overflow_style on other RewriteError
+        // since the current approach retries formatting if allow_overflow is true
+        item.rewrite_result(context, rewrite_shape)
+            .or_else(|_| format_overflow_style(item.span, context).unknown_error())
     } else {
-        item.rewrite(context, rewrite_shape)
+        item.rewrite_result(context, rewrite_shape)
     }
 }
 
@@ -135,17 +142,17 @@ pub(crate) fn rewrite_chain(
     expr: &ast::Expr,
     context: &RewriteContext<'_>,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     let chain = Chain::from_ast(expr, context);
     debug!("rewrite_chain {:?} {:?}", chain, shape);
 
     // If this is just an expression with some `?`s, then format it trivially and
     // return early.
     if chain.children.is_empty() {
-        return chain.parent.rewrite(context, shape);
+        return chain.parent.rewrite_result(context, shape);
     }
 
-    chain.rewrite(context, shape)
+    chain.rewrite_result(context, shape)
 }
 
 #[derive(Debug)]
@@ -203,7 +210,7 @@ impl ChainItemKind {
     fn is_tup_field_access(expr: &ast::Expr) -> bool {
         match expr.kind {
             ast::ExprKind::Field(_, ref field) => {
-                field.name.to_string().chars().all(|c| c.is_digit(10))
+                field.name.as_str().chars().all(|c| c.is_digit(10))
             }
             _ => false,
         }
@@ -269,7 +276,13 @@ impl ChainItemKind {
 
 impl Rewrite for ChainItem {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
-        let shape = shape.sub_width(self.tries)?;
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
+        let shape = shape
+            .sub_width(self.tries)
+            .max_width_error(shape.width, self.span)?;
         let rewrite = match self.kind {
             ChainItemKind::Parent {
                 ref expr,
@@ -278,14 +291,14 @@ impl Rewrite for ChainItem {
             ChainItemKind::Parent {
                 ref expr,
                 parens: false,
-            } => expr.rewrite(context, shape)?,
+            } => expr.rewrite_result(context, shape)?,
             ChainItemKind::MethodCall(ref segment, ref types, ref exprs) => {
                 Self::rewrite_method_call(segment.ident, types, exprs, self.span, context, shape)?
             }
             ChainItemKind::StructField(ident) => format!(".{}", rewrite_ident(context, ident)),
             ChainItemKind::TupleField(ident, nested) => format!(
                 "{}.{}",
-                if nested && context.config.version() == Version::One {
+                if nested && context.config.style_edition() <= StyleEdition::Edition2021 {
                     " "
                 } else {
                     ""
@@ -297,7 +310,7 @@ impl Rewrite for ChainItem {
                 rewrite_comment(comment, false, shape, context.config)?
             }
         };
-        Some(format!("{rewrite}{}", "?".repeat(self.tries)))
+        Ok(format!("{rewrite}{}", "?".repeat(self.tries)))
     }
 }
 
@@ -327,14 +340,14 @@ impl ChainItem {
         span: Span,
         context: &RewriteContext<'_>,
         shape: Shape,
-    ) -> Option<String> {
+    ) -> RewriteResult {
         let type_str = if types.is_empty() {
             String::new()
         } else {
             let type_list = types
                 .iter()
-                .map(|ty| ty.rewrite(context, shape))
-                .collect::<Option<Vec<_>>>()?;
+                .map(|ty| ty.rewrite_result(context, shape))
+                .collect::<Result<Vec<_>, RewriteError>>()?;
 
             format!("::<{}>", type_list.join(", "))
         };
@@ -519,6 +532,10 @@ impl Chain {
 
 impl Rewrite for Chain {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         debug!("rewrite chain {:?} {:?}", self, shape);
 
         let mut formatter = match context.config.indent_style() {
@@ -532,17 +549,25 @@ impl Rewrite for Chain {
 
         formatter.format_root(&self.parent, context, shape)?;
         if let Some(result) = formatter.pure_root() {
-            return wrap_str(result, context.config.max_width(), shape);
+            return wrap_str(result, context.config.max_width(), shape)
+                .max_width_error(shape.width, self.parent.span);
         }
 
+        let first = self.children.first().unwrap_or(&self.parent);
+        let last = self.children.last().unwrap_or(&self.parent);
+        let children_span = mk_sp(first.span.lo(), last.span.hi());
+        let full_span = self.parent.span.with_hi(children_span.hi());
+
         // Decide how to layout the rest of the chain.
-        let child_shape = formatter.child_shape(context, shape)?;
+        let child_shape = formatter
+            .child_shape(context, shape)
+            .max_width_error(shape.width, children_span)?;
 
         formatter.format_children(context, child_shape)?;
         formatter.format_last_child(context, shape, child_shape)?;
 
         let result = formatter.join_rewrites(context, child_shape)?;
-        wrap_str(result, context.config.max_width(), shape)
+        wrap_str(result, context.config.max_width(), shape).max_width_error(shape.width, full_span)
     }
 }
 
@@ -564,16 +589,20 @@ trait ChainFormatter {
         parent: &ChainItem,
         context: &RewriteContext<'_>,
         shape: Shape,
-    ) -> Option<()>;
+    ) -> Result<(), RewriteError>;
     fn child_shape(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<Shape>;
-    fn format_children(&mut self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<()>;
+    fn format_children(
+        &mut self,
+        context: &RewriteContext<'_>,
+        child_shape: Shape,
+    ) -> Result<(), RewriteError>;
     fn format_last_child(
         &mut self,
         context: &RewriteContext<'_>,
         shape: Shape,
         child_shape: Shape,
-    ) -> Option<()>;
-    fn join_rewrites(&self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<String>;
+    ) -> Result<(), RewriteError>;
+    fn join_rewrites(&self, context: &RewriteContext<'_>, child_shape: Shape) -> RewriteResult;
     // Returns `Some` if the chain is only a root, None otherwise.
     fn pure_root(&mut self) -> Option<String>;
 }
@@ -616,12 +645,16 @@ impl<'a> ChainFormatterShared<'a> {
         }
     }
 
-    fn format_children(&mut self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<()> {
+    fn format_children(
+        &mut self,
+        context: &RewriteContext<'_>,
+        child_shape: Shape,
+    ) -> Result<(), RewriteError> {
         for item in &self.children[..self.children.len() - 1] {
             let rewrite = format_chain_item(item, context, child_shape, self.allow_overflow)?;
             self.rewrites.push(rewrite);
         }
-        Some(())
+        Ok(())
     }
 
     // Rewrite the last child. The last child of a chain requires special treatment. We need to
@@ -662,8 +695,8 @@ impl<'a> ChainFormatterShared<'a> {
         context: &RewriteContext<'_>,
         shape: Shape,
         child_shape: Shape,
-    ) -> Option<()> {
-        let last = self.children.last()?;
+    ) -> Result<(), RewriteError> {
+        let last = self.children.last().unknown_error()?;
         let extendable = may_extend && last_line_extendable(&self.rewrites[0]);
         let prev_last_line_width = last_line_width(&self.rewrites[0]);
 
@@ -687,11 +720,17 @@ impl<'a> ChainFormatterShared<'a> {
             && self.rewrites.iter().all(|s| !s.contains('\n'))
             && one_line_budget > 0;
         let last_shape = if all_in_one_line {
-            shape.sub_width(last.tries)?
+            shape
+                .sub_width(last.tries)
+                .max_width_error(shape.width, last.span)?
         } else if extendable {
-            child_shape.sub_width(last.tries)?
+            child_shape
+                .sub_width(last.tries)
+                .max_width_error(child_shape.width, last.span)?
         } else {
-            child_shape.sub_width(shape.rhs_overhead(context.config) + last.tries)?
+            child_shape
+                .sub_width(shape.rhs_overhead(context.config) + last.tries)
+                .max_width_error(child_shape.width, last.span)?
         };
 
         let mut last_subexpr_str = None;
@@ -707,7 +746,7 @@ impl<'a> ChainFormatterShared<'a> {
             };
 
             if let Some(one_line_shape) = one_line_shape {
-                if let Some(rw) = last.rewrite(context, one_line_shape) {
+                if let Ok(rw) = last.rewrite_result(context, one_line_shape) {
                     // We allow overflowing here only if both of the following conditions match:
                     // 1. The entire chain fits in a single line except the last child.
                     // 2. `last_child_str.lines().count() >= 5`.
@@ -722,17 +761,18 @@ impl<'a> ChainFormatterShared<'a> {
                         // last child on its own line, and compare two rewrites to choose which is
                         // better.
                         let last_shape = child_shape
-                            .sub_width(shape.rhs_overhead(context.config) + last.tries)?;
-                        match last.rewrite(context, last_shape) {
-                            Some(ref new_rw) if !could_fit_single_line => {
+                            .sub_width(shape.rhs_overhead(context.config) + last.tries)
+                            .max_width_error(child_shape.width, last.span)?;
+                        match last.rewrite_result(context, last_shape) {
+                            Ok(ref new_rw) if !could_fit_single_line => {
                                 last_subexpr_str = Some(new_rw.clone());
                             }
-                            Some(ref new_rw) if new_rw.lines().count() >= line_count => {
+                            Ok(ref new_rw) if new_rw.lines().count() >= line_count => {
                                 last_subexpr_str = Some(rw);
                                 self.fits_single_line = could_fit_single_line && all_in_one_line;
                             }
-                            new_rw @ Some(..) => {
-                                last_subexpr_str = new_rw;
+                            Ok(new_rw) => {
+                                last_subexpr_str = Some(new_rw);
                             }
                             _ => {
                                 last_subexpr_str = Some(rw);
@@ -747,22 +787,28 @@ impl<'a> ChainFormatterShared<'a> {
         let last_shape = if context.use_block_indent() {
             last_shape
         } else {
-            child_shape.sub_width(shape.rhs_overhead(context.config) + last.tries)?
+            child_shape
+                .sub_width(shape.rhs_overhead(context.config) + last.tries)
+                .max_width_error(child_shape.width, last.span)?
         };
 
-        last_subexpr_str = last_subexpr_str.or_else(|| last.rewrite(context, last_shape));
-        self.rewrites.push(last_subexpr_str?);
-        Some(())
+        let last_subexpr_str =
+            last_subexpr_str.unwrap_or(last.rewrite_result(context, last_shape)?);
+        self.rewrites.push(last_subexpr_str);
+        Ok(())
     }
 
-    fn join_rewrites(&self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<String> {
+    fn join_rewrites(&self, context: &RewriteContext<'_>, child_shape: Shape) -> RewriteResult {
         let connector = if self.fits_single_line {
             // Yay, we can put everything on one line.
             Cow::from("")
         } else {
             // Use new lines.
             if context.force_one_line_chain.get() {
-                return None;
+                return Err(RewriteError::ExceedsMaxWidth {
+                    configured_width: child_shape.width,
+                    span: self.children.last().unknown_error()?.span,
+                });
             }
             child_shape.to_string_with_newline(context.config)
         };
@@ -781,7 +827,7 @@ impl<'a> ChainFormatterShared<'a> {
             result.push_str(rewrite);
         }
 
-        Some(result)
+        Ok(result)
     }
 }
 
@@ -806,8 +852,8 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> {
         parent: &ChainItem,
         context: &RewriteContext<'_>,
         shape: Shape,
-    ) -> Option<()> {
-        let mut root_rewrite: String = parent.rewrite(context, shape)?;
+    ) -> Result<(), RewriteError> {
+        let mut root_rewrite: String = parent.rewrite_result(context, shape)?;
 
         let mut root_ends_with_block = parent.kind.is_block_like(context, &root_rewrite);
         let tab_width = context.config.tab_spaces().saturating_sub(shape.offset);
@@ -817,10 +863,12 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> {
             if let ChainItemKind::Comment(..) = item.kind {
                 break;
             }
-            let shape = shape.offset_left(root_rewrite.len())?;
-            match &item.rewrite(context, shape) {
-                Some(rewrite) => root_rewrite.push_str(rewrite),
-                None => break,
+            let shape = shape
+                .offset_left(root_rewrite.len())
+                .max_width_error(shape.width, item.span)?;
+            match &item.rewrite_result(context, shape) {
+                Ok(rewrite) => root_rewrite.push_str(rewrite),
+                Err(_) => break,
             }
 
             root_ends_with_block = last_line_extendable(&root_rewrite);
@@ -832,7 +880,7 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> {
         }
         self.shared.rewrites.push(root_rewrite);
         self.root_ends_with_block = root_ends_with_block;
-        Some(())
+        Ok(())
     }
 
     fn child_shape(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<Shape> {
@@ -840,7 +888,11 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> {
         Some(get_block_child_shape(block_end, context, shape))
     }
 
-    fn format_children(&mut self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<()> {
+    fn format_children(
+        &mut self,
+        context: &RewriteContext<'_>,
+        child_shape: Shape,
+    ) -> Result<(), RewriteError> {
         self.shared.format_children(context, child_shape)
     }
 
@@ -849,12 +901,12 @@ impl<'a> ChainFormatter for ChainFormatterBlock<'a> {
         context: &RewriteContext<'_>,
         shape: Shape,
         child_shape: Shape,
-    ) -> Option<()> {
+    ) -> Result<(), RewriteError> {
         self.shared
             .format_last_child(true, context, shape, child_shape)
     }
 
-    fn join_rewrites(&self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<String> {
+    fn join_rewrites(&self, context: &RewriteContext<'_>, child_shape: Shape) -> RewriteResult {
         self.shared.join_rewrites(context, child_shape)
     }
 
@@ -885,9 +937,9 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> {
         parent: &ChainItem,
         context: &RewriteContext<'_>,
         shape: Shape,
-    ) -> Option<()> {
+    ) -> Result<(), RewriteError> {
         let parent_shape = shape.visual_indent(0);
-        let mut root_rewrite = parent.rewrite(context, parent_shape)?;
+        let mut root_rewrite = parent.rewrite_result(context, parent_shape)?;
         let multiline = root_rewrite.contains('\n');
         self.offset = if multiline {
             last_line_width(&root_rewrite).saturating_sub(shape.used_width())
@@ -899,18 +951,19 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> {
             let item = &self.shared.children[0];
             if let ChainItemKind::Comment(..) = item.kind {
                 self.shared.rewrites.push(root_rewrite);
-                return Some(());
+                return Ok(());
             }
             let child_shape = parent_shape
                 .visual_indent(self.offset)
-                .sub_width(self.offset)?;
-            let rewrite = item.rewrite(context, child_shape)?;
+                .sub_width(self.offset)
+                .max_width_error(parent_shape.width, item.span)?;
+            let rewrite = item.rewrite_result(context, child_shape)?;
             if filtered_str_fits(&rewrite, context.config.max_width(), shape) {
                 root_rewrite.push_str(&rewrite);
             } else {
                 // We couldn't fit in at the visual indent, try the last
                 // indent.
-                let rewrite = item.rewrite(context, parent_shape)?;
+                let rewrite = item.rewrite_result(context, parent_shape)?;
                 root_rewrite.push_str(&rewrite);
                 self.offset = 0;
             }
@@ -919,7 +972,7 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> {
         }
 
         self.shared.rewrites.push(root_rewrite);
-        Some(())
+        Ok(())
     }
 
     fn child_shape(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<Shape> {
@@ -932,7 +985,11 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> {
         )
     }
 
-    fn format_children(&mut self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<()> {
+    fn format_children(
+        &mut self,
+        context: &RewriteContext<'_>,
+        child_shape: Shape,
+    ) -> Result<(), RewriteError> {
         self.shared.format_children(context, child_shape)
     }
 
@@ -941,12 +998,12 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> {
         context: &RewriteContext<'_>,
         shape: Shape,
         child_shape: Shape,
-    ) -> Option<()> {
+    ) -> Result<(), RewriteError> {
         self.shared
             .format_last_child(false, context, shape, child_shape)
     }
 
-    fn join_rewrites(&self, context: &RewriteContext<'_>, child_shape: Shape) -> Option<String> {
+    fn join_rewrites(&self, context: &RewriteContext<'_>, child_shape: Shape) -> RewriteResult {
         self.shared.join_rewrites(context, child_shape)
     }
 
diff --git a/src/tools/rustfmt/src/closures.rs b/src/tools/rustfmt/src/closures.rs
index b5c26235e77..a37b47e3bc9 100644
--- a/src/tools/rustfmt/src/closures.rs
+++ b/src/tools/rustfmt/src/closures.rs
@@ -4,17 +4,17 @@ use thin_vec::thin_vec;
 use tracing::debug;
 
 use crate::attr::get_attrs_from_stmt;
+use crate::config::StyleEdition;
 use crate::config::lists::*;
-use crate::config::Version;
 use crate::expr::{block_contains_comment, is_simple_block, is_unsafe_block, rewrite_cond};
 use crate::items::{span_hi_for_param, span_lo_for_param};
-use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator};
+use crate::lists::{ListFormatting, Separator, definitive_tactic, itemize_list, write_list};
 use crate::overflow::OverflowableItem;
-use crate::rewrite::{Rewrite, RewriteContext};
+use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult};
 use crate::shape::Shape;
 use crate::source_map::SpanUtils;
 use crate::types::rewrite_bound_params;
-use crate::utils::{last_line_width, left_most_sub_expr, stmt_expr, NodeIdExt};
+use crate::utils::{NodeIdExt, last_line_width, left_most_sub_expr, stmt_expr};
 
 // This module is pretty messy because of the rules around closures and blocks:
 // FIXME - the below is probably no longer true in full.
@@ -37,7 +37,7 @@ pub(crate) fn rewrite_closure(
     span: Span,
     context: &RewriteContext<'_>,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     debug!("rewrite_closure {:?}", body);
 
     let (prefix, extra_offset) = rewrite_closure_fn_decl(
@@ -53,13 +53,15 @@ pub(crate) fn rewrite_closure(
         shape,
     )?;
     // 1 = space between `|...|` and body.
-    let body_shape = shape.offset_left(extra_offset)?;
+    let body_shape = shape
+        .offset_left(extra_offset)
+        .max_width_error(shape.width, span)?;
 
     if let ast::ExprKind::Block(ref block, _) = body.kind {
         // The body of the closure is an empty block.
         if block.stmts.is_empty() && !block_contains_comment(context, block) {
             return body
-                .rewrite(context, shape)
+                .rewrite_result(context, shape)
                 .map(|s| format!("{} {}", prefix, s));
         }
 
@@ -67,15 +69,15 @@ pub(crate) fn rewrite_closure(
             ast::FnRetTy::Default(_) if !context.inside_macro() => {
                 try_rewrite_without_block(body, &prefix, context, shape, body_shape)
             }
-            _ => None,
+            _ => Err(RewriteError::Unknown),
         };
 
-        result.or_else(|| {
+        result.or_else(|_| {
             // Either we require a block, or tried without and failed.
             rewrite_closure_block(block, &prefix, context, body_shape)
         })
     } else {
-        rewrite_closure_expr(body, &prefix, context, body_shape).or_else(|| {
+        rewrite_closure_expr(body, &prefix, context, body_shape).or_else(|_| {
             // The closure originally had a non-block expression, but we can't fit on
             // one line, so we'll insert a block.
             rewrite_closure_with_block(body, &prefix, context, body_shape)
@@ -89,7 +91,7 @@ fn try_rewrite_without_block(
     context: &RewriteContext<'_>,
     shape: Shape,
     body_shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     let expr = get_inner_expr(expr, prefix, context);
 
     if is_block_closure_forced(context, expr) {
@@ -153,11 +155,11 @@ fn rewrite_closure_with_block(
     prefix: &str,
     context: &RewriteContext<'_>,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     let left_most = left_most_sub_expr(body);
     let veto_block = veto_block(body) && !expr_requires_semi_to_be_stmt(left_most);
     if veto_block {
-        return None;
+        return Err(RewriteError::Unknown);
     }
 
     let block = ast::Block {
@@ -185,7 +187,7 @@ fn rewrite_closure_with_block(
         shape,
         false,
     )?;
-    Some(format!("{prefix} {block}"))
+    Ok(format!("{prefix} {block}"))
 }
 
 // Rewrite closure with a single expression without wrapping its body with block.
@@ -194,7 +196,7 @@ fn rewrite_closure_expr(
     prefix: &str,
     context: &RewriteContext<'_>,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     fn allow_multi_line(expr: &ast::Expr) -> bool {
         match expr.kind {
             ast::ExprKind::Match(..)
@@ -217,12 +219,12 @@ fn rewrite_closure_expr(
     // unless it is a block-like expression or we are inside macro call.
     let veto_multiline = (!allow_multi_line(expr) && !context.inside_macro())
         || context.config.force_multiline_blocks();
-    expr.rewrite(context, shape)
+    expr.rewrite_result(context, shape)
         .and_then(|rw| {
             if veto_multiline && rw.contains('\n') {
-                None
+                Err(RewriteError::Unknown)
             } else {
-                Some(rw)
+                Ok(rw)
             }
         })
         .map(|rw| format!("{} {}", prefix, rw))
@@ -234,8 +236,12 @@ fn rewrite_closure_block(
     prefix: &str,
     context: &RewriteContext<'_>,
     shape: Shape,
-) -> Option<String> {
-    Some(format!("{} {}", prefix, block.rewrite(context, shape)?))
+) -> RewriteResult {
+    Ok(format!(
+        "{} {}",
+        prefix,
+        block.rewrite_result(context, shape)?
+    ))
 }
 
 // Return type is (prefix, extra_offset)
@@ -250,13 +256,14 @@ fn rewrite_closure_fn_decl(
     span: Span,
     context: &RewriteContext<'_>,
     shape: Shape,
-) -> Option<(String, usize)> {
+) -> Result<(String, usize), RewriteError> {
     let binder = match binder {
         ast::ClosureBinder::For { generic_params, .. } if generic_params.is_empty() => {
             "for<> ".to_owned()
         }
         ast::ClosureBinder::For { generic_params, .. } => {
-            let lifetime_str = rewrite_bound_params(context, shape, generic_params)?;
+            let lifetime_str =
+                rewrite_bound_params(context, shape, generic_params).unknown_error()?;
             format!("for<{lifetime_str}> ")
         }
         ast::ClosureBinder::NotPresent => "".to_owned(),
@@ -287,13 +294,17 @@ fn rewrite_closure_fn_decl(
     // 4 = "|| {".len(), which is overconservative when the closure consists of
     // a single expression.
     let nested_shape = shape
-        .shrink_left(binder.len() + const_.len() + immovable.len() + coro.len() + mover.len())?
-        .sub_width(4)?;
+        .shrink_left(binder.len() + const_.len() + immovable.len() + coro.len() + mover.len())
+        .and_then(|shape| shape.sub_width(4))
+        .max_width_error(shape.width, span)?;
 
     // 1 = |
     let param_offset = nested_shape.indent + 1;
-    let param_shape = nested_shape.offset_left(1)?.visual_indent(0);
-    let ret_str = fn_decl.output.rewrite(context, param_shape)?;
+    let param_shape = nested_shape
+        .offset_left(1)
+        .max_width_error(nested_shape.width, span)?
+        .visual_indent(0);
+    let ret_str = fn_decl.output.rewrite_result(context, param_shape)?;
 
     let param_items = itemize_list(
         context.snippet_provider,
@@ -302,7 +313,7 @@ fn rewrite_closure_fn_decl(
         ",",
         |param| span_lo_for_param(param),
         |param| span_hi_for_param(context, param),
-        |param| param.rewrite(context, param_shape),
+        |param| param.rewrite_result(context, param_shape),
         context.snippet_provider.span_after(span, "|"),
         body.span.lo(),
         false,
@@ -317,7 +328,9 @@ fn rewrite_closure_fn_decl(
         horizontal_budget,
     );
     let param_shape = match tactic {
-        DefinitiveListTactic::Horizontal => param_shape.sub_width(ret_str.len() + 1)?,
+        DefinitiveListTactic::Horizontal => param_shape
+            .sub_width(ret_str.len() + 1)
+            .max_width_error(param_shape.width, span)?,
         _ => param_shape,
     };
 
@@ -339,7 +352,7 @@ fn rewrite_closure_fn_decl(
     // 1 = space between `|...|` and body.
     let extra_offset = last_line_width(&prefix) + 1;
 
-    Some((prefix, extra_offset))
+    Ok((prefix, extra_offset))
 }
 
 // Rewriting closure which is placed at the end of the function call's arg.
@@ -348,7 +361,7 @@ pub(crate) fn rewrite_last_closure(
     context: &RewriteContext<'_>,
     expr: &ast::Expr,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     if let ast::ExprKind::Closure(ref closure) = expr.kind {
         let ast::Closure {
             ref binder,
@@ -385,10 +398,12 @@ pub(crate) fn rewrite_last_closure(
         )?;
         // If the closure goes multi line before its body, do not overflow the closure.
         if prefix.contains('\n') {
-            return None;
+            return Err(RewriteError::Unknown);
         }
 
-        let body_shape = shape.offset_left(extra_offset)?;
+        let body_shape = shape
+            .offset_left(extra_offset)
+            .max_width_error(shape.width, expr.span)?;
 
         // We force to use block for the body of the closure for certain kinds of expressions.
         if is_block_closure_forced(context, body) {
@@ -400,7 +415,7 @@ pub(crate) fn rewrite_last_closure(
                             // closure.  However, if the closure has a return type, then we must
                             // keep the blocks.
                             match rewrite_closure_expr(body, &prefix, context, shape) {
-                                Some(single_line_body_str)
+                                Ok(single_line_body_str)
                                     if !single_line_body_str.contains('\n') =>
                                 {
                                     single_line_body_str
@@ -424,9 +439,9 @@ pub(crate) fn rewrite_last_closure(
         }
 
         // Seems fine, just format the closure in usual manner.
-        return expr.rewrite(context, shape);
+        return expr.rewrite_result(context, shape);
     }
-    None
+    Err(RewriteError::Unknown)
 }
 
 /// Returns `true` if the given vector of arguments has more than one `ast::ExprKind::Closure`.
@@ -443,18 +458,18 @@ fn is_block_closure_forced(context: &RewriteContext<'_>, expr: &ast::Expr) -> bo
     if context.inside_macro() {
         false
     } else {
-        is_block_closure_forced_inner(expr, context.config.version())
+        is_block_closure_forced_inner(expr, context.config.style_edition())
     }
 }
 
-fn is_block_closure_forced_inner(expr: &ast::Expr, version: Version) -> bool {
+fn is_block_closure_forced_inner(expr: &ast::Expr, style_edition: StyleEdition) -> bool {
     match expr.kind {
         ast::ExprKind::If(..) | ast::ExprKind::While(..) | ast::ExprKind::ForLoop { .. } => true,
-        ast::ExprKind::Loop(..) if version == Version::Two => true,
+        ast::ExprKind::Loop(..) if style_edition >= StyleEdition::Edition2024 => true,
         ast::ExprKind::AddrOf(_, _, ref expr)
         | ast::ExprKind::Try(ref expr)
         | ast::ExprKind::Unary(_, ref expr)
-        | ast::ExprKind::Cast(ref expr, _) => is_block_closure_forced_inner(expr, version),
+        | ast::ExprKind::Cast(ref expr, _) => is_block_closure_forced_inner(expr, style_edition),
         _ => false,
     }
 }
diff --git a/src/tools/rustfmt/src/comment.rs b/src/tools/rustfmt/src/comment.rs
index e76be0fd162..b7d7a396a67 100644
--- a/src/tools/rustfmt/src/comment.rs
+++ b/src/tools/rustfmt/src/comment.rs
@@ -2,14 +2,14 @@
 
 use std::{borrow::Cow, iter};
 
-use itertools::{multipeek, MultiPeek};
+use itertools::{Itertools as _, MultiPeek, multipeek};
 use rustc_span::Span;
 use tracing::{debug, trace};
 
 use crate::config::Config;
-use crate::rewrite::RewriteContext;
+use crate::rewrite::{RewriteContext, RewriteErrorExt, RewriteResult};
 use crate::shape::{Indent, Shape};
-use crate::string::{rewrite_string, StringFormat};
+use crate::string::{StringFormat, rewrite_string};
 use crate::utils::{
     count_newlines, first_line_width, last_line_width, trim_left_preserve_layout,
     trimmed_last_line_width, unicode_str_width,
@@ -158,7 +158,7 @@ pub(crate) fn combine_strs_with_missing_comments(
     span: Span,
     shape: Shape,
     allow_extend: bool,
-) -> Option<String> {
+) -> RewriteResult {
     trace!(
         "combine_strs_with_missing_comments `{}` `{}` {:?} {:?}",
         prev_str, next_str, span, shape
@@ -188,7 +188,7 @@ pub(crate) fn combine_strs_with_missing_comments(
             result.push_str(&indent.to_string_with_newline(config))
         }
         result.push_str(next_str);
-        return Some(result);
+        return Ok(result);
     }
 
     // We have a missing comment between the first expression and the second expression.
@@ -233,10 +233,10 @@ pub(crate) fn combine_strs_with_missing_comments(
     result.push_str(&second_sep);
     result.push_str(next_str);
 
-    Some(result)
+    Ok(result)
 }
 
-pub(crate) fn rewrite_doc_comment(orig: &str, shape: Shape, config: &Config) -> Option<String> {
+pub(crate) fn rewrite_doc_comment(orig: &str, shape: Shape, config: &Config) -> RewriteResult {
     identify_comment(orig, false, shape, config, true)
 }
 
@@ -245,7 +245,7 @@ pub(crate) fn rewrite_comment(
     block_style: bool,
     shape: Shape,
     config: &Config,
-) -> Option<String> {
+) -> RewriteResult {
     identify_comment(orig, block_style, shape, config, false)
 }
 
@@ -255,7 +255,7 @@ fn identify_comment(
     shape: Shape,
     config: &Config,
     is_doc_comment: bool,
-) -> Option<String> {
+) -> RewriteResult {
     let style = comment_style(orig, false);
 
     // Computes the byte length of line taking into account a newline if the line is part of a
@@ -347,7 +347,7 @@ fn identify_comment(
     let (first_group, rest) = orig.split_at(first_group_ending);
     let rewritten_first_group =
         if !config.normalize_comments() && has_bare_lines && style.is_block_comment() {
-            trim_left_preserve_layout(first_group, shape.indent, config)?
+            trim_left_preserve_layout(first_group, shape.indent, config).unknown_error()?
         } else if !config.normalize_comments()
             && !config.wrap_comments()
             && !(
@@ -368,7 +368,7 @@ fn identify_comment(
             )?
         };
     if rest.is_empty() {
-        Some(rewritten_first_group)
+        Ok(rewritten_first_group)
     } else {
         identify_comment(
             rest.trim_start(),
@@ -534,10 +534,11 @@ impl ItemizedBlock {
 
     /// Returns the block as a string, with each line trimmed at the start.
     fn trimmed_block_as_string(&self) -> String {
-        self.lines
-            .iter()
-            .map(|line| format!("{} ", line.trim_start()))
-            .collect::<String>()
+        self.lines.iter().fold(String::new(), |mut acc, line| {
+            acc.push_str(line.trim_start());
+            acc.push(' ');
+            acc
+        })
     }
 
     /// Returns the block as a string under its original form.
@@ -900,7 +901,7 @@ fn rewrite_comment_inner(
     shape: Shape,
     config: &Config,
     is_doc_comment: bool,
-) -> Option<String> {
+) -> RewriteResult {
     let mut rewriter = CommentRewrite::new(orig, block_style, shape, config);
 
     let line_breaks = count_newlines(orig.trim_end());
@@ -934,7 +935,7 @@ fn rewrite_comment_inner(
         }
     }
 
-    Some(rewriter.finish())
+    Ok(rewriter.finish())
 }
 
 const RUSTFMT_CUSTOM_COMMENT_PREFIX: &str = "//#### ";
@@ -999,7 +1000,7 @@ pub(crate) fn rewrite_missing_comment(
     span: Span,
     shape: Shape,
     context: &RewriteContext<'_>,
-) -> Option<String> {
+) -> RewriteResult {
     let missing_snippet = context.snippet(span);
     let trimmed_snippet = missing_snippet.trim();
     // check the span starts with a comment
@@ -1007,7 +1008,7 @@ pub(crate) fn rewrite_missing_comment(
     if !trimmed_snippet.is_empty() && pos.is_some() {
         rewrite_comment(trimmed_snippet, false, shape, context.config)
     } else {
-        Some(String::new())
+        Ok(String::new())
     }
 }
 
@@ -1019,13 +1020,13 @@ pub(crate) fn recover_missing_comment_in_span(
     shape: Shape,
     context: &RewriteContext<'_>,
     used_width: usize,
-) -> Option<String> {
+) -> RewriteResult {
     let missing_comment = rewrite_missing_comment(span, shape, context)?;
     if missing_comment.is_empty() {
-        Some(String::new())
+        Ok(String::new())
     } else {
         let missing_snippet = context.snippet(span);
-        let pos = missing_snippet.find('/')?;
+        let pos = missing_snippet.find('/').unknown_error()?;
         // 1 = ` `
         let total_width = missing_comment.len() + used_width + 1;
         let force_new_line_before_comment =
@@ -1035,7 +1036,7 @@ pub(crate) fn recover_missing_comment_in_span(
         } else {
             Cow::from(" ")
         };
-        Some(format!("{sep}{missing_comment}"))
+        Ok(format!("{sep}{missing_comment}"))
     }
 }
 
@@ -1055,8 +1056,7 @@ fn light_rewrite_comment(
     config: &Config,
     is_doc_comment: bool,
 ) -> String {
-    let lines: Vec<&str> = orig
-        .lines()
+    orig.lines()
         .map(|l| {
             // This is basically just l.trim(), but in the case that a line starts
             // with `*` we want to leave one space before it, so it aligns with the
@@ -1074,8 +1074,7 @@ fn light_rewrite_comment(
             // Preserve markdown's double-space line break syntax in doc comment.
             trim_end_unless_two_whitespaces(left_trimmed, is_doc_comment)
         })
-        .collect();
-    lines.join(&format!("\n{}", offset.to_string(config)))
+        .join(&format!("\n{}", offset.to_string(config)))
 }
 
 /// Trims comment characters and possibly a single space from the left of a string.
@@ -1704,12 +1703,11 @@ impl<'a> Iterator for CommentCodeSlices<'a> {
 }
 
 /// Checks is `new` didn't miss any comment from `span`, if it removed any, return previous text
-/// (if it fits in the width/offset, else return `None`), else return `new`
 pub(crate) fn recover_comment_removed(
     new: String,
     span: Span,
     context: &RewriteContext<'_>,
-) -> Option<String> {
+) -> String {
     let snippet = context.snippet(span);
     if snippet != new && changed_comment_content(snippet, &new) {
         // We missed some comments. Warn and keep the original text.
@@ -1723,9 +1721,9 @@ pub(crate) fn recover_comment_removed(
                 )],
             );
         }
-        Some(snippet.to_owned())
+        snippet.to_owned()
     } else {
-        Some(new)
+        new
     }
 }
 
diff --git a/src/tools/rustfmt/src/config/config_type.rs b/src/tools/rustfmt/src/config/config_type.rs
index f7cff1a1729..14217caba0a 100644
--- a/src/tools/rustfmt/src/config/config_type.rs
+++ b/src/tools/rustfmt/src/config/config_type.rs
@@ -70,15 +70,15 @@ macro_rules! create_config {
     //
     // - $i: the ident name of the option
     // - $ty: the type of the option value
-    // - $def: the default value of the option
     // - $stb: true if the option is stable
     // - $dstring: description of the option
-    ($($i:ident: $ty:ty, $def:expr, $stb:expr, $( $dstring:expr ),+ );+ $(;)*) => (
+    ($($i:ident: $ty:ty, $stb:expr, $( $dstring:expr ),+ );+ $(;)*) => (
         #[cfg(test)]
         use std::collections::HashSet;
         use std::io::Write;
 
         use serde::{Deserialize, Serialize};
+        use $crate::config::style_edition::StyleEditionDefault;
 
         #[derive(Clone)]
         #[allow(unreachable_pub)]
@@ -89,7 +89,10 @@ macro_rules! create_config {
             // - 1: true if the option was manually initialized
             // - 2: the option value
             // - 3: true if the option is unstable
-            $($i: (Cell<bool>, bool, $ty, bool)),+
+            // - 4: true if the option was set manually from a CLI flag
+            // FIXME: 4 is probably unnecessary and duplicative
+            // https://github.com/rust-lang/rustfmt/issues/6252
+            $($i: (Cell<bool>, bool, <$ty as StyleEditionDefault>::ConfigType, bool, bool)),+
         }
 
         // Just like the Config struct but with each property wrapped
@@ -100,7 +103,7 @@ macro_rules! create_config {
         #[derive(Deserialize, Serialize, Clone)]
         #[allow(unreachable_pub)]
         pub struct PartialConfig {
-            $(pub $i: Option<$ty>),+
+            $(pub $i: Option<<$ty as StyleEditionDefault>::ConfigType>),+
         }
 
         // Macro hygiene won't allow us to make `set_$i()` methods on Config
@@ -114,7 +117,7 @@ macro_rules! create_config {
         impl<'a> ConfigSetter<'a> {
             $(
             #[allow(unreachable_pub)]
-            pub fn $i(&mut self, value: $ty) {
+            pub fn $i(&mut self, value: <$ty as StyleEditionDefault>::ConfigType) {
                 (self.0).$i.2 = value;
                 match stringify!($i) {
                     "max_width"
@@ -130,6 +133,37 @@ macro_rules! create_config {
                     "merge_imports" => self.0.set_merge_imports(),
                     "fn_args_layout" => self.0.set_fn_args_layout(),
                     "hide_parse_errors" => self.0.set_hide_parse_errors(),
+                    "version" => self.0.set_version(),
+                    &_ => (),
+                }
+            }
+            )+
+        }
+
+        #[allow(unreachable_pub)]
+        pub struct CliConfigSetter<'a>(&'a mut Config);
+
+        impl<'a> CliConfigSetter<'a> {
+            $(
+            #[allow(unreachable_pub)]
+            pub fn $i(&mut self, value: <$ty as StyleEditionDefault>::ConfigType) {
+                (self.0).$i.2 = value;
+                (self.0).$i.4 = true;
+                match stringify!($i) {
+                    "max_width"
+                    | "use_small_heuristics"
+                    | "fn_call_width"
+                    | "single_line_if_else_max_width"
+                    | "single_line_let_else_max_width"
+                    | "attr_fn_like_width"
+                    | "struct_lit_width"
+                    | "struct_variant_width"
+                    | "array_width"
+                    | "chain_width" => self.0.set_heuristics(),
+                    "merge_imports" => self.0.set_merge_imports(),
+                    "fn_args_layout" => self.0.set_fn_args_layout(),
+                    "hide_parse_errors" => self.0.set_hide_parse_errors(),
+                    "version" => self.0.set_version(),
                     &_ => (),
                 }
             }
@@ -150,25 +184,66 @@ macro_rules! create_config {
             )+
         }
 
+        // Query each option, returns true if the user set the option via a CLI flag,
+        // false if a default was used.
+        #[allow(unreachable_pub)]
+        pub struct CliConfigWasSet<'a>(&'a Config);
+
+        impl<'a> CliConfigWasSet<'a> {
+            $(
+            #[allow(unreachable_pub)]
+            pub fn $i(&self) -> bool {
+                (self.0).$i.4
+            }
+            )+
+        }
+
         impl Config {
             $(
             #[allow(unreachable_pub)]
-            pub fn $i(&self) -> $ty {
+            pub fn $i(&self) -> <$ty as StyleEditionDefault>::ConfigType {
                 self.$i.0.set(true);
                 self.$i.2.clone()
             }
             )+
 
             #[allow(unreachable_pub)]
+            pub(super) fn default_with_style_edition(style_edition: StyleEdition) -> Config {
+                Config {
+                    $(
+                        $i: (
+                                Cell::new(false),
+                                false,
+                                <$ty as StyleEditionDefault>::style_edition_default(
+                                    style_edition
+                                ),
+                                $stb,
+                                false,
+                            ),
+                    )+
+                }
+            }
+
+            #[allow(unreachable_pub)]
             pub fn set(&mut self) -> ConfigSetter<'_> {
                 ConfigSetter(self)
             }
 
             #[allow(unreachable_pub)]
+            pub fn set_cli(&mut self) -> CliConfigSetter<'_> {
+                CliConfigSetter(self)
+            }
+
+            #[allow(unreachable_pub)]
             pub fn was_set(&self) -> ConfigWasSet<'_> {
                 ConfigWasSet(self)
             }
 
+            #[allow(unreachable_pub)]
+            pub fn was_set_cli(&self) -> CliConfigWasSet<'_> {
+                CliConfigWasSet(self)
+            }
+
             fn fill_from_parsed_config(mut self, parsed: PartialConfig, dir: &Path) -> Config {
             $(
                 if let Some(option_value) = parsed.$i {
@@ -186,6 +261,7 @@ macro_rules! create_config {
                 self.set_merge_imports();
                 self.set_fn_args_layout();
                 self.set_hide_parse_errors();
+                self.set_version();
                 self
             }
 
@@ -212,7 +288,9 @@ macro_rules! create_config {
             pub fn is_valid_key_val(key: &str, val: &str) -> bool {
                 match key {
                     $(
-                        stringify!($i) => val.parse::<$ty>().is_ok(),
+                        stringify!($i) => {
+                            val.parse::<<$ty as StyleEditionDefault>::ConfigType>().is_ok()
+                        }
                     )+
                         _ => false,
                 }
@@ -246,11 +324,15 @@ macro_rules! create_config {
                 match key {
                     $(
                         stringify!($i) => {
-                            let option_value = val.parse::<$ty>()
-                                .expect(&format!("Failed to parse override for {} (\"{}\") as a {}",
-                                                 stringify!($i),
-                                                 val,
-                                                 stringify!($ty)));
+                            let value = val.parse::<<$ty as StyleEditionDefault>::ConfigType>()
+                                .expect(
+                                    &format!(
+                                        "Failed to parse override for {} (\"{}\") as a {}",
+                                        stringify!($i),
+                                        val,
+                                        stringify!(<$ty as StyleEditionDefault>::ConfigType)
+                                    )
+                                );
 
                             // Users are currently allowed to set unstable
                             // options/variants via the `--config` options override.
@@ -261,7 +343,7 @@ macro_rules! create_config {
                             // For now, do not validate whether the option or value is stable,
                             // just always set it.
                             self.$i.1 = true;
-                            self.$i.2 = option_value;
+                            self.$i.2 = value;
                         }
                     )+
                     _ => panic!("Unknown config key in override: {}", key)
@@ -281,6 +363,7 @@ macro_rules! create_config {
                     "merge_imports" => self.set_merge_imports(),
                     "fn_args_layout" => self.set_fn_args_layout(),
                     "hide_parse_errors" => self.set_hide_parse_errors(),
+                    "version" => self.set_version(),
                     &_ => (),
                 }
             }
@@ -301,6 +384,7 @@ macro_rules! create_config {
 
             #[allow(unreachable_pub)]
             pub fn print_docs(out: &mut dyn Write, include_unstable: bool) {
+                let style_edition = StyleEdition::Edition2015;
                 use std::cmp;
                 let max = 0;
                 $( let max = cmp::max(max, stringify!($i).len()+1); )+
@@ -317,14 +401,17 @@ macro_rules! create_config {
                             }
                             name_out.push_str(name_raw);
                             name_out.push(' ');
-                            let mut default_str = format!("{}", $def);
+                            let default_value = <$ty as StyleEditionDefault>::style_edition_default(
+                                style_edition
+                            );
+                            let mut default_str = format!("{}", default_value);
                             if default_str.is_empty() {
                                 default_str = String::from("\"\"");
                             }
                             writeln!(out,
                                     "{}{} Default: {}{}",
                                     name_out,
-                                    <$ty>::doc_hint(),
+                                    <<$ty as StyleEditionDefault>::ConfigType>::doc_hint(),
                                     default_str,
                                     if !$stb { " (unstable)" } else { "" }).unwrap();
                             $(
@@ -477,12 +564,36 @@ macro_rules! create_config {
                 }
             }
 
+            fn set_version(&mut self) {
+                if !self.was_set().version() {
+                    return;
+                }
+
+                eprintln!(
+                    "Warning: the `version` option is deprecated. \
+                    Use `style_edition` instead."
+                );
+
+                if self.was_set().style_edition() || self.was_set_cli().style_edition() {
+                    eprintln!(
+                        "Warning: the deprecated `version` option was \
+                        used in conjunction with the `style_edition` \
+                        option which takes precedence. \
+                        The value of the `version` option will be ignored."
+                    );
+                }
+            }
+
             #[allow(unreachable_pub)]
             /// Returns `true` if the config key was explicitly set and is the default value.
             pub fn is_default(&self, key: &str) -> bool {
+                let style_edition = StyleEdition::Edition2015;
                 $(
+                    let default_value = <$ty as StyleEditionDefault>::style_edition_default(
+                        style_edition
+                    );
                     if let stringify!($i) = key {
-                        return self.$i.1 && self.$i.2 == $def;
+                        return self.$i.1 && self.$i.2 == default_value;
                     }
                  )+
                 false
@@ -492,11 +603,7 @@ macro_rules! create_config {
         // Template for the default configuration
         impl Default for Config {
             fn default() -> Config {
-                Config {
-                    $(
-                        $i: (Cell::new(false), false, $def, $stb),
-                    )+
-                }
+                Config::default_with_style_edition(StyleEdition::Edition2015)
             }
         }
     )
diff --git a/src/tools/rustfmt/src/config/file_lines.rs b/src/tools/rustfmt/src/config/file_lines.rs
index 224864393d3..c53ec6371e9 100644
--- a/src/tools/rustfmt/src/config/file_lines.rs
+++ b/src/tools/rustfmt/src/config/file_lines.rs
@@ -7,7 +7,7 @@ use std::{cmp, fmt, iter, str};
 
 use rustc_data_structures::sync::Lrc;
 use rustc_span::SourceFile;
-use serde::{ser, Deserialize, Deserializer, Serialize, Serializer};
+use serde::{Deserialize, Deserializer, Serialize, Serializer, ser};
 use serde_json as json;
 use thiserror::Error;
 
@@ -38,7 +38,7 @@ impl From<rustc_span::FileName> for FileName {
 impl fmt::Display for FileName {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self {
-            FileName::Real(p) => write!(f, "{}", p.to_str().unwrap()),
+            FileName::Real(p) => write!(f, "{}", p.display()),
             FileName::Stdin => write!(f, "<stdin>"),
         }
     }
@@ -201,7 +201,7 @@ impl FileLines {
     }
 
     /// Returns `true` if this `FileLines` contains all lines in all files.
-    pub(crate) fn is_all(&self) -> bool {
+    pub fn is_all(&self) -> bool {
         self.0.is_none()
     }
 
diff --git a/src/tools/rustfmt/src/config/mod.rs b/src/tools/rustfmt/src/config/mod.rs
index 9484b2e5829..ea257c0a8ba 100644
--- a/src/tools/rustfmt/src/config/mod.rs
+++ b/src/tools/rustfmt/src/config/mod.rs
@@ -10,9 +10,7 @@ use crate::config::config_type::ConfigType;
 #[allow(unreachable_pub)]
 pub use crate::config::file_lines::{FileLines, FileName, Range};
 #[allow(unreachable_pub)]
-pub use crate::config::lists::*;
-#[allow(unreachable_pub)]
-pub use crate::config::macro_names::{MacroSelector, MacroSelectors};
+pub use crate::config::macro_names::MacroSelector;
 #[allow(unreachable_pub)]
 pub use crate::config::options::*;
 
@@ -34,161 +32,169 @@ pub(crate) mod style_edition;
 // `name: value type, default value, is stable, description;`
 create_config! {
     // Fundamental stuff
-    max_width: usize, 100, true, "Maximum width of each line";
-    hard_tabs: bool, false, true, "Use tab characters for indentation, spaces for alignment";
-    tab_spaces: usize, 4, true, "Number of spaces per tab";
-    newline_style: NewlineStyle, NewlineStyle::Auto, true, "Unix or Windows line endings";
-    indent_style: IndentStyle, IndentStyle::Block, false, "How do we indent expressions or items";
+    max_width: MaxWidth, true, "Maximum width of each line";
+    hard_tabs: HardTabs, true, "Use tab characters for indentation, spaces for alignment";
+    tab_spaces: TabSpaces, true, "Number of spaces per tab";
+    newline_style: NewlineStyleConfig, true, "Unix or Windows line endings";
+    indent_style: IndentStyleConfig, false, "How do we indent expressions or items";
 
     // Width Heuristics
-    use_small_heuristics: Heuristics, Heuristics::Default, true, "Whether to use different \
+    use_small_heuristics: UseSmallHeuristics, true, "Whether to use different \
         formatting for items and expressions if they satisfy a heuristic notion of 'small'";
-    width_heuristics: WidthHeuristics, WidthHeuristics::scaled(100), false,
-        "'small' heuristic values";
-    fn_call_width: usize, 60, true, "Maximum width of the args of a function call before \
+    width_heuristics: WidthHeuristicsConfig, false, "'small' heuristic values";
+    fn_call_width: FnCallWidth, true, "Maximum width of the args of a function call before \
         falling back to vertical formatting.";
-    attr_fn_like_width: usize, 70, true, "Maximum width of the args of a function-like \
+    attr_fn_like_width: AttrFnLikeWidth, true, "Maximum width of the args of a function-like \
         attributes before falling back to vertical formatting.";
-    struct_lit_width: usize, 18, true, "Maximum width in the body of a struct lit before \
-        falling back to vertical formatting.";
-    struct_variant_width: usize, 35, true, "Maximum width in the body of a struct variant before \
+    struct_lit_width: StructLitWidth, true, "Maximum width in the body of a struct lit before \
         falling back to vertical formatting.";
-    array_width: usize, 60, true,  "Maximum width of an array literal before falling \
+    struct_variant_width: StructVariantWidth, true, "Maximum width in the body of a struct variant \
+        before falling back to vertical formatting.";
+    array_width: ArrayWidth, true,  "Maximum width of an array literal before falling \
         back to vertical formatting.";
-    chain_width: usize, 60, true, "Maximum length of a chain to fit on a single line.";
-    single_line_if_else_max_width: usize, 50, true, "Maximum line length for single line if-else \
-        expressions. A value of zero means always break if-else expressions.";
-    single_line_let_else_max_width: usize, 50, true, "Maximum line length for single line \
-        let-else statements. A value of zero means always format the divergent `else` block \
-        over multiple lines.";
+    chain_width: ChainWidth, true, "Maximum length of a chain to fit on a single line.";
+    single_line_if_else_max_width: SingleLineIfElseMaxWidth, true, "Maximum line length for single \
+        line if-else expressions. A value of zero means always break if-else expressions.";
+    single_line_let_else_max_width: SingleLineLetElseMaxWidth, true, "Maximum line length for \
+        single line let-else statements. A value of zero means always format the divergent `else` \
+        block over multiple lines.";
 
     // Comments. macros, and strings
-    wrap_comments: bool, false, false, "Break comments to fit on the line";
-    format_code_in_doc_comments: bool, false, false, "Format the code snippet in doc comments.";
-    doc_comment_code_block_width: usize, 100, false, "Maximum width for code snippets in doc \
-        comments. No effect unless format_code_in_doc_comments = true";
-    comment_width: usize, 80, false,
+    wrap_comments: WrapComments, false, "Break comments to fit on the line";
+    format_code_in_doc_comments: FormatCodeInDocComments, false, "Format the code snippet in \
+        doc comments.";
+    doc_comment_code_block_width: DocCommentCodeBlockWidth, false, "Maximum width for code \
+        snippets in doc comments. No effect unless format_code_in_doc_comments = true";
+    comment_width: CommentWidth, false,
         "Maximum length of comments. No effect unless wrap_comments = true";
-    normalize_comments: bool, false, false, "Convert /* */ comments to // comments where possible";
-    normalize_doc_attributes: bool, false, false, "Normalize doc attributes as doc comments";
-    format_strings: bool, false, false, "Format string literals where necessary";
-    format_macro_matchers: bool, false, false,
+    normalize_comments: NormalizeComments, false, "Convert /* */ comments to // comments where \
+        possible";
+    normalize_doc_attributes: NormalizeDocAttributes, false, "Normalize doc attributes as doc \
+        comments";
+    format_strings: FormatStrings, false, "Format string literals where necessary";
+    format_macro_matchers: FormatMacroMatchers, false,
         "Format the metavariable matching patterns in macros";
-    format_macro_bodies: bool, true, false, "Format the bodies of declarative macro definitions";
-    skip_macro_invocations: MacroSelectors, MacroSelectors::default(), false,
+    format_macro_bodies: FormatMacroBodies, false,
+        "Format the bodies of declarative macro definitions";
+    skip_macro_invocations: SkipMacroInvocations, false,
         "Skip formatting the bodies of macros invoked with the following names.";
-    hex_literal_case: HexLiteralCase, HexLiteralCase::Preserve, false,
-        "Format hexadecimal integer literals";
+    hex_literal_case: HexLiteralCaseConfig, false, "Format hexadecimal integer literals";
 
     // Single line expressions and items
-    empty_item_single_line: bool, true, false,
+    empty_item_single_line: EmptyItemSingleLine, false,
         "Put empty-body functions and impls on a single line";
-    struct_lit_single_line: bool, true, false,
+    struct_lit_single_line: StructLitSingleLine, false,
         "Put small struct literals on a single line";
-    fn_single_line: bool, false, false, "Put single-expression functions on a single line";
-    where_single_line: bool, false, false, "Force where-clauses to be on a single line";
+    fn_single_line: FnSingleLine, false, "Put single-expression functions on a single line";
+    where_single_line: WhereSingleLine, false, "Force where-clauses to be on a single line";
 
     // Imports
-    imports_indent: IndentStyle, IndentStyle::Block, false, "Indent of imports";
-    imports_layout: ListTactic, ListTactic::Mixed, false, "Item layout inside a import block";
-    imports_granularity: ImportGranularity, ImportGranularity::Preserve, false,
+    imports_indent: ImportsIndent, false, "Indent of imports";
+    imports_layout: ImportsLayout, false, "Item layout inside a import block";
+    imports_granularity: ImportsGranularityConfig, false,
         "Merge or split imports to the provided granularity";
-    group_imports: GroupImportsTactic, GroupImportsTactic::Preserve, false,
+    group_imports: GroupImportsTacticConfig, false,
         "Controls the strategy for how imports are grouped together";
-    merge_imports: bool, false, false, "(deprecated: use imports_granularity instead)";
+    merge_imports: MergeImports, false, "(deprecated: use imports_granularity instead)";
 
     // Ordering
-    reorder_imports: bool, true, true, "Reorder import and extern crate statements alphabetically";
-    reorder_modules: bool, true, true, "Reorder module statements alphabetically in group";
-    reorder_impl_items: bool, false, false, "Reorder impl items";
+    reorder_imports: ReorderImports, true, "Reorder import and extern crate statements \
+        alphabetically";
+    reorder_modules: ReorderModules, true, "Reorder module statements alphabetically in group";
+    reorder_impl_items: ReorderImplItems, false, "Reorder impl items";
 
     // Spaces around punctuation
-    type_punctuation_density: TypeDensity, TypeDensity::Wide, false,
+    type_punctuation_density: TypePunctuationDensity, false,
         "Determines if '+' or '=' are wrapped in spaces in the punctuation of types";
-    space_before_colon: bool, false, false, "Leave a space before the colon";
-    space_after_colon: bool, true, false, "Leave a space after the colon";
-    spaces_around_ranges: bool, false, false, "Put spaces around the  .. and ..= range operators";
-    binop_separator: SeparatorPlace, SeparatorPlace::Front, false,
+    space_before_colon: SpaceBeforeColon, false, "Leave a space before the colon";
+    space_after_colon: SpaceAfterColon, false, "Leave a space after the colon";
+    spaces_around_ranges: SpacesAroundRanges, false, "Put spaces around the  .. and ..= range \
+        operators";
+    binop_separator: BinopSeparator, false,
         "Where to put a binary operator when a binary expression goes multiline";
 
     // Misc.
-    remove_nested_parens: bool, true, true, "Remove nested parens";
-    combine_control_expr: bool, true, false, "Combine control expressions with function calls";
-    short_array_element_width_threshold: usize, 10, true,
+    remove_nested_parens: RemoveNestedParens, true, "Remove nested parens";
+    combine_control_expr: CombineControlExpr, false, "Combine control expressions with function \
+        calls";
+    short_array_element_width_threshold: ShortArrayElementWidthThreshold, true,
         "Width threshold for an array element to be considered short";
-    overflow_delimited_expr: bool, false, false,
+    overflow_delimited_expr: OverflowDelimitedExpr, false,
         "Allow trailing bracket/brace delimited expressions to overflow";
-    struct_field_align_threshold: usize, 0, false,
+    struct_field_align_threshold: StructFieldAlignThreshold, false,
         "Align struct fields if their diffs fits within threshold";
-    enum_discrim_align_threshold: usize, 0, false,
+    enum_discrim_align_threshold: EnumDiscrimAlignThreshold, false,
         "Align enum variants discrims, if their diffs fit within threshold";
-    match_arm_blocks: bool, true, false, "Wrap the body of arms in blocks when it does not fit on \
-        the same line with the pattern of arms";
-    match_arm_leading_pipes: MatchArmLeadingPipe, MatchArmLeadingPipe::Never, true,
+    match_arm_blocks: MatchArmBlocks, false, "Wrap the body of arms in blocks when it does not fit \
+        on the same line with the pattern of arms";
+    match_arm_leading_pipes: MatchArmLeadingPipeConfig, true,
         "Determines whether leading pipes are emitted on match arms";
-    force_multiline_blocks: bool, false, false,
+    force_multiline_blocks: ForceMultilineBlocks, false,
         "Force multiline closure bodies and match arms to be wrapped in a block";
-    fn_args_layout: Density, Density::Tall, true,
+    fn_args_layout: FnArgsLayout, true,
         "(deprecated: use fn_params_layout instead)";
-    fn_params_layout: Density, Density::Tall, true,
+    fn_params_layout: FnParamsLayout, true,
         "Control the layout of parameters in function signatures.";
-    brace_style: BraceStyle, BraceStyle::SameLineWhere, false, "Brace style for items";
-    control_brace_style: ControlBraceStyle, ControlBraceStyle::AlwaysSameLine, false,
+    brace_style: BraceStyleConfig, false, "Brace style for items";
+    control_brace_style: ControlBraceStyleConfig, false,
         "Brace style for control flow constructs";
-    trailing_semicolon: bool, true, false,
+    trailing_semicolon: TrailingSemicolon, false,
         "Add trailing semicolon after break, continue and return";
-    trailing_comma: SeparatorTactic, SeparatorTactic::Vertical, false,
+    trailing_comma: TrailingComma, false,
         "How to handle trailing commas for lists";
-    match_block_trailing_comma: bool, false, true,
+    match_block_trailing_comma: MatchBlockTrailingComma, true,
         "Put a trailing comma after a block based match arm (non-block arms are not affected)";
-    blank_lines_upper_bound: usize, 1, false,
+    blank_lines_upper_bound: BlankLinesUpperBound, false,
         "Maximum number of blank lines which can be put between items";
-    blank_lines_lower_bound: usize, 0, false,
+    blank_lines_lower_bound: BlankLinesLowerBound, false,
         "Minimum number of blank lines which must be put between items";
-    edition: Edition, Edition::Edition2015, true, "The edition of the parser (RFC 2052)";
-    version: Version, Version::One, false, "Version of formatting rules";
-    inline_attribute_width: usize, 0, false,
+    edition: EditionConfig, true, "The edition of the parser (RFC 2052)";
+    style_edition: StyleEditionConfig, false, "The edition of the Style Guide (RFC 3338)";
+    version: VersionConfig, false, "Version of formatting rules";
+    inline_attribute_width: InlineAttributeWidth, false,
         "Write an item and its attribute on the same line \
         if their combined width is below a threshold";
-    format_generated_files: bool, true, false, "Format generated files";
-    generated_marker_line_search_limit: usize, 5, false, "Number of lines to check for a \
-        `@generated` marker when `format_generated_files` is enabled";
+    format_generated_files: FormatGeneratedFiles, false, "Format generated files";
+    generated_marker_line_search_limit: GeneratedMarkerLineSearchLimit, false, "Number of lines to \
+        check for a `@generated` marker when `format_generated_files` is enabled";
 
     // Options that can change the source code beyond whitespace/blocks (somewhat linty things)
-    merge_derives: bool, true, true, "Merge multiple `#[derive(...)]` into a single one";
-    use_try_shorthand: bool, false, true, "Replace uses of the try! macro by the ? shorthand";
-    use_field_init_shorthand: bool, false, true, "Use field initialization shorthand if possible";
-    force_explicit_abi: bool, true, true, "Always print the abi for extern items";
-    condense_wildcard_suffixes: bool, false, false, "Replace strings of _ wildcards by a single .. \
-                                                     in tuple patterns";
+    merge_derives: MergeDerives, true, "Merge multiple `#[derive(...)]` into a single one";
+    use_try_shorthand: UseTryShorthand, true, "Replace uses of the try! macro by the ? shorthand";
+    use_field_init_shorthand: UseFieldInitShorthand, true, "Use field initialization shorthand if \
+        possible";
+    force_explicit_abi: ForceExplicitAbi, true, "Always print the abi for extern items";
+    condense_wildcard_suffixes: CondenseWildcardSuffixes, false, "Replace strings of _ wildcards \
+        by a single .. in tuple patterns";
 
     // Control options (changes the operation of rustfmt, rather than the formatting)
-    color: Color, Color::Auto, false,
+    color: ColorConfig, false,
         "What Color option to use when none is supplied: Always, Never, Auto";
-    required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false,
+    required_version: RequiredVersion, false,
         "Require a specific version of rustfmt";
-    unstable_features: bool, false, false,
+    unstable_features: UnstableFeatures, false,
             "Enables unstable features. Only available on nightly channel";
-    disable_all_formatting: bool, false, true, "Don't reformat anything";
-    skip_children: bool, false, false, "Don't reformat out of line modules";
-    hide_parse_errors: bool, false, false, "(deprecated: use show_parse_errors instead)";
-    show_parse_errors: bool, true, false, "Show errors from the parser (unstable)";
-    error_on_line_overflow: bool, false, false, "Error if unable to get all lines within max_width";
-    error_on_unformatted: bool, false, false,
+    disable_all_formatting: DisableAllFormatting, true, "Don't reformat anything";
+    skip_children: SkipChildren, false, "Don't reformat out of line modules";
+    hide_parse_errors: HideParseErrors, false, "Hide errors from the parser";
+    show_parse_errors: ShowParseErrors, false, "Show errors from the parser (unstable)";
+    error_on_line_overflow: ErrorOnLineOverflow, false, "Error if unable to get all lines within \
+        max_width";
+    error_on_unformatted: ErrorOnUnformatted, false,
         "Error if unable to get comments or string literals within max_width, \
          or they are left with trailing whitespaces";
-    ignore: IgnoreList, IgnoreList::default(), false,
+    ignore: Ignore, false,
         "Skip formatting the specified files and directories";
 
     // Not user-facing
-    verbose: Verbosity, Verbosity::Normal, false, "How much to information to emit to the user";
-    file_lines: FileLines, FileLines::all(), false,
+    verbose: Verbose, false, "How much to information to emit to the user";
+    file_lines: FileLinesConfig, false,
         "Lines to format; this is not supported in rustfmt.toml, and can only be specified \
          via the --file-lines option";
-    emit_mode: EmitMode, EmitMode::Files, false,
+    emit_mode: EmitModeConfig, false,
         "What emit Mode to use when none is supplied";
-    make_backup: bool, false, false, "Backup changed files";
-    print_misformatted_file_names: bool, false, true,
+    make_backup: MakeBackup, false, "Backup changed files";
+    print_misformatted_file_names: PrintMisformattedFileNames, true,
         "Prints the names of mismatched files that were formatted. Prints the names of \
          files that would be formatted when used with `--check` mode. ";
 }
@@ -211,9 +217,48 @@ impl PartialConfig {
 
         ::toml::to_string(&cloned).map_err(ToTomlError)
     }
+
+    pub(super) fn to_parsed_config(
+        self,
+        style_edition_override: Option<StyleEdition>,
+        edition_override: Option<Edition>,
+        version_override: Option<Version>,
+        dir: &Path,
+    ) -> Config {
+        Config::default_for_possible_style_edition(
+            style_edition_override.or(self.style_edition),
+            edition_override.or(self.edition),
+            version_override.or(self.version),
+        )
+        .fill_from_parsed_config(self, dir)
+    }
 }
 
 impl Config {
+    pub fn default_for_possible_style_edition(
+        style_edition: Option<StyleEdition>,
+        edition: Option<Edition>,
+        version: Option<Version>,
+    ) -> Config {
+        // Ensures the configuration defaults associated with Style Editions
+        // follow the precedence set in
+        // https://rust-lang.github.io/rfcs/3338-style-evolution.html
+        // 'version' is a legacy alias for 'style_edition' that we'll support
+        // for some period of time
+        // FIXME(calebcartwright) - remove 'version' at some point
+        match (style_edition, version, edition) {
+            (Some(se), _, _) => Self::default_with_style_edition(se),
+            (None, Some(Version::Two), _) => {
+                Self::default_with_style_edition(StyleEdition::Edition2024)
+            }
+            (None, Some(Version::One), _) => {
+                Self::default_with_style_edition(StyleEdition::Edition2015)
+            }
+            (None, None, Some(e)) => Self::default_with_style_edition(e.into()),
+            (None, None, None) => Config::default(),
+        }
+    }
+
     pub(crate) fn version_meets_requirement(&self) -> bool {
         if self.was_set().required_version() {
             let version = env!("CARGO_PKG_VERSION");
@@ -237,11 +282,16 @@ impl Config {
     ///
     /// Returns a `Config` if the config could be read and parsed from
     /// the file, otherwise errors.
-    pub(super) fn from_toml_path(file_path: &Path) -> Result<Config, Error> {
+    pub(super) fn from_toml_path(
+        file_path: &Path,
+        edition: Option<Edition>,
+        style_edition: Option<StyleEdition>,
+        version: Option<Version>,
+    ) -> Result<Config, Error> {
         let mut file = File::open(&file_path)?;
         let mut toml = String::new();
         file.read_to_string(&mut toml)?;
-        Config::from_toml(&toml, file_path.parent().unwrap())
+        Config::from_toml_for_style_edition(&toml, file_path, edition, style_edition, version)
             .map_err(|err| Error::new(ErrorKind::InvalidData, err))
     }
 
@@ -254,9 +304,14 @@ impl Config {
     ///
     /// Returns the `Config` to use, and the path of the project file if there was
     /// one.
-    pub(super) fn from_resolved_toml_path(dir: &Path) -> Result<(Config, Option<PathBuf>), Error> {
+    pub(super) fn from_resolved_toml_path(
+        dir: &Path,
+        edition: Option<Edition>,
+        style_edition: Option<StyleEdition>,
+        version: Option<Version>,
+    ) -> Result<(Config, Option<PathBuf>), Error> {
         /// Try to find a project file in the given directory and its parents.
-        /// Returns the path of a the nearest project file if one exists,
+        /// Returns the path of the nearest project file if one exists,
         /// or `None` if no project file was found.
         fn resolve_project_file(dir: &Path) -> Result<Option<PathBuf>, Error> {
             let mut current = if dir.is_relative() {
@@ -299,12 +354,27 @@ impl Config {
         }
 
         match resolve_project_file(dir)? {
-            None => Ok((Config::default(), None)),
-            Some(path) => Config::from_toml_path(&path).map(|config| (config, Some(path))),
+            None => Ok((
+                Config::default_for_possible_style_edition(style_edition, edition, version),
+                None,
+            )),
+            Some(path) => Config::from_toml_path(&path, edition, style_edition, version)
+                .map(|config| (config, Some(path))),
         }
     }
 
-    pub(crate) fn from_toml(toml: &str, dir: &Path) -> Result<Config, String> {
+    #[allow(dead_code)]
+    pub(super) fn from_toml(toml: &str, file_path: &Path) -> Result<Config, String> {
+        Self::from_toml_for_style_edition(toml, file_path, None, None, None)
+    }
+
+    pub(crate) fn from_toml_for_style_edition(
+        toml: &str,
+        file_path: &Path,
+        edition: Option<Edition>,
+        style_edition: Option<StyleEdition>,
+        version: Option<Version>,
+    ) -> Result<Config, String> {
         let parsed: ::toml::Value = toml
             .parse()
             .map_err(|e| format!("Could not parse TOML: {}", e))?;
@@ -318,18 +388,25 @@ impl Config {
                 err.push_str(msg)
             }
         }
-        match parsed.try_into() {
+
+        match parsed.try_into::<PartialConfig>() {
             Ok(parsed_config) => {
                 if !err.is_empty() {
                     eprint!("{err}");
                 }
-                Ok(Config::default().fill_from_parsed_config(parsed_config, dir))
+                let dir = file_path.parent().ok_or_else(|| {
+                    format!("failed to get parent directory for {}", file_path.display())
+                })?;
+
+                Ok(parsed_config.to_parsed_config(style_edition, edition, version, dir))
             }
             Err(e) => {
-                err.push_str("Error: Decoding config file failed:\n");
-                err.push_str(format!("{e}\n").as_str());
-                err.push_str("Please check your config file.");
-                Err(err)
+                let err_msg = format!(
+                    "The file `{}` failed to parse.\nError details: {e}",
+                    file_path.display()
+                );
+                err.push_str(&err_msg);
+                Err(err_msg)
             }
         }
     }
@@ -341,17 +418,26 @@ pub fn load_config<O: CliOptions>(
     file_path: Option<&Path>,
     options: Option<O>,
 ) -> Result<(Config, Option<PathBuf>), Error> {
-    let over_ride = match options {
-        Some(ref opts) => config_path(opts)?,
-        None => None,
+    let (over_ride, edition, style_edition, version) = match options {
+        Some(ref opts) => (
+            config_path(opts)?,
+            opts.edition(),
+            opts.style_edition(),
+            opts.version(),
+        ),
+        None => (None, None, None, None),
     };
 
     let result = if let Some(over_ride) = over_ride {
-        Config::from_toml_path(over_ride.as_ref()).map(|p| (p, Some(over_ride.to_owned())))
+        Config::from_toml_path(over_ride.as_ref(), edition, style_edition, version)
+            .map(|p| (p, Some(over_ride.to_owned())))
     } else if let Some(file_path) = file_path {
-        Config::from_resolved_toml_path(file_path)
+        Config::from_resolved_toml_path(file_path, edition, style_edition, version)
     } else {
-        Ok((Config::default(), None))
+        Ok((
+            Config::default_for_possible_style_edition(style_edition, edition, version),
+            None,
+        ))
     };
 
     result.map(|(mut c, p)| {
@@ -362,7 +448,7 @@ pub fn load_config<O: CliOptions>(
     })
 }
 
-// Check for the presence of known config file names (`rustfmt.toml, `.rustfmt.toml`) in `dir`
+// Check for the presence of known config file names (`rustfmt.toml`, `.rustfmt.toml`) in `dir`
 //
 // Return the path if a config file exists, empty if no file exists, and Error for IO errors
 fn get_toml_path(dir: &Path) -> Result<Option<PathBuf>, Error> {
@@ -372,7 +458,7 @@ fn get_toml_path(dir: &Path) -> Result<Option<PathBuf>, Error> {
         match fs::metadata(&config_file) {
             // Only return if it's a file to handle the unlikely situation of a directory named
             // `rustfmt.toml`.
-            Ok(ref md) if md.is_file() => return Ok(Some(config_file)),
+            Ok(ref md) if md.is_file() => return Ok(Some(config_file.canonicalize()?)),
             // Return the error if it's something other than `NotFound`; otherwise we didn't
             // find the project file yet, and continue searching.
             Err(e) => {
@@ -411,7 +497,11 @@ fn config_path(options: &dyn CliOptions) -> Result<Option<PathBuf>, Error> {
                 config_path_not_found(path.to_str().unwrap())
             }
         }
-        path => Ok(path.map(ToOwned::to_owned)),
+        Some(path) => Ok(Some(
+            // Canonicalize only after checking above that the `path.exists()`.
+            path.canonicalize()?,
+        )),
+        None => Ok(None),
     }
 }
 
@@ -420,12 +510,13 @@ mod test {
     use super::*;
     use std::str;
 
-    use crate::config::macro_names::MacroName;
+    use crate::config::macro_names::{MacroName, MacroSelectors};
     use rustfmt_config_proc_macro::{nightly_only_test, stable_only_test};
 
     #[allow(dead_code)]
     mod mock {
         use super::super::*;
+        use crate::config_option_with_style_edition_default;
         use rustfmt_config_proc_macro::config_type;
 
         #[config_type]
@@ -436,66 +527,69 @@ mod test {
             V3,
         }
 
+        config_option_with_style_edition_default!(
+            StableOption, bool, _ => false;
+            UnstableOption, bool, _ => false;
+            PartiallyUnstable, PartiallyUnstableOption, _ => PartiallyUnstableOption::V1;
+        );
+
         create_config! {
             // Options that are used by the generated functions
-            max_width: usize, 100, true, "Maximum width of each line";
-            required_version: String, env!("CARGO_PKG_VERSION").to_owned(), false,
-                "Require a specific version of rustfmt.";
-            ignore: IgnoreList, IgnoreList::default(), false,
-                "Skip formatting the specified files and directories.";
-            verbose: Verbosity, Verbosity::Normal, false,
-                "How much to information to emit to the user";
-            file_lines: FileLines, FileLines::all(), false,
+            max_width: MaxWidth, true, "Maximum width of each line";
+            required_version: RequiredVersion, false, "Require a specific version of rustfmt.";
+            ignore: Ignore, false, "Skip formatting the specified files and directories.";
+            verbose: Verbose, false, "How much to information to emit to the user";
+            file_lines: FileLinesConfig, false,
                 "Lines to format; this is not supported in rustfmt.toml, and can only be specified \
                     via the --file-lines option";
 
             // merge_imports deprecation
-            imports_granularity: ImportGranularity, ImportGranularity::Preserve, false,
-                "Merge imports";
-            merge_imports: bool, false, false, "(deprecated: use imports_granularity instead)";
+            imports_granularity: ImportsGranularityConfig, false, "Merge imports";
+            merge_imports: MergeImports, false, "(deprecated: use imports_granularity instead)";
 
             // fn_args_layout renamed to fn_params_layout
-            fn_args_layout: Density, Density::Tall, true,
-                "(deprecated: use fn_params_layout instead)";
-            fn_params_layout: Density, Density::Tall, true,
+            fn_args_layout: FnArgsLayout, true, "(deprecated: use fn_params_layout instead)";
+            fn_params_layout: FnParamsLayout, true,
                 "Control the layout of parameters in a function signatures.";
 
             // hide_parse_errors renamed to show_parse_errors
-            hide_parse_errors: bool, false, false,
+            hide_parse_errors: HideParseErrors, false,
                 "(deprecated: use show_parse_errors instead)";
-            show_parse_errors: bool, true, false,
+            show_parse_errors: ShowParseErrors, false,
                 "Show errors from the parser (unstable)";
 
 
             // Width Heuristics
-            use_small_heuristics: Heuristics, Heuristics::Default, true,
+            use_small_heuristics: UseSmallHeuristics, true,
                 "Whether to use different formatting for items and \
                  expressions if they satisfy a heuristic notion of 'small'.";
-            width_heuristics: WidthHeuristics, WidthHeuristics::scaled(100), false,
-                "'small' heuristic values";
+            width_heuristics: WidthHeuristicsConfig, false, "'small' heuristic values";
 
-            fn_call_width: usize, 60, true, "Maximum width of the args of a function call before \
+            fn_call_width: FnCallWidth, true, "Maximum width of the args of a function call before \
                 falling back to vertical formatting.";
-            attr_fn_like_width: usize, 70, true, "Maximum width of the args of a function-like \
-                attributes before falling back to vertical formatting.";
-            struct_lit_width: usize, 18, true, "Maximum width in the body of a struct lit before \
-                falling back to vertical formatting.";
-            struct_variant_width: usize, 35, true, "Maximum width in the body of a struct \
+            attr_fn_like_width: AttrFnLikeWidth, true, "Maximum width of the args of a \
+                function-like attributes before falling back to vertical formatting.";
+            struct_lit_width: StructLitWidth, true, "Maximum width in the body of a struct lit \
+                before falling back to vertical formatting.";
+            struct_variant_width: StructVariantWidth, true, "Maximum width in the body of a struct \
                 variant before falling back to vertical formatting.";
-            array_width: usize, 60, true,  "Maximum width of an array literal before falling \
+            array_width: ArrayWidth, true,  "Maximum width of an array literal before falling \
                 back to vertical formatting.";
-            chain_width: usize, 60, true, "Maximum length of a chain to fit on a single line.";
-            single_line_if_else_max_width: usize, 50, true, "Maximum line length for single \
-                line if-else expressions. A value of zero means always break if-else expressions.";
-            single_line_let_else_max_width: usize, 50, false, "Maximum line length for single \
-                line let-else statements. A value of zero means always format the divergent \
-                `else` block over multiple lines.";
+            chain_width: ChainWidth, true, "Maximum length of a chain to fit on a single line.";
+            single_line_if_else_max_width: SingleLineIfElseMaxWidth, true, "Maximum line length \
+                for single line if-else expressions. A value of zero means always break if-else \
+                expressions.";
+            single_line_let_else_max_width: SingleLineLetElseMaxWidth, false, "Maximum line length \
+                for single line let-else statements. A value of zero means always format the \
+                divergent `else` block over multiple lines.";
 
             // Options that are used by the tests
-            stable_option: bool, false, true, "A stable option";
-            unstable_option: bool, false, false, "An unstable option";
-            partially_unstable_option: PartiallyUnstableOption, PartiallyUnstableOption::V1, true,
-                "A partially unstable option";
+            stable_option: StableOption, true, "A stable option";
+            unstable_option: UnstableOption, false, "An unstable option";
+            partially_unstable_option: PartiallyUnstable, true, "A partially unstable option";
+            edition: EditionConfig, true, "blah";
+            style_edition: StyleEditionConfig, true, "blah";
+            version: VersionConfig, false, "blah blah"
         }
 
         #[cfg(test)]
@@ -580,7 +674,7 @@ mod test {
 
     #[test]
     fn test_was_set() {
-        let config = Config::from_toml("hard_tabs = true", Path::new("")).unwrap();
+        let config = Config::from_toml("hard_tabs = true", Path::new("./rustfmt.toml")).unwrap();
 
         assert_eq!(config.was_set().hard_tabs(), true);
         assert_eq!(config.was_set().verbose(), false);
@@ -679,6 +773,7 @@ match_block_trailing_comma = false
 blank_lines_upper_bound = 1
 blank_lines_lower_bound = 0
 edition = "2015"
+style_edition = "2015"
 version = "One"
 inline_attribute_width = 0
 format_generated_files = true
@@ -706,6 +801,114 @@ make_backup = false
         assert_eq!(&toml, &default_config);
     }
 
+    #[test]
+    fn test_dump_style_edition_2024_config() {
+        let edition_2024_config = format!(
+            r#"max_width = 100
+hard_tabs = false
+tab_spaces = 4
+newline_style = "Auto"
+indent_style = "Block"
+use_small_heuristics = "Default"
+fn_call_width = 60
+attr_fn_like_width = 70
+struct_lit_width = 18
+struct_variant_width = 35
+array_width = 60
+chain_width = 60
+single_line_if_else_max_width = 50
+single_line_let_else_max_width = 50
+wrap_comments = false
+format_code_in_doc_comments = false
+doc_comment_code_block_width = 100
+comment_width = 80
+normalize_comments = false
+normalize_doc_attributes = false
+format_strings = false
+format_macro_matchers = false
+format_macro_bodies = true
+skip_macro_invocations = []
+hex_literal_case = "Preserve"
+empty_item_single_line = true
+struct_lit_single_line = true
+fn_single_line = false
+where_single_line = false
+imports_indent = "Block"
+imports_layout = "Mixed"
+imports_granularity = "Preserve"
+group_imports = "Preserve"
+reorder_imports = true
+reorder_modules = true
+reorder_impl_items = false
+type_punctuation_density = "Wide"
+space_before_colon = false
+space_after_colon = true
+spaces_around_ranges = false
+binop_separator = "Front"
+remove_nested_parens = true
+combine_control_expr = true
+short_array_element_width_threshold = 10
+overflow_delimited_expr = true
+struct_field_align_threshold = 0
+enum_discrim_align_threshold = 0
+match_arm_blocks = true
+match_arm_leading_pipes = "Never"
+force_multiline_blocks = false
+fn_params_layout = "Tall"
+brace_style = "SameLineWhere"
+control_brace_style = "AlwaysSameLine"
+trailing_semicolon = true
+trailing_comma = "Vertical"
+match_block_trailing_comma = false
+blank_lines_upper_bound = 1
+blank_lines_lower_bound = 0
+edition = "2015"
+style_edition = "2024"
+version = "Two"
+inline_attribute_width = 0
+format_generated_files = true
+generated_marker_line_search_limit = 5
+merge_derives = true
+use_try_shorthand = false
+use_field_init_shorthand = false
+force_explicit_abi = true
+condense_wildcard_suffixes = false
+color = "Auto"
+required_version = "{}"
+unstable_features = false
+disable_all_formatting = false
+skip_children = false
+show_parse_errors = true
+error_on_line_overflow = false
+error_on_unformatted = false
+ignore = []
+emit_mode = "Files"
+make_backup = false
+"#,
+            env!("CARGO_PKG_VERSION")
+        );
+        let toml = Config::default_with_style_edition(StyleEdition::Edition2024)
+            .all_options()
+            .to_toml()
+            .unwrap();
+        assert_eq!(&toml, &edition_2024_config);
+    }
+
+    #[test]
+    fn test_editions_2015_2018_2021_identical() {
+        let get_edition_toml = |style_edition: StyleEdition| {
+            Config::default_with_style_edition(style_edition)
+                .all_options()
+                .to_toml()
+                .unwrap()
+        };
+        let edition2015 = get_edition_toml(StyleEdition::Edition2015);
+        let edition2018 = get_edition_toml(StyleEdition::Edition2018);
+        let edition2021 = get_edition_toml(StyleEdition::Edition2021);
+        assert_eq!(edition2015, edition2018);
+        assert_eq!(edition2018, edition2021);
+    }
+
     #[stable_only_test]
     #[test]
     fn test_as_not_nightly_channel() {
@@ -730,11 +933,26 @@ make_backup = false
     #[nightly_only_test]
     #[test]
     fn test_unstable_from_toml() {
-        let config = Config::from_toml("unstable_features = true", Path::new("")).unwrap();
+        let config =
+            Config::from_toml("unstable_features = true", Path::new("./rustfmt.toml")).unwrap();
         assert_eq!(config.was_set().unstable_features(), true);
         assert_eq!(config.unstable_features(), true);
     }
 
+    #[test]
+    fn test_set_cli() {
+        let mut config = Config::default();
+        assert_eq!(config.was_set().edition(), false);
+        assert_eq!(config.was_set_cli().edition(), false);
+        config.set().edition(Edition::Edition2021);
+        assert_eq!(config.was_set().edition(), false);
+        assert_eq!(config.was_set_cli().edition(), false);
+        config.set_cli().edition(Edition::Edition2021);
+        assert_eq!(config.was_set().edition(), false);
+        assert_eq!(config.was_set_cli().edition(), true);
+        assert_eq!(config.was_set_cli().emit_mode(), false);
+    }
+
     #[cfg(test)]
     mod deprecated_option_merge_imports {
         use super::*;
@@ -746,7 +964,7 @@ make_backup = false
                 unstable_features = true
                 merge_imports = true
             "#;
-            let config = Config::from_toml(toml, Path::new("")).unwrap();
+            let config = Config::from_toml(toml, Path::new("./rustfmt.toml")).unwrap();
             assert_eq!(config.imports_granularity(), ImportGranularity::Crate);
         }
 
@@ -758,7 +976,7 @@ make_backup = false
                 merge_imports = true
                 imports_granularity = "Preserve"
             "#;
-            let config = Config::from_toml(toml, Path::new("")).unwrap();
+            let config = Config::from_toml(toml, Path::new("./rustfmt.toml")).unwrap();
             assert_eq!(config.imports_granularity(), ImportGranularity::Preserve);
         }
 
@@ -769,7 +987,7 @@ make_backup = false
                 unstable_features = true
                 merge_imports = true
             "#;
-            let mut config = Config::from_toml(toml, Path::new("")).unwrap();
+            let mut config = Config::from_toml(toml, Path::new("./rustfmt.toml")).unwrap();
             config.override_value("imports_granularity", "Preserve");
             assert_eq!(config.imports_granularity(), ImportGranularity::Preserve);
         }
@@ -781,7 +999,7 @@ make_backup = false
                 unstable_features = true
                 imports_granularity = "Module"
             "#;
-            let mut config = Config::from_toml(toml, Path::new("")).unwrap();
+            let mut config = Config::from_toml(toml, Path::new("./rustfmt.toml")).unwrap();
             config.override_value("merge_imports", "true");
             // no effect: the new option always takes precedence
             assert_eq!(config.imports_granularity(), ImportGranularity::Module);
@@ -798,7 +1016,7 @@ make_backup = false
                 use_small_heuristics = "Default"
                 max_width = 200
             "#;
-            let config = Config::from_toml(toml, Path::new("")).unwrap();
+            let config = Config::from_toml(toml, Path::new("./rustfmt.toml")).unwrap();
             assert_eq!(config.array_width(), 120);
             assert_eq!(config.attr_fn_like_width(), 140);
             assert_eq!(config.chain_width(), 120);
@@ -814,7 +1032,7 @@ make_backup = false
                 use_small_heuristics = "Max"
                 max_width = 120
             "#;
-            let config = Config::from_toml(toml, Path::new("")).unwrap();
+            let config = Config::from_toml(toml, Path::new("./rustfmt.toml")).unwrap();
             assert_eq!(config.array_width(), 120);
             assert_eq!(config.attr_fn_like_width(), 120);
             assert_eq!(config.chain_width(), 120);
@@ -830,11 +1048,11 @@ make_backup = false
                 use_small_heuristics = "Off"
                 max_width = 100
             "#;
-            let config = Config::from_toml(toml, Path::new("")).unwrap();
-            assert_eq!(config.array_width(), usize::max_value());
-            assert_eq!(config.attr_fn_like_width(), usize::max_value());
-            assert_eq!(config.chain_width(), usize::max_value());
-            assert_eq!(config.fn_call_width(), usize::max_value());
+            let config = Config::from_toml(toml, Path::new("./rustfmt.toml")).unwrap();
+            assert_eq!(config.array_width(), usize::MAX);
+            assert_eq!(config.attr_fn_like_width(), usize::MAX);
+            assert_eq!(config.chain_width(), usize::MAX);
+            assert_eq!(config.fn_call_width(), usize::MAX);
             assert_eq!(config.single_line_if_else_max_width(), 0);
             assert_eq!(config.struct_lit_width(), 0);
             assert_eq!(config.struct_variant_width(), 0);
@@ -852,7 +1070,7 @@ make_backup = false
                 struct_lit_width = 30
                 struct_variant_width = 34
             "#;
-            let config = Config::from_toml(toml, Path::new("")).unwrap();
+            let config = Config::from_toml(toml, Path::new("./rustfmt.toml")).unwrap();
             assert_eq!(config.array_width(), 20);
             assert_eq!(config.attr_fn_like_width(), 40);
             assert_eq!(config.chain_width(), 20);
@@ -874,7 +1092,7 @@ make_backup = false
                 struct_lit_width = 30
                 struct_variant_width = 34
             "#;
-            let config = Config::from_toml(toml, Path::new("")).unwrap();
+            let config = Config::from_toml(toml, Path::new("./rustfmt.toml")).unwrap();
             assert_eq!(config.array_width(), 20);
             assert_eq!(config.attr_fn_like_width(), 40);
             assert_eq!(config.chain_width(), 20);
@@ -896,7 +1114,7 @@ make_backup = false
                 struct_lit_width = 30
                 struct_variant_width = 34
             "#;
-            let config = Config::from_toml(toml, Path::new("")).unwrap();
+            let config = Config::from_toml(toml, Path::new("./rustfmt.toml")).unwrap();
             assert_eq!(config.array_width(), 20);
             assert_eq!(config.attr_fn_like_width(), 40);
             assert_eq!(config.chain_width(), 20);
@@ -912,7 +1130,7 @@ make_backup = false
                 max_width = 90
                 fn_call_width = 95
             "#;
-            let config = Config::from_toml(toml, Path::new("")).unwrap();
+            let config = Config::from_toml(toml, Path::new("./rustfmt.toml")).unwrap();
             assert_eq!(config.fn_call_width(), 90);
         }
 
@@ -922,7 +1140,7 @@ make_backup = false
                 max_width = 80
                 attr_fn_like_width = 90
             "#;
-            let config = Config::from_toml(toml, Path::new("")).unwrap();
+            let config = Config::from_toml(toml, Path::new("./rustfmt.toml")).unwrap();
             assert_eq!(config.attr_fn_like_width(), 80);
         }
 
@@ -932,7 +1150,7 @@ make_backup = false
                 max_width = 78
                 struct_lit_width = 90
             "#;
-            let config = Config::from_toml(toml, Path::new("")).unwrap();
+            let config = Config::from_toml(toml, Path::new("./rustfmt.toml")).unwrap();
             assert_eq!(config.struct_lit_width(), 78);
         }
 
@@ -942,7 +1160,7 @@ make_backup = false
                 max_width = 80
                 struct_variant_width = 90
             "#;
-            let config = Config::from_toml(toml, Path::new("")).unwrap();
+            let config = Config::from_toml(toml, Path::new("./rustfmt.toml")).unwrap();
             assert_eq!(config.struct_variant_width(), 80);
         }
 
@@ -952,7 +1170,7 @@ make_backup = false
                 max_width = 60
                 array_width = 80
             "#;
-            let config = Config::from_toml(toml, Path::new("")).unwrap();
+            let config = Config::from_toml(toml, Path::new("./rustfmt.toml")).unwrap();
             assert_eq!(config.array_width(), 60);
         }
 
@@ -962,7 +1180,7 @@ make_backup = false
                 max_width = 80
                 chain_width = 90
             "#;
-            let config = Config::from_toml(toml, Path::new("")).unwrap();
+            let config = Config::from_toml(toml, Path::new("./rustfmt.toml")).unwrap();
             assert_eq!(config.chain_width(), 80);
         }
 
@@ -972,7 +1190,7 @@ make_backup = false
                 max_width = 70
                 single_line_if_else_max_width = 90
             "#;
-            let config = Config::from_toml(toml, Path::new("")).unwrap();
+            let config = Config::from_toml(toml, Path::new("./rustfmt.toml")).unwrap();
             assert_eq!(config.single_line_if_else_max_width(), 70);
         }
 
diff --git a/src/tools/rustfmt/src/config/options.rs b/src/tools/rustfmt/src/config/options.rs
index 3c5c713a33a..c526b5c678f 100644
--- a/src/tools/rustfmt/src/config/options.rs
+++ b/src/tools/rustfmt/src/config/options.rs
@@ -1,6 +1,6 @@
 #![allow(unused_imports)]
 
-use std::collections::{hash_set, HashSet};
+use std::collections::{HashSet, hash_set};
 use std::fmt;
 use std::path::{Path, PathBuf};
 use std::str::FromStr;
@@ -11,8 +11,10 @@ use serde::de::{SeqAccess, Visitor};
 use serde::ser::SerializeSeq;
 use serde::{Deserialize, Deserializer, Serialize, Serializer};
 
-use crate::config::lists::*;
 use crate::config::Config;
+use crate::config::file_lines::FileLines;
+use crate::config::lists::*;
+use crate::config::macro_names::MacroSelectors;
 
 #[config_type]
 pub enum NewlineStyle {
@@ -253,12 +255,12 @@ impl WidthHeuristics {
     // Using this WidthHeuristics means we ignore heuristics.
     pub fn null() -> WidthHeuristics {
         WidthHeuristics {
-            fn_call_width: usize::max_value(),
-            attr_fn_like_width: usize::max_value(),
+            fn_call_width: usize::MAX,
+            attr_fn_like_width: usize::MAX,
             struct_lit_width: 0,
             struct_variant_width: 0,
-            array_width: usize::max_value(),
-            chain_width: usize::max_value(),
+            array_width: usize::MAX,
+            chain_width: usize::MAX,
             single_line_if_else_max_width: 0,
             single_line_let_else_max_width: 0,
         }
@@ -413,7 +415,13 @@ impl FromStr for IgnoreList {
 /// values in a config with values from the command line.
 pub trait CliOptions {
     fn apply_to(self, config: &mut Config);
+
+    /// It is ok if the returned path doesn't exist or is not canonicalized
+    /// (i.e. the callers are expected to handle such cases).
     fn config_path(&self) -> Option<&Path>;
+    fn edition(&self) -> Option<Edition>;
+    fn style_edition(&self) -> Option<StyleEdition>;
+    fn version(&self) -> Option<Version>;
 }
 
 /// The edition of the syntax and semantics of code (RFC 2052).
@@ -454,6 +462,17 @@ impl From<Edition> for rustc_span::edition::Edition {
     }
 }
 
+impl From<Edition> for StyleEdition {
+    fn from(edition: Edition) -> Self {
+        match edition {
+            Edition::Edition2015 => StyleEdition::Edition2015,
+            Edition::Edition2018 => StyleEdition::Edition2018,
+            Edition::Edition2021 => StyleEdition::Edition2021,
+            Edition::Edition2024 => StyleEdition::Edition2024,
+        }
+    }
+}
+
 impl PartialOrd for Edition {
     fn partial_cmp(&self, other: &Edition) -> Option<std::cmp::Ordering> {
         rustc_span::edition::Edition::partial_cmp(&(*self).into(), &(*other).into())
@@ -471,10 +490,11 @@ pub enum MatchArmLeadingPipe {
     Preserve,
 }
 
-/// Defines the default values for each config according to [the style guide].
-/// rustfmt output may differ between style editions.
+/// Defines the default values for each config according to the edition of the
+/// [Style Guide] as per [RFC 3338]. Rustfmt output may differ between Style editions.
 ///
-/// [the style guide]: https://doc.rust-lang.org/nightly/style-guide/
+/// [Style Guide]: https://doc.rust-lang.org/nightly/style-guide/
+/// [RFC 3338]: https://rust-lang.github.io/rfcs/3338-style-evolution.html
 #[config_type]
 pub enum StyleEdition {
     #[value = "2015"]
@@ -491,6 +511,169 @@ pub enum StyleEdition {
     Edition2021,
     #[value = "2024"]
     #[doc_hint = "2024"]
+    #[unstable_variant]
     /// [Edition 2024]().
     Edition2024,
 }
+
+impl From<StyleEdition> for rustc_span::edition::Edition {
+    fn from(edition: StyleEdition) -> Self {
+        match edition {
+            StyleEdition::Edition2015 => Self::Edition2015,
+            StyleEdition::Edition2018 => Self::Edition2018,
+            StyleEdition::Edition2021 => Self::Edition2021,
+            StyleEdition::Edition2024 => Self::Edition2024,
+        }
+    }
+}
+
+impl PartialOrd for StyleEdition {
+    fn partial_cmp(&self, other: &StyleEdition) -> Option<std::cmp::Ordering> {
+        rustc_span::edition::Edition::partial_cmp(&(*self).into(), &(*other).into())
+    }
+}
+
+/// Defines unit structs to implement `StyleEditionDefault` for.
+#[macro_export]
+macro_rules! config_option_with_style_edition_default {
+    ($name:ident, $config_ty:ty, _ => $default:expr) => {
+        #[allow(unreachable_pub)]
+        pub struct $name;
+        $crate::style_edition_default!($name, $config_ty, _ => $default);
+    };
+    ($name:ident, $config_ty:ty, Edition2024 => $default_2024:expr, _ => $default_2015:expr) => {
+        pub struct $name;
+        $crate::style_edition_default!(
+            $name,
+            $config_ty,
+            Edition2024 => $default_2024,
+            _ => $default_2015
+        );
+    };
+    (
+        $($name:ident, $config_ty:ty, $(Edition2024 => $default_2024:expr,)? _ => $default:expr);*
+        $(;)*
+    ) => {
+        $(
+            config_option_with_style_edition_default!(
+                $name, $config_ty, $(Edition2024 => $default_2024,)? _ => $default
+            );
+        )*
+    };
+}
+
+// TODO(ytmimi) Some of the configuration values have a `Config` suffix, while others don't.
+// I chose to add a `Config` suffix in cases where a type for the config option was already
+// defined. For example, `NewlineStyle` and `NewlineStyleConfig`. There was some discussion
+// about using the `Config` suffix more consistently.
+config_option_with_style_edition_default!(
+    // Fundamental stuff
+    MaxWidth, usize, _ => 100;
+    HardTabs, bool, _ => false;
+    TabSpaces, usize, _ => 4;
+    NewlineStyleConfig, NewlineStyle, _ => NewlineStyle::Auto;
+    IndentStyleConfig, IndentStyle, _ => IndentStyle::Block;
+
+    // Width Heuristics
+    UseSmallHeuristics, Heuristics, _ => Heuristics::Default;
+    WidthHeuristicsConfig, WidthHeuristics, _ => WidthHeuristics::scaled(100);
+    FnCallWidth, usize, _ => 60;
+    AttrFnLikeWidth, usize, _ => 70;
+    StructLitWidth, usize, _ => 18;
+    StructVariantWidth, usize, _ => 35;
+    ArrayWidth, usize, _ => 60;
+    ChainWidth, usize, _ => 60;
+    SingleLineIfElseMaxWidth, usize, _ => 50;
+    SingleLineLetElseMaxWidth, usize, _ => 50;
+
+    // Comments. macros, and strings
+    WrapComments, bool, _ => false;
+    FormatCodeInDocComments, bool, _ => false;
+    DocCommentCodeBlockWidth, usize, _ => 100;
+    CommentWidth, usize, _ => 80;
+    NormalizeComments, bool, _ => false;
+    NormalizeDocAttributes, bool, _ => false;
+    FormatStrings, bool, _ => false;
+    FormatMacroMatchers, bool, _ => false;
+    FormatMacroBodies, bool, _ => true;
+    SkipMacroInvocations, MacroSelectors, _ => MacroSelectors::default();
+    HexLiteralCaseConfig, HexLiteralCase, _ => HexLiteralCase::Preserve;
+
+    // Single line expressions and items
+    EmptyItemSingleLine, bool, _ => true;
+    StructLitSingleLine, bool, _ => true;
+    FnSingleLine, bool, _ => false;
+    WhereSingleLine, bool, _ => false;
+
+    // Imports
+    ImportsIndent, IndentStyle, _ => IndentStyle::Block;
+    ImportsLayout, ListTactic, _ => ListTactic::Mixed;
+    ImportsGranularityConfig, ImportGranularity, _ => ImportGranularity::Preserve;
+    GroupImportsTacticConfig, GroupImportsTactic, _ => GroupImportsTactic::Preserve;
+    MergeImports, bool, _ => false;
+
+    // Ordering
+    ReorderImports, bool, _ => true;
+    ReorderModules, bool, _ => true;
+    ReorderImplItems, bool, _ => false;
+
+    // Spaces around punctuation
+    TypePunctuationDensity, TypeDensity, _ => TypeDensity::Wide;
+    SpaceBeforeColon, bool, _ => false;
+    SpaceAfterColon, bool, _ => true;
+    SpacesAroundRanges, bool, _ => false;
+    BinopSeparator, SeparatorPlace, _ => SeparatorPlace::Front;
+
+    // Misc.
+    RemoveNestedParens, bool, _ => true;
+    CombineControlExpr, bool, _ => true;
+    ShortArrayElementWidthThreshold, usize, _ => 10;
+    OverflowDelimitedExpr, bool, Edition2024 => true, _ => false;
+    StructFieldAlignThreshold, usize, _ => 0;
+    EnumDiscrimAlignThreshold, usize, _ => 0;
+    MatchArmBlocks, bool, _ => true;
+    MatchArmLeadingPipeConfig, MatchArmLeadingPipe, _ => MatchArmLeadingPipe::Never;
+    ForceMultilineBlocks, bool, _ => false;
+    FnArgsLayout, Density, _ => Density::Tall;
+    FnParamsLayout, Density, _ => Density::Tall;
+    BraceStyleConfig, BraceStyle, _ => BraceStyle::SameLineWhere;
+    ControlBraceStyleConfig, ControlBraceStyle, _ => ControlBraceStyle::AlwaysSameLine;
+    TrailingSemicolon, bool, _ => true;
+    TrailingComma, SeparatorTactic, _ => SeparatorTactic::Vertical;
+    MatchBlockTrailingComma, bool, _ => false;
+    BlankLinesUpperBound, usize, _ => 1;
+    BlankLinesLowerBound, usize, _ => 0;
+    EditionConfig, Edition, _ => Edition::Edition2015;
+    StyleEditionConfig, StyleEdition,
+        Edition2024 =>  StyleEdition::Edition2024, _ => StyleEdition::Edition2015;
+    VersionConfig, Version, Edition2024 => Version::Two, _ => Version::One;
+    InlineAttributeWidth, usize, _ => 0;
+    FormatGeneratedFiles, bool, _ => true;
+    GeneratedMarkerLineSearchLimit, usize, _ => 5;
+
+    // Options that can change the source code beyond whitespace/blocks (somewhat linty things)
+    MergeDerives, bool, _ => true;
+    UseTryShorthand, bool, _ => false;
+    UseFieldInitShorthand, bool, _ => false;
+    ForceExplicitAbi, bool, _ => true;
+    CondenseWildcardSuffixes, bool, _ => false;
+
+    // Control options (changes the operation of rustfmt, rather than the formatting)
+    ColorConfig, Color, _ => Color::Auto;
+    RequiredVersion, String, _ => env!("CARGO_PKG_VERSION").to_owned();
+    UnstableFeatures, bool, _ => false;
+    DisableAllFormatting, bool, _ => false;
+    SkipChildren, bool, _ => false;
+    HideParseErrors, bool, _ => false;
+    ShowParseErrors, bool, _ => true;
+    ErrorOnLineOverflow, bool, _ => false;
+    ErrorOnUnformatted, bool, _ => false;
+    Ignore, IgnoreList, _ => IgnoreList::default();
+
+    // Not user-facing
+    Verbose, Verbosity, _ => Verbosity::Normal;
+    FileLinesConfig, FileLines, _ => FileLines::all();
+    EmitModeConfig, EmitMode, _ => EmitMode::Files;
+    MakeBackup, bool, _ => false;
+    PrintMisformattedFileNames, bool, _ => false;
+);
diff --git a/src/tools/rustfmt/src/config/style_edition.rs b/src/tools/rustfmt/src/config/style_edition.rs
index 7b3ea3bc119..c34eca9c8e1 100644
--- a/src/tools/rustfmt/src/config/style_edition.rs
+++ b/src/tools/rustfmt/src/config/style_edition.rs
@@ -2,7 +2,7 @@ use crate::config::StyleEdition;
 
 /// Defines the default value for the given style edition
 #[allow(dead_code)]
-pub(crate) trait StyleEditionDefault {
+pub trait StyleEditionDefault {
     type ConfigType;
     fn style_edition_default(style_edition: StyleEdition) -> Self::ConfigType;
 }
diff --git a/src/tools/rustfmt/src/emitter/checkstyle.rs b/src/tools/rustfmt/src/emitter/checkstyle.rs
index 9385ae59a06..c320c16bd1d 100644
--- a/src/tools/rustfmt/src/emitter/checkstyle.rs
+++ b/src/tools/rustfmt/src/emitter/checkstyle.rs
@@ -1,6 +1,6 @@
 use self::xml::XmlEscaped;
 use super::*;
-use crate::rustfmt_diff::{make_diff, DiffLine, Mismatch};
+use crate::rustfmt_diff::{DiffLine, Mismatch, make_diff};
 
 mod xml;
 
diff --git a/src/tools/rustfmt/src/emitter/json.rs b/src/tools/rustfmt/src/emitter/json.rs
index 084f565804c..a99626f783d 100644
--- a/src/tools/rustfmt/src/emitter/json.rs
+++ b/src/tools/rustfmt/src/emitter/json.rs
@@ -1,5 +1,5 @@
 use super::*;
-use crate::rustfmt_diff::{make_diff, DiffLine, Mismatch};
+use crate::rustfmt_diff::{DiffLine, Mismatch, make_diff};
 use serde::Serialize;
 use serde_json::to_string as to_json_string;
 
diff --git a/src/tools/rustfmt/src/emitter/modified_lines.rs b/src/tools/rustfmt/src/emitter/modified_lines.rs
index 81f0a31b974..0d5124bc33e 100644
--- a/src/tools/rustfmt/src/emitter/modified_lines.rs
+++ b/src/tools/rustfmt/src/emitter/modified_lines.rs
@@ -1,5 +1,5 @@
 use super::*;
-use crate::rustfmt_diff::{make_diff, ModifiedLines};
+use crate::rustfmt_diff::{ModifiedLines, make_diff};
 
 #[derive(Debug, Default)]
 pub(crate) struct ModifiedLinesEmitter;
diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs
index 75c75c523b0..77c9818b66b 100644
--- a/src/tools/rustfmt/src/expr.rs
+++ b/src/tools/rustfmt/src/expr.rs
@@ -3,33 +3,33 @@ use std::cmp::min;
 
 use itertools::Itertools;
 use rustc_ast::token::{Delimiter, Lit, LitKind};
-use rustc_ast::{ast, ptr, token, ForLoopKind, MatchKind};
+use rustc_ast::{ForLoopKind, MatchKind, ast, ptr, token};
 use rustc_span::{BytePos, Span};
 use tracing::debug;
 
 use crate::chains::rewrite_chain;
 use crate::closures;
 use crate::comment::{
-    combine_strs_with_missing_comments, contains_comment, recover_comment_removed, rewrite_comment,
-    rewrite_missing_comment, CharClasses, FindUncommented,
+    CharClasses, FindUncommented, combine_strs_with_missing_comments, contains_comment,
+    recover_comment_removed, rewrite_comment, rewrite_missing_comment,
 };
 use crate::config::lists::*;
-use crate::config::{Config, ControlBraceStyle, HexLiteralCase, IndentStyle, Version};
+use crate::config::{Config, ControlBraceStyle, HexLiteralCase, IndentStyle, StyleEdition};
 use crate::lists::{
-    definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape,
-    struct_lit_tactic, write_list, ListFormatting, Separator,
+    ListFormatting, Separator, definitive_tactic, itemize_list, shape_for_tactic,
+    struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list,
 };
-use crate::macros::{rewrite_macro, MacroPosition};
+use crate::macros::{MacroPosition, rewrite_macro};
 use crate::matches::rewrite_match;
 use crate::overflow::{self, IntoOverflowableItem, OverflowableItem};
-use crate::pairs::{rewrite_all_pairs, rewrite_pair, PairParts};
-use crate::rewrite::{Rewrite, RewriteContext};
+use crate::pairs::{PairParts, rewrite_all_pairs, rewrite_pair};
+use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult};
 use crate::shape::{Indent, Shape};
 use crate::source_map::{LineRangeUtils, SpanUtils};
 use crate::spanned::Spanned;
 use crate::stmt;
-use crate::string::{rewrite_string, StringFormat};
-use crate::types::{rewrite_path, PathContext};
+use crate::string::{StringFormat, rewrite_string};
+use crate::types::{PathContext, rewrite_path};
 use crate::utils::{
     colon_spaces, contains_skip, count_newlines, filtered_str_fits, first_line_ends_with,
     inner_attributes, last_line_extendable, last_line_width, mk_sp, outer_attributes,
@@ -40,6 +40,10 @@ use crate::visitor::FmtVisitor;
 
 impl Rewrite for ast::Expr {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         format_expr(self, ExprType::SubExpression, context, shape)
     }
 }
@@ -59,14 +63,14 @@ pub(crate) fn format_expr(
     expr_type: ExprType,
     context: &RewriteContext<'_>,
     shape: Shape,
-) -> Option<String> {
-    skip_out_of_file_lines_range!(context, expr.span);
+) -> RewriteResult {
+    skip_out_of_file_lines_range_err!(context, expr.span);
 
     if contains_skip(&*expr.attrs) {
-        return Some(context.snippet(expr.span()).to_owned());
+        return Ok(context.snippet(expr.span()).to_owned());
     }
     let shape = if expr_type == ExprType::Statement && semicolon_for_expr(context, expr) {
-        shape.sub_width(1)?
+        shape.sub_width(1).max_width_error(shape.width, expr.span)?
     } else {
         shape
     };
@@ -82,25 +86,25 @@ pub(crate) fn format_expr(
             None,
         ),
         ast::ExprKind::Lit(token_lit) => {
-            if let Some(expr_rw) = rewrite_literal(context, token_lit, expr.span, shape) {
-                Some(expr_rw)
+            if let Ok(expr_rw) = rewrite_literal(context, token_lit, expr.span, shape) {
+                Ok(expr_rw)
             } else {
                 if let LitKind::StrRaw(_) = token_lit.kind {
-                    Some(context.snippet(expr.span).trim().into())
+                    Ok(context.snippet(expr.span).trim().into())
                 } else {
-                    None
+                    Err(RewriteError::Unknown)
                 }
             }
         }
         ast::ExprKind::Call(ref callee, ref args) => {
             let inner_span = mk_sp(callee.span.hi(), expr.span.hi());
-            let callee_str = callee.rewrite(context, shape)?;
+            let callee_str = callee.rewrite_result(context, shape)?;
             rewrite_call(context, &callee_str, args, inner_span, shape)
         }
         ast::ExprKind::Paren(ref subexpr) => rewrite_paren(context, subexpr, shape, expr.span),
         ast::ExprKind::Binary(op, ref lhs, ref rhs) => {
             // FIXME: format comments between operands and operator
-            rewrite_all_pairs(expr, shape, context).or_else(|| {
+            rewrite_all_pairs(expr, shape, context).or_else(|_| {
                 rewrite_pair(
                     &**lhs,
                     &**rhs,
@@ -138,7 +142,8 @@ pub(crate) fn format_expr(
         | ast::ExprKind::ForLoop { .. }
         | ast::ExprKind::Loop(..)
         | ast::ExprKind::While(..) => to_control_flow(expr, expr_type)
-            .and_then(|control_flow| control_flow.rewrite(context, shape)),
+            .unknown_error()
+            .and_then(|control_flow| control_flow.rewrite_result(context, shape)),
         ast::ExprKind::ConstBlock(ref anon_const) => {
             let rewrite = match anon_const.value.kind {
                 ast::ExprKind::Block(ref block, opt_label) => {
@@ -148,20 +153,20 @@ pub(crate) fn format_expr(
                     // See https://github.com/rust-lang/rustfmt/issues/6158
                     rewrite_block(block, Some(&expr.attrs), opt_label, context, shape)?
                 }
-                _ => anon_const.rewrite(context, shape)?,
+                _ => anon_const.rewrite_result(context, shape)?,
             };
-            Some(format!("const {}", rewrite))
+            Ok(format!("const {}", rewrite))
         }
         ast::ExprKind::Block(ref block, opt_label) => {
             match expr_type {
                 ExprType::Statement => {
                     if is_unsafe_block(block) {
                         rewrite_block(block, Some(&expr.attrs), opt_label, context, shape)
-                    } else if let rw @ Some(_) =
+                    } else if let Some(rw) =
                         rewrite_empty_block(context, block, Some(&expr.attrs), opt_label, "", shape)
                     {
                         // Rewrite block without trying to put it in a single line.
-                        rw
+                        Ok(rw)
                     } else {
                         let prefix = block_prefix(context, block, shape)?;
 
@@ -198,7 +203,7 @@ pub(crate) fn format_expr(
                 Some(label) => format!(" {}", label.ident),
                 None => String::new(),
             };
-            Some(format!("continue{id_str}"))
+            Ok(format!("continue{id_str}"))
         }
         ast::ExprKind::Break(ref opt_label, ref opt_expr) => {
             let id_str = match *opt_label {
@@ -209,14 +214,14 @@ pub(crate) fn format_expr(
             if let Some(ref expr) = *opt_expr {
                 rewrite_unary_prefix(context, &format!("break{id_str} "), &**expr, shape)
             } else {
-                Some(format!("break{id_str}"))
+                Ok(format!("break{id_str}"))
             }
         }
         ast::ExprKind::Yield(ref opt_expr) => {
             if let Some(ref expr) = *opt_expr {
                 rewrite_unary_prefix(context, "yield ", &**expr, shape)
             } else {
-                Some("yield".to_string())
+                Ok("yield".to_string())
             }
         }
         ast::ExprKind::Closure(ref cl) => closures::rewrite_closure(
@@ -236,20 +241,21 @@ pub(crate) fn format_expr(
         | ast::ExprKind::MethodCall(..)
         | ast::ExprKind::Await(_, _) => rewrite_chain(expr, context, shape),
         ast::ExprKind::MacCall(ref mac) => {
-            rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|| {
+            rewrite_macro(mac, None, context, shape, MacroPosition::Expression).or_else(|_| {
                 wrap_str(
                     context.snippet(expr.span).to_owned(),
                     context.config.max_width(),
                     shape,
                 )
+                .max_width_error(shape.width, expr.span)
             })
         }
-        ast::ExprKind::Ret(None) => Some("return".to_owned()),
+        ast::ExprKind::Ret(None) => Ok("return".to_owned()),
         ast::ExprKind::Ret(Some(ref expr)) => {
             rewrite_unary_prefix(context, "return ", &**expr, shape)
         }
         ast::ExprKind::Become(ref expr) => rewrite_unary_prefix(context, "become ", &**expr, shape),
-        ast::ExprKind::Yeet(None) => Some("do yeet".to_owned()),
+        ast::ExprKind::Yeet(None) => Ok("do yeet".to_owned()),
         ast::ExprKind::Yeet(Some(ref expr)) => {
             rewrite_unary_prefix(context, "do yeet ", &**expr, shape)
         }
@@ -344,23 +350,23 @@ pub(crate) fn format_expr(
                     };
                     rewrite_unary_suffix(context, &sp_delim, &*lhs, shape)
                 }
-                (None, None) => Some(delim.to_owned()),
+                (None, None) => Ok(delim.to_owned()),
             }
         }
         // We do not format these expressions yet, but they should still
         // satisfy our width restrictions.
         // Style Guide RFC for InlineAsm variant pending
         // https://github.com/rust-dev-tools/fmt-rfcs/issues/152
-        ast::ExprKind::InlineAsm(..) => Some(context.snippet(expr.span).to_owned()),
+        ast::ExprKind::InlineAsm(..) => Ok(context.snippet(expr.span).to_owned()),
         ast::ExprKind::TryBlock(ref block) => {
-            if let rw @ Some(_) =
+            if let rw @ Ok(_) =
                 rewrite_single_line_block(context, "try ", block, Some(&expr.attrs), None, shape)
             {
                 rw
             } else {
                 // 9 = `try `
                 let budget = shape.width.saturating_sub(9);
-                Some(format!(
+                Ok(format!(
                     "{}{}",
                     "try ",
                     rewrite_block(
@@ -379,7 +385,7 @@ pub(crate) fn format_expr(
             } else {
                 ""
             };
-            if let rw @ Some(_) = rewrite_single_line_block(
+            if let rw @ Ok(_) = rewrite_single_line_block(
                 context,
                 format!("{kind} {mover}").as_str(),
                 block,
@@ -391,7 +397,7 @@ pub(crate) fn format_expr(
             } else {
                 // 6 = `async `
                 let budget = shape.width.saturating_sub(6);
-                Some(format!(
+                Ok(format!(
                     "{kind} {mover}{}",
                     rewrite_block(
                         block,
@@ -403,7 +409,7 @@ pub(crate) fn format_expr(
                 ))
             }
         }
-        ast::ExprKind::Underscore => Some("_".to_owned()),
+        ast::ExprKind::Underscore => Ok("_".to_owned()),
         ast::ExprKind::FormatArgs(..)
         | ast::ExprKind::Type(..)
         | ast::ExprKind::IncludedBytes(..)
@@ -412,16 +418,16 @@ pub(crate) fn format_expr(
             // rustfmt tries to parse macro arguments when formatting macros, so it's not totally
             // impossible for rustfmt to come across one of these nodes when formatting a file.
             // Also, rustfmt might get passed the output from `-Zunpretty=expanded`.
-            None
+            Err(RewriteError::Unknown)
         }
-        ast::ExprKind::Err(_) | ast::ExprKind::Dummy => None,
+        ast::ExprKind::Err(_) | ast::ExprKind::Dummy => Err(RewriteError::Unknown),
     };
 
     expr_rw
-        .and_then(|expr_str| recover_comment_removed(expr_str, expr.span, context))
+        .map(|expr_str| recover_comment_removed(expr_str, expr.span, context))
         .and_then(|expr_str| {
             let attrs = outer_attributes(&expr.attrs);
-            let attrs_str = attrs.rewrite(context, shape)?;
+            let attrs_str = attrs.rewrite_result(context, shape)?;
             let span = mk_sp(
                 attrs.last().map_or(expr.span.lo(), |attr| attr.span.hi()),
                 expr.span.lo(),
@@ -438,7 +444,7 @@ pub(crate) fn rewrite_array<'a, T: 'a + IntoOverflowableItem<'a>>(
     shape: Shape,
     force_separator_tactic: Option<SeparatorTactic>,
     delim_token: Option<Delimiter>,
-) -> Option<String> {
+) -> RewriteResult {
     overflow::rewrite_with_square_brackets(
         context,
         name,
@@ -488,17 +494,20 @@ fn rewrite_empty_block(
     None
 }
 
-fn block_prefix(context: &RewriteContext<'_>, block: &ast::Block, shape: Shape) -> Option<String> {
-    Some(match block.rules {
+fn block_prefix(context: &RewriteContext<'_>, block: &ast::Block, shape: Shape) -> RewriteResult {
+    Ok(match block.rules {
         ast::BlockCheckMode::Unsafe(..) => {
             let snippet = context.snippet(block.span);
-            let open_pos = snippet.find_uncommented("{")?;
+            let open_pos = snippet.find_uncommented("{").unknown_error()?;
             // Extract comment between unsafe and block start.
             let trimmed = &snippet[6..open_pos].trim();
 
             if !trimmed.is_empty() {
                 // 9 = "unsafe  {".len(), 7 = "unsafe ".len()
-                let budget = shape.width.checked_sub(9)?;
+                let budget = shape
+                    .width
+                    .checked_sub(9)
+                    .max_width_error(shape.width, block.span)?;
                 format!(
                     "unsafe {} ",
                     rewrite_comment(
@@ -523,17 +532,19 @@ fn rewrite_single_line_block(
     attrs: Option<&[ast::Attribute]>,
     label: Option<ast::Label>,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     if let Some(block_expr) = stmt::Stmt::from_simple_block(context, block, attrs) {
-        let expr_shape = shape.offset_left(last_line_width(prefix))?;
-        let expr_str = block_expr.rewrite(context, expr_shape)?;
+        let expr_shape = shape
+            .offset_left(last_line_width(prefix))
+            .max_width_error(shape.width, block_expr.span())?;
+        let expr_str = block_expr.rewrite_result(context, expr_shape)?;
         let label_str = rewrite_label(context, label);
         let result = format!("{prefix}{label_str}{{ {expr_str} }}");
         if result.len() <= shape.width && !result.contains('\n') {
-            return Some(result);
+            return Ok(result);
         }
     }
-    None
+    Err(RewriteError::Unknown)
 }
 
 pub(crate) fn rewrite_block_with_visitor(
@@ -544,9 +555,9 @@ pub(crate) fn rewrite_block_with_visitor(
     label: Option<ast::Label>,
     shape: Shape,
     has_braces: bool,
-) -> Option<String> {
-    if let rw @ Some(_) = rewrite_empty_block(context, block, attrs, label, prefix, shape) {
-        return rw;
+) -> RewriteResult {
+    if let Some(rw_str) = rewrite_empty_block(context, block, attrs, label, prefix, shape) {
+        return Ok(rw_str);
     }
 
     let mut visitor = FmtVisitor::from_context(context);
@@ -555,7 +566,7 @@ pub(crate) fn rewrite_block_with_visitor(
     match (block.rules, label) {
         (ast::BlockCheckMode::Unsafe(..), _) | (ast::BlockCheckMode::Default, Some(_)) => {
             let snippet = context.snippet(block.span);
-            let open_pos = snippet.find_uncommented("{")?;
+            let open_pos = snippet.find_uncommented("{").unknown_error()?;
             visitor.last_pos = block.span.lo() + BytePos(open_pos as u32)
         }
         (ast::BlockCheckMode::Default, None) => visitor.last_pos = block.span.lo(),
@@ -569,11 +580,15 @@ pub(crate) fn rewrite_block_with_visitor(
         .skipped_range
         .borrow_mut()
         .append(&mut visitor_context.skipped_range.borrow_mut());
-    Some(format!("{}{}{}", prefix, label_str, visitor.buffer))
+    Ok(format!("{}{}{}", prefix, label_str, visitor.buffer))
 }
 
 impl Rewrite for ast::Block {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         rewrite_block(self, None, None, context, shape)
     }
 }
@@ -584,7 +599,7 @@ fn rewrite_block(
     label: Option<ast::Label>,
     context: &RewriteContext<'_>,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     rewrite_block_inner(block, attrs, label, true, context, shape)
 }
 
@@ -595,27 +610,24 @@ fn rewrite_block_inner(
     allow_single_line: bool,
     context: &RewriteContext<'_>,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     let prefix = block_prefix(context, block, shape)?;
 
     // shape.width is used only for the single line case: either the empty block `{}`,
     // or an unsafe expression `unsafe { e }`.
-    if let rw @ Some(_) = rewrite_empty_block(context, block, attrs, label, &prefix, shape) {
-        return rw;
+    if let Some(rw_str) = rewrite_empty_block(context, block, attrs, label, &prefix, shape) {
+        return Ok(rw_str);
     }
 
-    let result = rewrite_block_with_visitor(context, &prefix, block, attrs, label, shape, true);
-    if let Some(ref result_str) = result {
-        if allow_single_line && result_str.lines().count() <= 3 {
-            if let rw @ Some(_) =
-                rewrite_single_line_block(context, &prefix, block, attrs, label, shape)
-            {
-                return rw;
-            }
+    let result_str =
+        rewrite_block_with_visitor(context, &prefix, block, attrs, label, shape, true)?;
+    if allow_single_line && result_str.lines().count() <= 3 {
+        if let rw @ Ok(_) = rewrite_single_line_block(context, &prefix, block, attrs, label, shape)
+        {
+            return rw;
         }
     }
-
-    result
+    Ok(result_str)
 }
 
 /// Rewrite the divergent block of a `let-else` statement.
@@ -624,7 +636,7 @@ pub(crate) fn rewrite_let_else_block(
     allow_single_line: bool,
     context: &RewriteContext<'_>,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     rewrite_block_inner(block, None, None, allow_single_line, context, shape)
 }
 
@@ -648,6 +660,7 @@ pub(crate) fn rewrite_cond(
                 String::from("\n") + &shape.indent.block_only().to_string(context.config);
             control_flow
                 .rewrite_cond(context, shape, &alt_block_sep)
+                .ok()
                 .map(|rw| rw.0)
         }),
     }
@@ -872,10 +885,12 @@ impl<'a> ControlFlow<'a> {
         expr: &ast::Expr,
         shape: Shape,
         offset: usize,
-    ) -> Option<String> {
+    ) -> RewriteResult {
         debug!("rewrite_pat_expr {:?} {:?} {:?}", shape, self.pat, expr);
 
-        let cond_shape = shape.offset_left(offset)?;
+        let cond_shape = shape
+            .offset_left(offset)
+            .max_width_error(shape.width, expr.span)?;
         if let Some(pat) = self.pat {
             let matcher = if self.matcher.is_empty() {
                 self.matcher.to_owned()
@@ -883,9 +898,10 @@ impl<'a> ControlFlow<'a> {
                 format!("{} ", self.matcher)
             };
             let pat_shape = cond_shape
-                .offset_left(matcher.len())?
-                .sub_width(self.connector.len())?;
-            let pat_string = pat.rewrite(context, pat_shape)?;
+                .offset_left(matcher.len())
+                .and_then(|s| s.sub_width(self.connector.len()))
+                .max_width_error(cond_shape.width, pat.span)?;
+            let pat_string = pat.rewrite_result(context, pat_shape)?;
             let comments_lo = context
                 .snippet_provider
                 .span_after(self.span.with_lo(pat.span.hi()), self.connector.trim());
@@ -902,10 +918,10 @@ impl<'a> ControlFlow<'a> {
             );
         }
 
-        let expr_rw = expr.rewrite(context, cond_shape);
+        let expr_rw = expr.rewrite_result(context, cond_shape);
         // The expression may (partially) fit on the current line.
         // We do not allow splitting between `if` and condition.
-        if self.keyword == "if" || expr_rw.is_some() {
+        if self.keyword == "if" || expr_rw.is_ok() {
             return expr_rw;
         }
 
@@ -914,7 +930,7 @@ impl<'a> ControlFlow<'a> {
             .block_indent(context.config.tab_spaces())
             .with_max_width(context.config);
         let nested_indent_str = nested_shape.indent.to_string_with_newline(context.config);
-        expr.rewrite(context, nested_shape)
+        expr.rewrite_result(context, nested_shape)
             .map(|expr_rw| format!("{}{}", nested_indent_str, expr_rw))
     }
 
@@ -923,7 +939,7 @@ impl<'a> ControlFlow<'a> {
         context: &RewriteContext<'_>,
         shape: Shape,
         alt_block_sep: &str,
-    ) -> Option<(String, usize)> {
+    ) -> Result<(String, usize), RewriteError> {
         // Do not take the rhs overhead from the upper expressions into account
         // when rewriting pattern.
         let new_width = context.budget(shape.used_width());
@@ -934,7 +950,9 @@ impl<'a> ControlFlow<'a> {
         let constr_shape = if self.nested_if {
             // We are part of an if-elseif-else chain. Our constraints are tightened.
             // 7 = "} else " .len()
-            fresh_shape.offset_left(7)?
+            fresh_shape
+                .offset_left(7)
+                .max_width_error(fresh_shape.width, self.span)?
         } else {
             fresh_shape
         };
@@ -970,7 +988,7 @@ impl<'a> ControlFlow<'a> {
 
             if let Some(cond_str) = trial {
                 if cond_str.len() <= context.config.single_line_if_else_max_width() {
-                    return Some((cond_str, 0));
+                    return Ok((cond_str, 0));
                 }
             }
         }
@@ -1023,7 +1041,7 @@ impl<'a> ControlFlow<'a> {
             label_string.len() + self.keyword.len() + pat_expr_string.len() + 2
         };
 
-        Some((
+        Ok((
             format!(
                 "{}{}{}{}{}",
                 label_string,
@@ -1089,13 +1107,17 @@ pub(crate) fn rewrite_else_kw_with_comments(
 
 impl<'a> Rewrite for ControlFlow<'a> {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         debug!("ControlFlow::rewrite {:?} {:?}", self, shape);
 
         let alt_block_sep = &shape.indent.to_string_with_newline(context.config);
         let (cond_str, used_width) = self.rewrite_cond(context, shape, alt_block_sep)?;
         // If `used_width` is 0, it indicates that whole control flow is written in a single line.
         if used_width == 0 {
-            return Some(cond_str);
+            return Ok(cond_str);
         }
 
         let block_width = shape.width.saturating_sub(used_width);
@@ -1139,7 +1161,7 @@ impl<'a> Rewrite for ControlFlow<'a> {
                         true,
                         mk_sp(else_block.span.lo(), self.span.hi()),
                     )
-                    .rewrite(context, shape)
+                    .rewrite_result(context, shape)
                 }
                 _ => {
                     last_in_chain = true;
@@ -1164,7 +1186,7 @@ impl<'a> Rewrite for ControlFlow<'a> {
             result.push_str(&rewrite?);
         }
 
-        Some(result)
+        Ok(result)
     }
 }
 
@@ -1177,7 +1199,7 @@ fn rewrite_label(context: &RewriteContext<'_>, opt_label: Option<ast::Label>) ->
 
 fn extract_comment(span: Span, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
     match rewrite_missing_comment(span, shape, context) {
-        Some(ref comment) if !comment.is_empty() => Some(format!(
+        Ok(ref comment) if !comment.is_empty() => Some(format!(
             "{indent}{comment}{indent}",
             indent = shape.indent.to_string_with_newline(context.config)
         )),
@@ -1248,7 +1270,7 @@ pub(crate) fn rewrite_literal(
     token_lit: token::Lit,
     span: Span,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     match token_lit.kind {
         token::LitKind::Str => rewrite_string_lit(context, span, shape),
         token::LitKind::Integer => rewrite_int_lit(context, token_lit, span, shape),
@@ -1256,11 +1278,12 @@ pub(crate) fn rewrite_literal(
             context.snippet(span).to_owned(),
             context.config.max_width(),
             shape,
-        ),
+        )
+        .max_width_error(shape.width, span),
     }
 }
 
-fn rewrite_string_lit(context: &RewriteContext<'_>, span: Span, shape: Shape) -> Option<String> {
+fn rewrite_string_lit(context: &RewriteContext<'_>, span: Span, shape: Shape) -> RewriteResult {
     let string_lit = context.snippet(span);
 
     if !context.config.format_strings() {
@@ -1268,11 +1291,12 @@ fn rewrite_string_lit(context: &RewriteContext<'_>, span: Span, shape: Shape) ->
             .lines()
             .dropping_back(1)
             .all(|line| line.ends_with('\\'))
-            && context.config.version() == Version::Two
+            && context.config.style_edition() >= StyleEdition::Edition2024
         {
-            return Some(string_lit.to_owned());
+            return Ok(string_lit.to_owned());
         } else {
-            return wrap_str(string_lit.to_owned(), context.config.max_width(), shape);
+            return wrap_str(string_lit.to_owned(), context.config.max_width(), shape)
+                .max_width_error(shape.width, span);
         }
     }
 
@@ -1284,6 +1308,7 @@ fn rewrite_string_lit(context: &RewriteContext<'_>, span: Span, shape: Shape) ->
         &StringFormat::new(shape.visual_indent(0), context.config),
         shape.width.saturating_sub(2),
     )
+    .max_width_error(shape.width, span)
 }
 
 fn rewrite_int_lit(
@@ -1291,7 +1316,7 @@ fn rewrite_int_lit(
     token_lit: token::Lit,
     span: Span,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     let symbol = token_lit.symbol.as_str();
 
     if let Some(symbol_stripped) = symbol.strip_prefix("0x") {
@@ -1305,11 +1330,12 @@ fn rewrite_int_lit(
                 format!(
                     "0x{}{}",
                     hex_lit,
-                    token_lit.suffix.map_or(String::new(), |s| s.to_string())
+                    token_lit.suffix.as_ref().map_or("", |s| s.as_str())
                 ),
                 context.config.max_width(),
                 shape,
-            );
+            )
+            .max_width_error(shape.width, span);
         }
     }
 
@@ -1318,6 +1344,7 @@ fn rewrite_int_lit(
         context.config.max_width(),
         shape,
     )
+    .max_width_error(shape.width, span)
 }
 
 fn choose_separator_tactic(context: &RewriteContext<'_>, span: Span) -> Option<SeparatorTactic> {
@@ -1338,7 +1365,7 @@ pub(crate) fn rewrite_call(
     args: &[ptr::P<ast::Expr>],
     span: Span,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     overflow::rewrite_with_parens(
         context,
         callee,
@@ -1458,7 +1485,7 @@ pub(crate) fn rewrite_paren(
     mut subexpr: &ast::Expr,
     shape: Shape,
     mut span: Span,
-) -> Option<String> {
+) -> RewriteResult {
     debug!("rewrite_paren, shape: {:?}", shape);
 
     // Extract comments within parens.
@@ -1487,11 +1514,14 @@ pub(crate) fn rewrite_paren(
     }
 
     // 1 = `(` and `)`
-    let sub_shape = shape.offset_left(1)?.sub_width(1)?;
-    let subexpr_str = subexpr.rewrite(context, sub_shape)?;
+    let sub_shape = shape
+        .offset_left(1)
+        .and_then(|s| s.sub_width(1))
+        .max_width_error(shape.width, span)?;
+    let subexpr_str = subexpr.rewrite_result(context, sub_shape)?;
     let fits_single_line = !pre_comment.contains("//") && !post_comment.contains("//");
     if fits_single_line {
-        Some(format!("({pre_comment}{subexpr_str}{post_comment})"))
+        Ok(format!("({pre_comment}{subexpr_str}{post_comment})"))
     } else {
         rewrite_paren_in_multi_line(context, subexpr, shape, pre_span, post_span)
     }
@@ -1503,12 +1533,12 @@ fn rewrite_paren_in_multi_line(
     shape: Shape,
     pre_span: Span,
     post_span: Span,
-) -> Option<String> {
+) -> RewriteResult {
     let nested_indent = shape.indent.block_indent(context.config);
     let nested_shape = Shape::indented(nested_indent, context.config);
     let pre_comment = rewrite_missing_comment(pre_span, nested_shape, context)?;
     let post_comment = rewrite_missing_comment(post_span, nested_shape, context)?;
-    let subexpr_str = subexpr.rewrite(context, nested_shape)?;
+    let subexpr_str = subexpr.rewrite_result(context, nested_shape)?;
 
     let mut result = String::with_capacity(subexpr_str.len() * 2);
     result.push('(');
@@ -1525,7 +1555,7 @@ fn rewrite_paren_in_multi_line(
     result.push_str(&shape.indent.to_string_with_newline(context.config));
     result.push(')');
 
-    Some(result)
+    Ok(result)
 }
 
 fn rewrite_index(
@@ -1533,8 +1563,8 @@ fn rewrite_index(
     index: &ast::Expr,
     context: &RewriteContext<'_>,
     shape: Shape,
-) -> Option<String> {
-    let expr_str = expr.rewrite(context, shape)?;
+) -> RewriteResult {
+    let expr_str = expr.rewrite_result(context, shape)?;
 
     let offset = last_line_width(&expr_str) + 1;
     let rhs_overhead = shape.rhs_overhead(context.config);
@@ -1549,37 +1579,45 @@ fn rewrite_index(
                 .and_then(|shape| shape.sub_width(1)),
             IndentStyle::Visual => shape.visual_indent(offset).sub_width(offset + 1),
         }
-    };
-    let orig_index_rw = index_shape.and_then(|s| index.rewrite(context, s));
+    }
+    .max_width_error(shape.width, index.span());
+    let orig_index_rw = index_shape.and_then(|s| index.rewrite_result(context, s));
 
     // Return if index fits in a single line.
     match orig_index_rw {
-        Some(ref index_str) if !index_str.contains('\n') => {
-            return Some(format!("{expr_str}[{index_str}]"));
+        Ok(ref index_str) if !index_str.contains('\n') => {
+            return Ok(format!("{expr_str}[{index_str}]"));
         }
         _ => (),
     }
 
     // Try putting index on the next line and see if it fits in a single line.
     let indent = shape.indent.block_indent(context.config);
-    let index_shape = Shape::indented(indent, context.config).offset_left(1)?;
-    let index_shape = index_shape.sub_width(1 + rhs_overhead)?;
-    let new_index_rw = index.rewrite(context, index_shape);
+    let index_shape = Shape::indented(indent, context.config)
+        .offset_left(1)
+        .max_width_error(shape.width, index.span())?;
+    let index_shape = index_shape
+        .sub_width(1 + rhs_overhead)
+        .max_width_error(index_shape.width, index.span())?;
+    let new_index_rw = index.rewrite_result(context, index_shape);
     match (orig_index_rw, new_index_rw) {
-        (_, Some(ref new_index_str)) if !new_index_str.contains('\n') => Some(format!(
+        (_, Ok(ref new_index_str)) if !new_index_str.contains('\n') => Ok(format!(
             "{}{}[{}]",
             expr_str,
             indent.to_string_with_newline(context.config),
             new_index_str,
         )),
-        (None, Some(ref new_index_str)) => Some(format!(
+        (Err(_), Ok(ref new_index_str)) => Ok(format!(
             "{}{}[{}]",
             expr_str,
             indent.to_string_with_newline(context.config),
             new_index_str,
         )),
-        (Some(ref index_str), _) => Some(format!("{expr_str}[{index_str}]")),
-        _ => None,
+        (Ok(ref index_str), _) => Ok(format!("{expr_str}[{index_str}]")),
+        // When both orig_index_rw and new_index_rw result in errors, we currently propagate the
+        // error from the second attempt since it is more generous with width constraints.
+        // This decision is somewhat arbitrary and is open to change.
+        (Err(_), Err(new_index_rw_err)) => Err(new_index_rw_err),
     }
 }
 
@@ -1596,7 +1634,7 @@ fn rewrite_struct_lit<'a>(
     attrs: &[ast::Attribute],
     span: Span,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     debug!("rewrite_struct_lit: shape {:?}", shape);
 
     enum StructLitField<'a> {
@@ -1606,20 +1644,21 @@ fn rewrite_struct_lit<'a>(
     }
 
     // 2 = " {".len()
-    let path_shape = shape.sub_width(2)?;
+    let path_shape = shape.sub_width(2).max_width_error(shape.width, span)?;
     let path_str = rewrite_path(context, PathContext::Expr, qself, path, path_shape)?;
 
     let has_base_or_rest = match struct_rest {
-        ast::StructRest::None if fields.is_empty() => return Some(format!("{path_str} {{}}")),
+        ast::StructRest::None if fields.is_empty() => return Ok(format!("{path_str} {{}}")),
         ast::StructRest::Rest(_) if fields.is_empty() => {
-            return Some(format!("{path_str} {{ .. }}"));
+            return Ok(format!("{path_str} {{ .. }}"));
         }
         ast::StructRest::Rest(_) | ast::StructRest::Base(_) => true,
         _ => false,
     };
 
     // Foo { a: Foo } - indent is +3, width is -5.
-    let (h_shape, v_shape) = struct_lit_shape(shape, context, path_str.len() + 3, 2)?;
+    let (h_shape, v_shape) = struct_lit_shape(shape, context, path_str.len() + 3, 2)
+        .max_width_error(shape.width, span)?;
 
     let one_line_width = h_shape.map_or(0, |shape| shape.width);
     let body_lo = context.snippet_provider.span_after(span, "{");
@@ -1632,7 +1671,8 @@ fn rewrite_struct_lit<'a>(
             v_shape,
             mk_sp(body_lo, span.hi()),
             one_line_width,
-        )?
+        )
+        .unknown_error()?
     } else {
         let field_iter = fields.iter().map(StructLitField::Regular).chain(
             match struct_rest {
@@ -1661,14 +1701,24 @@ fn rewrite_struct_lit<'a>(
         let rewrite = |item: &StructLitField<'_>| match *item {
             StructLitField::Regular(field) => {
                 // The 1 taken from the v_budget is for the comma.
-                rewrite_field(context, field, v_shape.sub_width(1)?, 0)
+                rewrite_field(
+                    context,
+                    field,
+                    v_shape.sub_width(1).max_width_error(v_shape.width, span)?,
+                    0,
+                )
             }
             StructLitField::Base(expr) => {
                 // 2 = ..
-                expr.rewrite(context, v_shape.offset_left(2)?)
-                    .map(|s| format!("..{}", s))
+                expr.rewrite_result(
+                    context,
+                    v_shape
+                        .offset_left(2)
+                        .max_width_error(v_shape.width, span)?,
+                )
+                .map(|s| format!("..{}", s))
             }
-            StructLitField::Rest(_) => Some("..".to_owned()),
+            StructLitField::Rest(_) => Ok("..".to_owned()),
         };
 
         let items = itemize_list(
@@ -1703,7 +1753,7 @@ fn rewrite_struct_lit<'a>(
 
     let fields_str =
         wrap_struct_field(context, attrs, &fields_str, shape, v_shape, one_line_width)?;
-    Some(format!("{path_str} {{{fields_str}}}"))
+    Ok(format!("{path_str} {{{fields_str}}}"))
 
     // FIXME if context.config.indent_style() == Visual, but we run out
     // of space, we should fall back to BlockIndent.
@@ -1716,7 +1766,7 @@ pub(crate) fn wrap_struct_field(
     shape: Shape,
     nested_shape: Shape,
     one_line_width: usize,
-) -> Option<String> {
+) -> RewriteResult {
     let should_vertical = context.config.indent_style() == IndentStyle::Block
         && (fields_str.contains('\n')
             || !context.config.struct_lit_single_line()
@@ -1725,7 +1775,7 @@ pub(crate) fn wrap_struct_field(
     let inner_attrs = &inner_attributes(attrs);
     if inner_attrs.is_empty() {
         if should_vertical {
-            Some(format!(
+            Ok(format!(
                 "{}{}{}",
                 nested_shape.indent.to_string_with_newline(context.config),
                 fields_str,
@@ -1733,13 +1783,13 @@ pub(crate) fn wrap_struct_field(
             ))
         } else {
             // One liner or visual indent.
-            Some(format!(" {fields_str} "))
+            Ok(format!(" {fields_str} "))
         }
     } else {
-        Some(format!(
+        Ok(format!(
             "{}{}{}{}{}",
             nested_shape.indent.to_string_with_newline(context.config),
-            inner_attrs.rewrite(context, shape)?,
+            inner_attrs.rewrite_result(context, shape)?,
             nested_shape.indent.to_string_with_newline(context.config),
             fields_str,
             shape.indent.to_string_with_newline(context.config)
@@ -1756,38 +1806,40 @@ pub(crate) fn rewrite_field(
     field: &ast::ExprField,
     shape: Shape,
     prefix_max_width: usize,
-) -> Option<String> {
+) -> RewriteResult {
     if contains_skip(&field.attrs) {
-        return Some(context.snippet(field.span()).to_owned());
+        return Ok(context.snippet(field.span()).to_owned());
     }
-    let mut attrs_str = field.attrs.rewrite(context, shape)?;
+    let mut attrs_str = field.attrs.rewrite_result(context, shape)?;
     if !attrs_str.is_empty() {
         attrs_str.push_str(&shape.indent.to_string_with_newline(context.config));
     };
     let name = context.snippet(field.ident.span);
     if field.is_shorthand {
-        Some(attrs_str + name)
+        Ok(attrs_str + name)
     } else {
         let mut separator = String::from(struct_lit_field_separator(context.config));
         for _ in 0..prefix_max_width.saturating_sub(name.len()) {
             separator.push(' ');
         }
         let overhead = name.len() + separator.len();
-        let expr_shape = shape.offset_left(overhead)?;
-        let expr = field.expr.rewrite(context, expr_shape);
+        let expr_shape = shape
+            .offset_left(overhead)
+            .max_width_error(shape.width, field.span)?;
+        let expr = field.expr.rewrite_result(context, expr_shape);
         let is_lit = matches!(field.expr.kind, ast::ExprKind::Lit(_));
         match expr {
-            Some(ref e)
+            Ok(ref e)
                 if !is_lit && e.as_str() == name && context.config.use_field_init_shorthand() =>
             {
-                Some(attrs_str + name)
+                Ok(attrs_str + name)
             }
-            Some(e) => Some(format!("{attrs_str}{name}{separator}{e}")),
-            None => {
+            Ok(e) => Ok(format!("{attrs_str}{name}{separator}{e}")),
+            Err(_) => {
                 let expr_offset = shape.indent.block_indent(context.config);
                 let expr = field
                     .expr
-                    .rewrite(context, Shape::indented(expr_offset, context.config));
+                    .rewrite_result(context, Shape::indented(expr_offset, context.config));
                 expr.map(|s| {
                     format!(
                         "{}{}:\n{}{}",
@@ -1808,21 +1860,27 @@ fn rewrite_tuple_in_visual_indent_style<'a, T: 'a + IntoOverflowableItem<'a>>(
     span: Span,
     shape: Shape,
     is_singleton_tuple: bool,
-) -> Option<String> {
+) -> RewriteResult {
     // In case of length 1, need a trailing comma
     debug!("rewrite_tuple_in_visual_indent_style {:?}", shape);
     if is_singleton_tuple {
         // 3 = "(" + ",)"
-        let nested_shape = shape.sub_width(3)?.visual_indent(1);
+        let nested_shape = shape
+            .sub_width(3)
+            .max_width_error(shape.width, span)?
+            .visual_indent(1);
         return items
             .next()
             .unwrap()
-            .rewrite(context, nested_shape)
+            .rewrite_result(context, nested_shape)
             .map(|s| format!("({},)", s));
     }
 
     let list_lo = context.snippet_provider.span_after(span, "(");
-    let nested_shape = shape.sub_width(2)?.visual_indent(1);
+    let nested_shape = shape
+        .sub_width(2)
+        .max_width_error(shape.width, span)?
+        .visual_indent(1);
     let items = itemize_list(
         context.snippet_provider,
         items,
@@ -1830,7 +1888,7 @@ fn rewrite_tuple_in_visual_indent_style<'a, T: 'a + IntoOverflowableItem<'a>>(
         ",",
         |item| item.span().lo(),
         |item| item.span().hi(),
-        |item| item.rewrite(context, nested_shape),
+        |item| item.rewrite_result(context, nested_shape),
         list_lo,
         span.hi() - BytePos(1),
         false,
@@ -1847,7 +1905,7 @@ fn rewrite_tuple_in_visual_indent_style<'a, T: 'a + IntoOverflowableItem<'a>>(
         .ends_with_newline(false);
     let list_str = write_list(&item_vec, &fmt)?;
 
-    Some(format!("({list_str})"))
+    Ok(format!("({list_str})"))
 }
 
 fn rewrite_let(
@@ -1855,14 +1913,16 @@ fn rewrite_let(
     shape: Shape,
     pat: &ast::Pat,
     expr: &ast::Expr,
-) -> Option<String> {
+) -> RewriteResult {
     let mut result = "let ".to_owned();
 
     // TODO(ytmimi) comments could appear between `let` and the `pat`
 
     // 4 = "let ".len()
-    let pat_shape = shape.offset_left(4)?;
-    let pat_str = pat.rewrite(context, pat_shape)?;
+    let pat_shape = shape
+        .offset_left(4)
+        .max_width_error(shape.width, pat.span)?;
+    let pat_str = pat.rewrite_result(context, pat_shape)?;
     result.push_str(&pat_str);
 
     // TODO(ytmimi) comments could appear between `pat` and `=`
@@ -1890,7 +1950,7 @@ pub(crate) fn rewrite_tuple<'a, T: 'a + IntoOverflowableItem<'a>>(
     span: Span,
     shape: Shape,
     is_singleton_tuple: bool,
-) -> Option<String> {
+) -> RewriteResult {
     debug!("rewrite_tuple {:?}", shape);
     if context.use_block_indent() {
         // We use the same rule as function calls for rewriting tuples.
@@ -1919,31 +1979,35 @@ pub(crate) fn rewrite_tuple<'a, T: 'a + IntoOverflowableItem<'a>>(
     }
 }
 
-pub(crate) fn rewrite_unary_prefix<R: Rewrite>(
+pub(crate) fn rewrite_unary_prefix<R: Rewrite + Spanned>(
     context: &RewriteContext<'_>,
     prefix: &str,
     rewrite: &R,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
+    let shape = shape
+        .offset_left(prefix.len())
+        .max_width_error(shape.width, rewrite.span())?;
     rewrite
-        .rewrite(context, shape.offset_left(prefix.len())?)
+        .rewrite_result(context, shape)
         .map(|r| format!("{}{}", prefix, r))
 }
 
 // FIXME: this is probably not correct for multi-line Rewrites. we should
 // subtract suffix.len() from the last line budget, not the first!
-pub(crate) fn rewrite_unary_suffix<R: Rewrite>(
+pub(crate) fn rewrite_unary_suffix<R: Rewrite + Spanned>(
     context: &RewriteContext<'_>,
     suffix: &str,
     rewrite: &R,
     shape: Shape,
-) -> Option<String> {
-    rewrite
-        .rewrite(context, shape.sub_width(suffix.len())?)
-        .map(|mut r| {
-            r.push_str(suffix);
-            r
-        })
+) -> RewriteResult {
+    let shape = shape
+        .sub_width(suffix.len())
+        .max_width_error(shape.width, rewrite.span())?;
+    rewrite.rewrite_result(context, shape).map(|mut r| {
+        r.push_str(suffix);
+        r
+    })
 }
 
 fn rewrite_unary_op(
@@ -1951,7 +2015,7 @@ fn rewrite_unary_op(
     op: ast::UnOp,
     expr: &ast::Expr,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     // For some reason, an UnOp is not spanned like BinOp!
     rewrite_unary_prefix(context, op.as_str(), expr, shape)
 }
@@ -1990,15 +2054,21 @@ fn rewrite_assignment(
     rhs: &ast::Expr,
     op: Option<&ast::BinOp>,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     let operator_str = match op {
         Some(op) => context.snippet(op.span),
         None => "=",
     };
 
     // 1 = space between lhs and operator.
-    let lhs_shape = shape.sub_width(operator_str.len() + 1)?;
-    let lhs_str = format!("{} {}", lhs.rewrite(context, lhs_shape)?, operator_str);
+    let lhs_shape = shape
+        .sub_width(operator_str.len() + 1)
+        .max_width_error(shape.width, lhs.span())?;
+    let lhs_str = format!(
+        "{} {}",
+        lhs.rewrite_result(context, lhs_shape)?,
+        operator_str
+    );
 
     rewrite_assign_rhs(
         context,
@@ -2029,7 +2099,7 @@ pub(crate) fn rewrite_assign_rhs<S: Into<String>, R: Rewrite>(
     ex: &R,
     rhs_kind: &RhsAssignKind<'_>,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     rewrite_assign_rhs_with(context, lhs, ex, shape, rhs_kind, RhsTactics::Default)
 }
 
@@ -2040,7 +2110,7 @@ pub(crate) fn rewrite_assign_rhs_expr<R: Rewrite>(
     shape: Shape,
     rhs_kind: &RhsAssignKind<'_>,
     rhs_tactics: RhsTactics,
-) -> Option<String> {
+) -> RewriteResult {
     let last_line_width = last_line_width(lhs).saturating_sub(if lhs.contains('\n') {
         shape.indent.width()
     } else {
@@ -2062,7 +2132,7 @@ pub(crate) fn rewrite_assign_rhs_expr<R: Rewrite>(
         context,
         ex,
         orig_shape,
-        ex.rewrite(context, orig_shape),
+        ex.rewrite_result(context, orig_shape),
         rhs_kind,
         rhs_tactics,
         has_rhs_comment,
@@ -2076,13 +2146,13 @@ pub(crate) fn rewrite_assign_rhs_with<S: Into<String>, R: Rewrite>(
     shape: Shape,
     rhs_kind: &RhsAssignKind<'_>,
     rhs_tactics: RhsTactics,
-) -> Option<String> {
+) -> RewriteResult {
     let lhs = lhs.into();
     let rhs = rewrite_assign_rhs_expr(context, &lhs, ex, shape, rhs_kind, rhs_tactics)?;
-    Some(lhs + &rhs)
+    Ok(lhs + &rhs)
 }
 
-pub(crate) fn rewrite_assign_rhs_with_comments<S: Into<String>, R: Rewrite>(
+pub(crate) fn rewrite_assign_rhs_with_comments<S: Into<String>, R: Rewrite + Spanned>(
     context: &RewriteContext<'_>,
     lhs: S,
     ex: &R,
@@ -2091,21 +2161,22 @@ pub(crate) fn rewrite_assign_rhs_with_comments<S: Into<String>, R: Rewrite>(
     rhs_tactics: RhsTactics,
     between_span: Span,
     allow_extend: bool,
-) -> Option<String> {
+) -> RewriteResult {
     let lhs = lhs.into();
     let contains_comment = contains_comment(context.snippet(between_span));
     let shape = if contains_comment {
-        shape.block_left(context.config.tab_spaces())?
+        shape
+            .block_left(context.config.tab_spaces())
+            .max_width_error(shape.width, between_span.with_hi(ex.span().hi()))?
     } else {
         shape
     };
     let rhs = rewrite_assign_rhs_expr(context, &lhs, ex, shape, rhs_kind, rhs_tactics)?;
-
     if contains_comment {
         let rhs = rhs.trim_start();
         combine_strs_with_missing_comments(context, &lhs, rhs, between_span, shape, allow_extend)
     } else {
-        Some(lhs + &rhs)
+        Ok(lhs + &rhs)
     }
 }
 
@@ -2113,23 +2184,25 @@ fn choose_rhs<R: Rewrite>(
     context: &RewriteContext<'_>,
     expr: &R,
     shape: Shape,
-    orig_rhs: Option<String>,
+    orig_rhs: RewriteResult,
     _rhs_kind: &RhsAssignKind<'_>,
     rhs_tactics: RhsTactics,
     has_rhs_comment: bool,
-) -> Option<String> {
+) -> RewriteResult {
     match orig_rhs {
-        Some(ref new_str) if new_str.is_empty() => Some(String::new()),
-        Some(ref new_str)
-            if !new_str.contains('\n') && unicode_str_width(new_str) <= shape.width =>
-        {
-            Some(format!(" {new_str}"))
+        Ok(ref new_str) if new_str.is_empty() => Ok(String::new()),
+        Ok(ref new_str) if !new_str.contains('\n') && unicode_str_width(new_str) <= shape.width => {
+            Ok(format!(" {new_str}"))
         }
         _ => {
             // Expression did not fit on the same line as the identifier.
             // Try splitting the line and see if that works better.
-            let new_shape = shape_from_rhs_tactic(context, shape, rhs_tactics)?;
-            let new_rhs = expr.rewrite(context, new_shape);
+            let new_shape = shape_from_rhs_tactic(context, shape, rhs_tactics)
+                // TODO(ding-young) Ideally, we can replace unknown_error() with max_width_error(),
+                // but this requires either implementing the Spanned trait for ast::GenericBounds
+                // or grabbing the span from the call site.
+                .unknown_error()?;
+            let new_rhs = expr.rewrite_result(context, new_shape);
             let new_indent_str = &shape
                 .indent
                 .block_indent(context.config)
@@ -2137,24 +2210,27 @@ fn choose_rhs<R: Rewrite>(
             let before_space_str = if has_rhs_comment { "" } else { " " };
 
             match (orig_rhs, new_rhs) {
-                (Some(ref orig_rhs), Some(ref new_rhs))
+                (Ok(ref orig_rhs), Ok(ref new_rhs))
                     if !filtered_str_fits(&new_rhs, context.config.max_width(), new_shape) =>
                 {
-                    Some(format!("{before_space_str}{orig_rhs}"))
+                    Ok(format!("{before_space_str}{orig_rhs}"))
                 }
-                (Some(ref orig_rhs), Some(ref new_rhs))
+                (Ok(ref orig_rhs), Ok(ref new_rhs))
                     if prefer_next_line(orig_rhs, new_rhs, rhs_tactics) =>
                 {
-                    Some(format!("{new_indent_str}{new_rhs}"))
+                    Ok(format!("{new_indent_str}{new_rhs}"))
                 }
-                (None, Some(ref new_rhs)) => Some(format!("{new_indent_str}{new_rhs}")),
-                (None, None) if rhs_tactics == RhsTactics::AllowOverflow => {
+                (Err(_), Ok(ref new_rhs)) => Ok(format!("{new_indent_str}{new_rhs}")),
+                (Err(_), Err(_)) if rhs_tactics == RhsTactics::AllowOverflow => {
                     let shape = shape.infinite_width();
-                    expr.rewrite(context, shape)
+                    expr.rewrite_result(context, shape)
                         .map(|s| format!("{}{}", before_space_str, s))
                 }
-                (None, None) => None,
-                (Some(orig_rhs), _) => Some(format!("{before_space_str}{orig_rhs}")),
+                // When both orig_rhs and new_rhs result in errors, we currently propagate
+                // the error from the second attempt since it is more generous with
+                // width constraints. This decision is somewhat arbitrary and is open to change.
+                (Err(_), Err(new_rhs_err)) => Err(new_rhs_err),
+                (Ok(orig_rhs), _) => Ok(format!("{before_space_str}{orig_rhs}")),
             }
         }
     }
@@ -2204,7 +2280,7 @@ fn rewrite_expr_addrof(
     mutability: ast::Mutability,
     expr: &ast::Expr,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     let operator_str = match (mutability, borrow_kind) {
         (ast::Mutability::Not, ast::BorrowKind::Ref) => "&",
         (ast::Mutability::Not, ast::BorrowKind::Raw) => "&raw const ",
diff --git a/src/tools/rustfmt/src/formatting.rs b/src/tools/rustfmt/src/formatting.rs
index 5e71fe107eb..1e1e329f624 100644
--- a/src/tools/rustfmt/src/formatting.rs
+++ b/src/tools/rustfmt/src/formatting.rs
@@ -17,7 +17,7 @@ use crate::parse::parser::{DirectoryOwnership, Parser, ParserError};
 use crate::parse::session::ParseSess;
 use crate::utils::{contains_skip, count_newlines};
 use crate::visitor::FmtVisitor;
-use crate::{modules, source_file, ErrorKind, FormatReport, Input, Session};
+use crate::{ErrorKind, FormatReport, Input, Session, modules, source_file};
 
 mod generated;
 mod newline_style;
diff --git a/src/tools/rustfmt/src/git-rustfmt/main.rs b/src/tools/rustfmt/src/git-rustfmt/main.rs
index b8b0432aa95..64458420f59 100644
--- a/src/tools/rustfmt/src/git-rustfmt/main.rs
+++ b/src/tools/rustfmt/src/git-rustfmt/main.rs
@@ -13,7 +13,9 @@ use rustfmt_nightly as rustfmt;
 use tracing::debug;
 use tracing_subscriber::EnvFilter;
 
-use crate::rustfmt::{load_config, CliOptions, FormatReportFormatterBuilder, Input, Session};
+use crate::rustfmt::{
+    CliOptions, FormatReportFormatterBuilder, Input, Session, Version, load_config,
+};
 
 fn prune_files(files: Vec<&str>) -> Vec<&str> {
     let prefixes: Vec<_> = files
@@ -87,6 +89,15 @@ impl CliOptions for NullOptions {
     fn config_path(&self) -> Option<&Path> {
         unreachable!();
     }
+    fn edition(&self) -> Option<rustfmt_nightly::Edition> {
+        unreachable!();
+    }
+    fn style_edition(&self) -> Option<rustfmt_nightly::StyleEdition> {
+        unreachable!();
+    }
+    fn version(&self) -> Option<Version> {
+        unreachable!();
+    }
 }
 
 fn uncommitted_files() -> Vec<String> {
diff --git a/src/tools/rustfmt/src/ignore_path.rs b/src/tools/rustfmt/src/ignore_path.rs
index 5c25f233ce3..2f804ef5a25 100644
--- a/src/tools/rustfmt/src/ignore_path.rs
+++ b/src/tools/rustfmt/src/ignore_path.rs
@@ -41,8 +41,11 @@ mod test {
         use crate::ignore_path::IgnorePathSet;
         use std::path::{Path, PathBuf};
 
-        let config =
-            Config::from_toml(r#"ignore = ["foo.rs", "bar_dir/*"]"#, Path::new("")).unwrap();
+        let config = Config::from_toml(
+            r#"ignore = ["foo.rs", "bar_dir/*"]"#,
+            Path::new("./rustfmt.toml"),
+        )
+        .unwrap();
         let ignore_path_set = IgnorePathSet::from_ignore_list(&config.ignore()).unwrap();
 
         assert!(ignore_path_set.is_match(&FileName::Real(PathBuf::from("src/foo.rs"))));
@@ -59,7 +62,7 @@ mod test {
 
         let config = Config::from_toml(
             r#"ignore = ["foo.rs", "bar_dir/*", "!bar_dir/*/what.rs"]"#,
-            Path::new(""),
+            Path::new("./rustfmt.toml"),
         )
         .unwrap();
         let ignore_path_set = IgnorePathSet::from_ignore_list(&config.ignore()).unwrap();
diff --git a/src/tools/rustfmt/src/imports.rs b/src/tools/rustfmt/src/imports.rs
index 12c178e136f..b741dd9b5da 100644
--- a/src/tools/rustfmt/src/imports.rs
+++ b/src/tools/rustfmt/src/imports.rs
@@ -8,19 +8,20 @@ use itertools::Itertools;
 
 use rustc_ast::ast::{self, UseTreeKind};
 use rustc_span::{
+    BytePos, DUMMY_SP, Span,
     symbol::{self, sym},
-    BytePos, Span, DUMMY_SP,
 };
 
 use crate::comment::combine_strs_with_missing_comments;
-use crate::config::lists::*;
 use crate::config::ImportGranularity;
-use crate::config::{Edition, IndentStyle, Version};
+use crate::config::lists::*;
+use crate::config::{Edition, IndentStyle, StyleEdition};
 use crate::lists::{
-    definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator,
+    ListFormatting, ListItem, Separator, definitive_tactic, itemize_list, write_list,
 };
-use crate::rewrite::{Rewrite, RewriteContext};
+use crate::rewrite::{Rewrite, RewriteContext, RewriteErrorExt, RewriteResult};
 use crate::shape::Shape;
+use crate::sort::version_sort;
 use crate::source_map::SpanUtils;
 use crate::spanned::Spanned;
 use crate::utils::{is_same_visibility, mk_sp, rewrite_ident};
@@ -44,7 +45,8 @@ impl<'a> FmtVisitor<'a> {
             Some(item.span.lo()),
             Some(item.attrs.clone()),
         )
-        .rewrite_top_level(&self.get_context(), shape);
+        .rewrite_top_level(&self.get_context(), shape)
+        .ok();
         match rw {
             Some(ref s) if s.is_empty() => {
                 // Format up to last newline
@@ -104,7 +106,7 @@ pub(crate) enum UseSegmentKind {
 #[derive(Clone, Eq, PartialEq)]
 pub(crate) struct UseSegment {
     pub(crate) kind: UseSegmentKind,
-    pub(crate) version: Version,
+    pub(crate) style_edition: StyleEdition,
 }
 
 #[derive(Clone)]
@@ -149,7 +151,7 @@ impl UseSegment {
         };
         UseSegment {
             kind,
-            version: self.version,
+            style_edition: self.style_edition,
         }
     }
 
@@ -197,7 +199,7 @@ impl UseSegment {
 
         Some(UseSegment {
             kind,
-            version: context.config.version(),
+            style_edition: context.config.style_edition(),
         })
     }
 
@@ -331,12 +333,17 @@ impl UseTree {
         &self,
         context: &RewriteContext<'_>,
         shape: Shape,
-    ) -> Option<String> {
+    ) -> RewriteResult {
         let vis = self.visibility.as_ref().map_or(Cow::from(""), |vis| {
             crate::utils::format_visibility(context, vis)
         });
         let use_str = self
-            .rewrite(context, shape.offset_left(vis.len())?)
+            .rewrite_result(
+                context,
+                shape
+                    .offset_left(vis.len())
+                    .max_width_error(shape.width, self.span())?,
+            )
             .map(|s| {
                 if s.is_empty() {
                     s
@@ -346,8 +353,8 @@ impl UseTree {
             })?;
         match self.attrs {
             Some(ref attrs) if !attrs.is_empty() => {
-                let attr_str = attrs.rewrite(context, shape)?;
-                let lo = attrs.last().as_ref()?.span.hi();
+                let attr_str = attrs.rewrite_result(context, shape)?;
+                let lo = attrs.last().unknown_error()?.span.hi();
                 let hi = self.span.lo();
                 let span = mk_sp(lo, hi);
 
@@ -368,7 +375,7 @@ impl UseTree {
                     allow_extend,
                 )
             }
-            _ => Some(use_str),
+            _ => Ok(use_str),
         }
     }
 
@@ -444,18 +451,21 @@ impl UseTree {
             }
         }
 
-        let version = context.config.version();
+        let style_edition = context.config.style_edition();
 
         match a.kind {
             UseTreeKind::Glob => {
                 // in case of a global path and the glob starts at the root, e.g., "::*"
                 if a.prefix.segments.len() == 1 && leading_modsep {
                     let kind = UseSegmentKind::Ident("".to_owned(), None);
-                    result.path.push(UseSegment { kind, version });
+                    result.path.push(UseSegment {
+                        kind,
+                        style_edition,
+                    });
                 }
                 result.path.push(UseSegment {
                     kind: UseSegmentKind::Glob,
-                    version,
+                    style_edition,
                 });
             }
             UseTreeKind::Nested {
@@ -470,7 +480,7 @@ impl UseTree {
                     ",",
                     |tree| tree.span.lo(),
                     |tree| tree.span.hi(),
-                    |_| Some("".to_owned()), // We only need comments for now.
+                    |_| Ok("".to_owned()), // We only need comments for now.
                     context.snippet_provider.span_after(a.span, "{"),
                     a.span.hi(),
                     false,
@@ -480,7 +490,10 @@ impl UseTree {
                 // e.g., "::{foo, bar}"
                 if a.prefix.segments.len() == 1 && leading_modsep {
                     let kind = UseSegmentKind::Ident("".to_owned(), None);
-                    result.path.push(UseSegment { kind, version });
+                    result.path.push(UseSegment {
+                        kind,
+                        style_edition,
+                    });
                 }
                 let kind = UseSegmentKind::List(
                     list.iter()
@@ -490,7 +503,10 @@ impl UseTree {
                         })
                         .collect(),
                 );
-                result.path.push(UseSegment { kind, version });
+                result.path.push(UseSegment {
+                    kind,
+                    style_edition,
+                });
             }
             UseTreeKind::Simple(ref rename) => {
                 // If the path has leading double colons and is composed of only 2 segments, then we
@@ -519,7 +535,10 @@ impl UseTree {
                     _ => UseSegmentKind::Ident(name, alias),
                 };
 
-                let segment = UseSegment { kind, version };
+                let segment = UseSegment {
+                    kind,
+                    style_edition,
+                };
 
                 // `name` is already in result.
                 result.path.pop();
@@ -614,7 +633,7 @@ impl UseTree {
             list.sort();
             last = UseSegment {
                 kind: UseSegmentKind::List(list),
-                version: last.version,
+                style_edition: last.style_edition,
             };
         }
 
@@ -732,9 +751,12 @@ impl UseTree {
         }) = self.path.last()
         {
             let self_segment = self.path.pop().unwrap();
-            let version = self_segment.version;
+            let style_edition = self_segment.style_edition;
             let kind = UseSegmentKind::List(vec![UseTree::from_path(vec![self_segment], DUMMY_SP)]);
-            self.path.push(UseSegment { kind, version });
+            self.path.push(UseSegment {
+                kind,
+                style_edition,
+            });
         }
         self
     }
@@ -750,7 +772,7 @@ fn merge_rest(
         return None;
     }
     if a.len() != len && b.len() != len {
-        let version = a[len].version;
+        let style_edition = a[len].style_edition;
         if let UseSegmentKind::List(ref list) = a[len].kind {
             let mut list = list.clone();
             merge_use_trees_inner(
@@ -760,7 +782,10 @@ fn merge_rest(
             );
             let mut new_path = b[..len].to_vec();
             let kind = UseSegmentKind::List(list);
-            new_path.push(UseSegment { kind, version });
+            new_path.push(UseSegment {
+                kind,
+                style_edition,
+            });
             return Some(new_path);
         }
     } else if len == 1 {
@@ -770,9 +795,12 @@ fn merge_rest(
             (&b[0], &a[1..])
         };
         let kind = UseSegmentKind::Slf(common.get_alias().map(ToString::to_string));
-        let version = a[0].version;
+        let style_edition = a[0].style_edition;
         let mut list = vec![UseTree::from_path(
-            vec![UseSegment { kind, version }],
+            vec![UseSegment {
+                kind,
+                style_edition,
+            }],
             DUMMY_SP,
         )];
         match rest {
@@ -788,7 +816,7 @@ fn merge_rest(
             b[0].clone(),
             UseSegment {
                 kind: UseSegmentKind::List(list),
-                version,
+                style_edition,
             },
         ]);
     } else {
@@ -801,8 +829,11 @@ fn merge_rest(
     list.sort();
     let mut new_path = b[..len].to_vec();
     let kind = UseSegmentKind::List(list);
-    let version = a[0].version;
-    new_path.push(UseSegment { kind, version });
+    let style_edition = a[0].style_edition;
+    new_path.push(UseSegment {
+        kind,
+        style_edition,
+    });
     Some(new_path)
 }
 
@@ -892,8 +923,8 @@ impl Ord for UseSegment {
             | (Super(ref a), Super(ref b))
             | (Crate(ref a), Crate(ref b)) => match (a, b) {
                 (Some(sa), Some(sb)) => {
-                    if self.version == Version::Two {
-                        sa.trim_start_matches("r#").cmp(sb.trim_start_matches("r#"))
+                    if self.style_edition >= StyleEdition::Edition2024 {
+                        version_sort(sa.trim_start_matches("r#"), sb.trim_start_matches("r#"))
                     } else {
                         a.cmp(b)
                     }
@@ -902,25 +933,31 @@ impl Ord for UseSegment {
             },
             (Glob, Glob) => Ordering::Equal,
             (Ident(ref pia, ref aa), Ident(ref pib, ref ab)) => {
-                let (ia, ib) = if self.version == Version::Two {
+                let (ia, ib) = if self.style_edition >= StyleEdition::Edition2024 {
                     (pia.trim_start_matches("r#"), pib.trim_start_matches("r#"))
                 } else {
                     (pia.as_str(), pib.as_str())
                 };
-                // snake_case < CamelCase < UPPER_SNAKE_CASE
-                if ia.starts_with(char::is_uppercase) && ib.starts_with(char::is_lowercase) {
-                    return Ordering::Greater;
-                }
-                if ia.starts_with(char::is_lowercase) && ib.starts_with(char::is_uppercase) {
-                    return Ordering::Less;
-                }
-                if is_upper_snake_case(ia) && !is_upper_snake_case(ib) {
-                    return Ordering::Greater;
-                }
-                if !is_upper_snake_case(ia) && is_upper_snake_case(ib) {
-                    return Ordering::Less;
-                }
-                let ident_ord = ia.cmp(ib);
+
+                let ident_ord = if self.style_edition >= StyleEdition::Edition2024 {
+                    version_sort(ia, ib)
+                } else {
+                    // snake_case < CamelCase < UPPER_SNAKE_CASE
+                    if ia.starts_with(char::is_uppercase) && ib.starts_with(char::is_lowercase) {
+                        return Ordering::Greater;
+                    }
+                    if ia.starts_with(char::is_lowercase) && ib.starts_with(char::is_uppercase) {
+                        return Ordering::Less;
+                    }
+                    if is_upper_snake_case(ia) && !is_upper_snake_case(ib) {
+                        return Ordering::Greater;
+                    }
+                    if !is_upper_snake_case(ia) && is_upper_snake_case(ib) {
+                        return Ordering::Less;
+                    }
+                    ia.cmp(ib)
+                };
+
                 if ident_ord != Ordering::Equal {
                     return ident_ord;
                 }
@@ -928,9 +965,8 @@ impl Ord for UseSegment {
                     (None, Some(_)) => Ordering::Less,
                     (Some(_), None) => Ordering::Greater,
                     (Some(aas), Some(abs)) => {
-                        if self.version == Version::Two {
-                            aas.trim_start_matches("r#")
-                                .cmp(abs.trim_start_matches("r#"))
+                        if self.style_edition >= StyleEdition::Edition2024 {
+                            version_sort(aas.trim_start_matches("r#"), abs.trim_start_matches("r#"))
                         } else {
                             aas.cmp(abs)
                         }
@@ -982,21 +1018,24 @@ fn rewrite_nested_use_tree(
     context: &RewriteContext<'_>,
     use_tree_list: &[UseTree],
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     let mut list_items = Vec::with_capacity(use_tree_list.len());
     let nested_shape = match context.config.imports_indent() {
         IndentStyle::Block => shape
             .block_indent(context.config.tab_spaces())
             .with_max_width(context.config)
-            .sub_width(1)?,
+            .sub_width(1)
+            .unknown_error()?,
         IndentStyle::Visual => shape.visual_indent(0),
     };
     for use_tree in use_tree_list {
         if let Some(mut list_item) = use_tree.list_item.clone() {
-            list_item.item = use_tree.rewrite(context, nested_shape);
+            list_item.item = use_tree.rewrite_result(context, nested_shape);
             list_items.push(list_item);
         } else {
-            list_items.push(ListItem::from_str(use_tree.rewrite(context, nested_shape)?));
+            list_items.push(ListItem::from_str(
+                use_tree.rewrite_result(context, nested_shape)?,
+            ));
         }
     }
     let has_nested_list = use_tree_list.iter().any(|use_segment| {
@@ -1049,12 +1088,16 @@ fn rewrite_nested_use_tree(
         format!("{{{list_str}}}")
     };
 
-    Some(result)
+    Ok(result)
 }
 
 impl Rewrite for UseSegment {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
-        Some(match self.kind {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
+        Ok(match self.kind {
             UseSegmentKind::Ident(ref ident, Some(ref rename)) => {
                 format!("{ident} as {rename}")
             }
@@ -1066,31 +1109,42 @@ impl Rewrite for UseSegment {
             UseSegmentKind::Crate(Some(ref rename)) => format!("crate as {rename}"),
             UseSegmentKind::Crate(None) => "crate".to_owned(),
             UseSegmentKind::Glob => "*".to_owned(),
-            UseSegmentKind::List(ref use_tree_list) => rewrite_nested_use_tree(
-                context,
-                use_tree_list,
-                // 1 = "{" and "}"
-                shape.offset_left(1)?.sub_width(1)?,
-            )?,
+            UseSegmentKind::List(ref use_tree_list) => {
+                rewrite_nested_use_tree(
+                    context,
+                    use_tree_list,
+                    // 1 = "{" and "}"
+                    shape
+                        .offset_left(1)
+                        .and_then(|s| s.sub_width(1))
+                        .unknown_error()?,
+                )?
+            }
         })
     }
 }
 
 impl Rewrite for UseTree {
+    fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
     // This does NOT format attributes and visibility or add a trailing `;`.
-    fn rewrite(&self, context: &RewriteContext<'_>, mut shape: Shape) -> Option<String> {
+    fn rewrite_result(&self, context: &RewriteContext<'_>, mut shape: Shape) -> RewriteResult {
         let mut result = String::with_capacity(256);
         let mut iter = self.path.iter().peekable();
         while let Some(segment) = iter.next() {
-            let segment_str = segment.rewrite(context, shape)?;
+            let segment_str = segment.rewrite_result(context, shape)?;
             result.push_str(&segment_str);
             if iter.peek().is_some() {
                 result.push_str("::");
                 // 2 = "::"
-                shape = shape.offset_left(2 + segment_str.len())?;
+                shape = shape
+                    .offset_left(2 + segment_str.len())
+                    .max_width_error(shape.width, self.span())?;
             }
         }
-        Some(result)
+        Ok(result)
     }
 }
 
@@ -1114,7 +1168,7 @@ mod test {
 
         struct Parser<'a> {
             input: Peekable<Chars<'a>>,
-            version: Version,
+            style_edition: StyleEdition,
         }
 
         impl<'a> Parser<'a> {
@@ -1132,7 +1186,7 @@ mod test {
                 buf: &mut String,
                 alias_buf: &mut Option<String>,
             ) {
-                let version = self.version;
+                let style_edition = self.style_edition;
                 if !buf.is_empty() {
                     let mut alias = None;
                     swap(alias_buf, &mut alias);
@@ -1140,19 +1194,28 @@ mod test {
                     match buf.as_ref() {
                         "self" => {
                             let kind = UseSegmentKind::Slf(alias);
-                            result.push(UseSegment { kind, version });
+                            result.push(UseSegment {
+                                kind,
+                                style_edition,
+                            });
                             *buf = String::new();
                             *alias_buf = None;
                         }
                         "super" => {
                             let kind = UseSegmentKind::Super(alias);
-                            result.push(UseSegment { kind, version });
+                            result.push(UseSegment {
+                                kind,
+                                style_edition,
+                            });
                             *buf = String::new();
                             *alias_buf = None;
                         }
                         "crate" => {
                             let kind = UseSegmentKind::Crate(alias);
-                            result.push(UseSegment { kind, version });
+                            result.push(UseSegment {
+                                kind,
+                                style_edition,
+                            });
                             *buf = String::new();
                             *alias_buf = None;
                         }
@@ -1160,7 +1223,10 @@ mod test {
                             let mut name = String::new();
                             swap(buf, &mut name);
                             let kind = UseSegmentKind::Ident(name, alias);
-                            result.push(UseSegment { kind, version });
+                            result.push(UseSegment {
+                                kind,
+                                style_edition,
+                            });
                         }
                     }
                 }
@@ -1178,7 +1244,7 @@ mod test {
                             let kind = UseSegmentKind::List(self.parse_list());
                             result.push(UseSegment {
                                 kind,
-                                version: self.version,
+                                style_edition: self.style_edition,
                             });
                             self.eat('}');
                         }
@@ -1188,7 +1254,7 @@ mod test {
                             let kind = UseSegmentKind::Glob;
                             result.push(UseSegment {
                                 kind,
-                                version: self.version,
+                                style_edition: self.style_edition,
                             });
                         }
                         ':' => {
@@ -1249,7 +1315,7 @@ mod test {
 
         let mut parser = Parser {
             input: s.chars().peekable(),
-            version: Version::One,
+            style_edition: StyleEdition::Edition2015,
         };
         parser.parse_in_list()
     }
diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs
index cbf7ce90e37..fc043a697e0 100644
--- a/src/tools/rustfmt/src/items.rs
+++ b/src/tools/rustfmt/src/items.rs
@@ -1,31 +1,30 @@
 // Formatting top-level items - functions, structs, enums, traits, impls.
 
 use std::borrow::Cow;
-use std::cmp::{max, min, Ordering};
+use std::cmp::{Ordering, max, min};
 
 use regex::Regex;
 use rustc_ast::visit;
 use rustc_ast::{ast, ptr};
-use rustc_span::{symbol, BytePos, Span, DUMMY_SP};
+use rustc_span::{BytePos, DUMMY_SP, Span, symbol};
 use tracing::debug;
 
 use crate::attr::filter_inline_attrs;
 use crate::comment::{
-    combine_strs_with_missing_comments, contains_comment, is_last_comment_block,
+    FindUncommented, combine_strs_with_missing_comments, contains_comment, is_last_comment_block,
     recover_comment_removed, recover_missing_comment_in_span, rewrite_missing_comment,
-    FindUncommented,
 };
 use crate::config::lists::*;
-use crate::config::{BraceStyle, Config, IndentStyle, Version};
+use crate::config::{BraceStyle, Config, IndentStyle, StyleEdition};
 use crate::expr::{
-    is_empty_block, is_simple_block_stmt, rewrite_assign_rhs, rewrite_assign_rhs_with,
-    rewrite_assign_rhs_with_comments, rewrite_else_kw_with_comments, rewrite_let_else_block,
-    RhsAssignKind, RhsTactics,
+    RhsAssignKind, RhsTactics, is_empty_block, is_simple_block_stmt, rewrite_assign_rhs,
+    rewrite_assign_rhs_with, rewrite_assign_rhs_with_comments, rewrite_else_kw_with_comments,
+    rewrite_let_else_block,
 };
-use crate::lists::{definitive_tactic, itemize_list, write_list, ListFormatting, Separator};
-use crate::macros::{rewrite_macro, MacroPosition};
+use crate::lists::{ListFormatting, Separator, definitive_tactic, itemize_list, write_list};
+use crate::macros::{MacroPosition, rewrite_macro};
 use crate::overflow;
-use crate::rewrite::{Rewrite, RewriteContext};
+use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult};
 use crate::shape::{Indent, Shape};
 use crate::source_map::{LineRangeUtils, SpanUtils};
 use crate::spanned::Spanned;
@@ -49,18 +48,22 @@ fn type_annotation_separator(config: &Config) -> &str {
 // let pat: ty = init; or let pat: ty = init else { .. };
 impl Rewrite for ast::Local {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         debug!(
             "Local::rewrite {:?} {} {:?}",
             self, shape.width, shape.indent
         );
 
-        skip_out_of_file_lines_range!(context, self.span);
+        skip_out_of_file_lines_range_err!(context, self.span);
 
         if contains_skip(&self.attrs) {
-            return None;
+            return Err(RewriteError::SkipFormatting);
         }
 
-        let attrs_str = self.attrs.rewrite(context, shape)?;
+        let attrs_str = self.attrs.rewrite_result(context, shape)?;
         let mut result = if attrs_str.is_empty() {
             "let ".to_owned()
         } else {
@@ -79,10 +82,15 @@ impl Rewrite for ast::Local {
         let let_kw_offset = result.len() - "let ".len();
 
         // 4 = "let ".len()
-        let pat_shape = shape.offset_left(4)?;
+        let pat_shape = shape
+            .offset_left(4)
+            .max_width_error(shape.width, self.span())?;
         // 1 = ;
-        let pat_shape = pat_shape.sub_width(1)?;
-        let pat_str = self.pat.rewrite(context, pat_shape)?;
+        let pat_shape = pat_shape
+            .sub_width(1)
+            .max_width_error(shape.width, self.span())?;
+        let pat_str = self.pat.rewrite_result(context, pat_shape)?;
+
         result.push_str(&pat_str);
 
         // String that is placed within the assignment pattern and expression.
@@ -96,11 +104,13 @@ impl Rewrite for ast::Local {
                 } else {
                     shape
                 }
-                .offset_left(last_line_width(&result) + separator.len())?
+                .offset_left(last_line_width(&result) + separator.len())
+                .max_width_error(shape.width, self.span())?
                 // 2 = ` =`
-                .sub_width(2)?;
+                .sub_width(2)
+                .max_width_error(shape.width, self.span())?;
 
-                let rewrite = ty.rewrite(context, ty_shape)?;
+                let rewrite = ty.rewrite_result(context, ty_shape)?;
 
                 infix.push_str(separator);
                 infix.push_str(&rewrite);
@@ -117,7 +127,9 @@ impl Rewrite for ast::Local {
 
         if let Some((init, else_block)) = self.kind.init_else_opt() {
             // 1 = trailing semicolon;
-            let nested_shape = shape.sub_width(1)?;
+            let nested_shape = shape
+                .sub_width(1)
+                .max_width_error(shape.width, self.span())?;
 
             result = rewrite_assign_rhs(
                 context,
@@ -131,7 +143,8 @@ impl Rewrite for ast::Local {
                 let else_kw_span = init.span.between(block.span);
                 // Strip attributes and comments to check if newline is needed before the else
                 // keyword from the initializer part. (#5901)
-                let init_str = if context.config.version() == Version::Two {
+                let style_edition = context.config.style_edition();
+                let init_str = if style_edition >= StyleEdition::Edition2024 {
                     &result[let_kw_offset..]
                 } else {
                     result.as_str()
@@ -155,7 +168,8 @@ impl Rewrite for ast::Local {
                     std::cmp::min(shape.width, context.config.single_line_let_else_max_width());
 
                 // If available_space hits zero we know for sure this will be a multi-lined block
-                let assign_str_with_else_kw = if context.config.version() == Version::Two {
+                let style_edition = context.config.style_edition();
+                let assign_str_with_else_kw = if style_edition >= StyleEdition::Edition2024 {
                     &result[let_kw_offset..]
                 } else {
                     result.as_str()
@@ -184,7 +198,7 @@ impl Rewrite for ast::Local {
         }
 
         result.push(';');
-        Some(result)
+        Ok(result)
     }
 }
 
@@ -420,7 +434,7 @@ impl<'a> FmtVisitor<'a> {
 
         let mut fn_brace_style = newline_for_brace(self.config, &fn_sig.generics.where_clause);
         let (result, _, force_newline_brace) =
-            rewrite_fn_base(&context, indent, ident, fn_sig, span, fn_brace_style)?;
+            rewrite_fn_base(&context, indent, ident, fn_sig, span, fn_brace_style).ok()?;
 
         // 2 = ` {`
         if self.config.brace_style() == BraceStyle::AlwaysNextLine
@@ -441,7 +455,7 @@ impl<'a> FmtVisitor<'a> {
         vis: &ast::Visibility,
         generics: &ast::Generics,
         span: Span,
-    ) -> Option<String> {
+    ) -> RewriteResult {
         // Drop semicolon or it will be interpreted as comment.
         let span = mk_sp(span.lo(), span.hi() - BytePos(1));
         let context = self.get_context();
@@ -463,7 +477,7 @@ impl<'a> FmtVisitor<'a> {
         // Re-attach semicolon
         result.push(';');
 
-        Some(result)
+        Ok(result)
     }
 
     pub(crate) fn single_line_fn(
@@ -615,7 +629,10 @@ impl<'a> FmtVisitor<'a> {
                     }
                 },
                 |f| f.span.hi(),
-                |f| self.format_variant(f, one_line_width, pad_discrim_ident_to),
+                |f| {
+                    self.format_variant(f, one_line_width, pad_discrim_ident_to)
+                        .unknown_error()
+                },
                 body_lo,
                 body_hi,
                 false,
@@ -636,7 +653,7 @@ impl<'a> FmtVisitor<'a> {
             .trailing_separator(self.config.trailing_comma())
             .preserve_newline(true);
 
-        let list = write_list(&items, &fmt)?;
+        let list = write_list(&items, &fmt).ok()?;
         result.push_str(&list);
         result.push_str(&original_offset.to_string_with_newline(self.config));
         result.push('}');
@@ -658,10 +675,10 @@ impl<'a> FmtVisitor<'a> {
 
         let context = self.get_context();
         let shape = self.shape();
-        let attrs_str = if context.config.version() == Version::Two {
+        let attrs_str = if context.config.style_edition() >= StyleEdition::Edition2024 {
             field.attrs.rewrite(&context, shape)?
         } else {
-            // Version::One formatting that was off by 1. See issue #5801
+            // StyleEdition::Edition20{15|18|21} formatting that was off by 1. See issue #5801
             field.attrs.rewrite(&context, shape.sub_width(1)?)?
         };
         // sub_width(1) to take the trailing comma into account
@@ -693,12 +710,14 @@ impl<'a> FmtVisitor<'a> {
                 shape,
                 &RhsAssignKind::Expr(&ex.kind, ex.span),
                 RhsTactics::AllowOverflow,
-            )?
+            )
+            .ok()?
         } else {
             variant_body
         };
 
         combine_strs_with_missing_comments(&context, &attrs_str, &variant_body, span, shape, false)
+            .ok()
     }
 
     fn visit_impl_items(&mut self, items: &[ptr::P<ast::AssocItem>]) {
@@ -822,7 +841,8 @@ pub(crate) fn format_impl(
         where_span_end,
         self_ty.span.hi(),
         option,
-    )?;
+    )
+    .ok()?;
 
     // If there is no where-clause, we may have missing comments between the trait name and
     // the opening brace.
@@ -834,7 +854,7 @@ pub(crate) fn format_impl(
                 context,
                 last_line_width(&result),
             ) {
-                Some(ref missing_comment) if !missing_comment.is_empty() => {
+                Ok(ref missing_comment) if !missing_comment.is_empty() => {
                     result.push_str(missing_comment);
                 }
                 _ => (),
@@ -949,7 +969,7 @@ fn format_impl_ref_and_type(
     result.push_str(format_defaultness(defaultness));
     result.push_str(format_safety(safety));
 
-    let shape = if context.config.version() == Version::Two {
+    let shape = if context.config.style_edition() >= StyleEdition::Edition2024 {
         Shape::indented(offset + last_line_width(&result), context.config)
     } else {
         generics_shape_from_config(
@@ -958,7 +978,7 @@ fn format_impl_ref_and_type(
             0,
         )?
     };
-    let generics_str = rewrite_generics(context, "impl", generics, shape)?;
+    let generics_str = rewrite_generics(context, "impl", generics, shape).ok()?;
     result.push_str(&generics_str);
     result.push_str(format_constness_right(constness));
 
@@ -1166,7 +1186,7 @@ pub(crate) fn format_trait(
 
     let shape = Shape::indented(offset, context.config).offset_left(result.len())?;
     let generics_str =
-        rewrite_generics(context, rewrite_ident(context, item.ident), generics, shape)?;
+        rewrite_generics(context, rewrite_ident(context, item.ident), generics, shape).ok()?;
     result.push_str(&generics_str);
 
     // FIXME(#2055): rustfmt fails to format when there are comments between trait bounds.
@@ -1187,7 +1207,8 @@ pub(crate) fn format_trait(
             shape,
             &RhsAssignKind::Bounds,
             RhsTactics::ForceNextLineWithoutIndent,
-        )?;
+        )
+        .ok()?;
     }
 
     // Rewrite where-clause.
@@ -1212,7 +1233,8 @@ pub(crate) fn format_trait(
             None,
             pos_before_where,
             option,
-        )?;
+        )
+        .ok()?;
         // If the where-clause cannot fit on the same line,
         // put the where-clause on a new line
         if !where_clause_str.contains('\n')
@@ -1241,7 +1263,7 @@ pub(crate) fn format_trait(
                     context,
                     last_line_width(&result),
                 ) {
-                    Some(ref missing_comment) if !missing_comment.is_empty() => {
+                    Ok(ref missing_comment) if !missing_comment.is_empty() => {
                         result.push_str(missing_comment);
                     }
                     _ => (),
@@ -1317,7 +1339,11 @@ pub(crate) struct TraitAliasBounds<'a> {
 
 impl<'a> Rewrite for TraitAliasBounds<'a> {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
-        let generic_bounds_str = self.generic_bounds.rewrite(context, shape)?;
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
+        let generic_bounds_str = self.generic_bounds.rewrite_result(context, shape)?;
 
         let mut option = WhereClauseOption::new(true, WhereClauseSpace::None);
         option.allow_single_line();
@@ -1346,7 +1372,7 @@ impl<'a> Rewrite for TraitAliasBounds<'a> {
             shape.indent.to_string_with_newline(context.config)
         };
 
-        Some(format!("{generic_bounds_str}{space}{where_str}"))
+        Ok(format!("{generic_bounds_str}{space}{where_str}"))
     }
 }
 
@@ -1361,7 +1387,7 @@ pub(crate) fn format_trait_alias(
     let alias = rewrite_ident(context, ident);
     // 6 = "trait ", 2 = " ="
     let g_shape = shape.offset_left(6)?.sub_width(2)?;
-    let generics_str = rewrite_generics(context, alias, generics, g_shape)?;
+    let generics_str = rewrite_generics(context, alias, generics, g_shape).ok()?;
     let vis_str = format_visibility(context, vis);
     let lhs = format!("{vis_str}trait {generics_str} =");
     // 1 = ";"
@@ -1377,6 +1403,7 @@ pub(crate) fn format_trait_alias(
         shape.sub_width(1)?,
     )
     .map(|s| s + ";")
+    .ok()
 }
 
 fn format_unit_struct(
@@ -1531,8 +1558,8 @@ fn format_empty_struct_or_tuple(
     // indented shape for proper indenting of multi-line comments
     let shape = Shape::indented(offset.block_indent(context.config), context.config);
     match rewrite_missing_comment(span, shape, context) {
-        Some(ref s) if s.is_empty() => (),
-        Some(ref s) => {
+        Ok(ref s) if s.is_empty() => (),
+        Ok(ref s) => {
             let is_multi_line = !is_single_line(s);
             if is_multi_line || first_line_contains_single_line_comment(s) {
                 let nested_indent_str = offset
@@ -1545,7 +1572,7 @@ fn format_empty_struct_or_tuple(
                 result.push_str(&offset.to_string_with_newline(context.config));
             }
         }
-        None => result.push_str(context.snippet(span)),
+        Err(_) => result.push_str(context.snippet(span)),
     }
     result.push_str(closer);
 }
@@ -1587,7 +1614,7 @@ fn format_tuple_struct(
         Some(generics) => {
             let budget = context.budget(last_line_width(&header_str));
             let shape = Shape::legacy(budget, offset);
-            let generics_str = rewrite_generics(context, "", generics, shape)?;
+            let generics_str = rewrite_generics(context, "", generics, shape).ok()?;
             result.push_str(&generics_str);
 
             let where_budget = context.budget(last_line_width(&result));
@@ -1603,7 +1630,8 @@ fn format_tuple_struct(
                 None,
                 body_hi,
                 option,
-            )?
+            )
+            .ok()?
         }
         None => "".to_owned(),
     };
@@ -1629,7 +1657,8 @@ fn format_tuple_struct(
             mk_sp(lo, span.hi()),
             context.config.fn_call_width(),
             None,
-        )?;
+        )
+        .ok()?;
     }
 
     if !where_clause_str.is_empty()
@@ -1672,7 +1701,7 @@ pub(crate) fn rewrite_type_alias<'a, 'b>(
     indent: Indent,
     visitor_kind: &ItemVisitorKind<'b>,
     span: Span,
-) -> Option<String> {
+) -> RewriteResult {
     use ItemVisitorKind::*;
 
     let ast::TyAlias {
@@ -1683,6 +1712,9 @@ pub(crate) fn rewrite_type_alias<'a, 'b>(
         where_clauses,
     } = *ty_alias_kind;
     let ty_opt = ty.as_ref();
+    let rhs_hi = ty
+        .as_ref()
+        .map_or(where_clauses.before.span.hi(), |ty| ty.span.hi());
     let (ident, vis) = match visitor_kind {
         Item(i) => (i.ident, &i.vis),
         AssocTraitItem(i) | AssocImplItem(i) => (i.ident, &i.vis),
@@ -1697,21 +1729,27 @@ pub(crate) fn rewrite_type_alias<'a, 'b>(
     match (visitor_kind, &op_ty) {
         (Item(_) | AssocTraitItem(_) | ForeignItem(_), Some(op_bounds)) => {
             let op = OpaqueType { bounds: op_bounds };
-            rewrite_ty(rw_info, Some(bounds), Some(&op), vis)
+            rewrite_ty(rw_info, Some(bounds), Some(&op), rhs_hi, vis)
         }
         (Item(_) | AssocTraitItem(_) | ForeignItem(_), None) => {
-            rewrite_ty(rw_info, Some(bounds), ty_opt, vis)
+            rewrite_ty(rw_info, Some(bounds), ty_opt, rhs_hi, vis)
         }
         (AssocImplItem(_), _) => {
             let result = if let Some(op_bounds) = op_ty {
                 let op = OpaqueType { bounds: op_bounds };
-                rewrite_ty(rw_info, Some(bounds), Some(&op), &DEFAULT_VISIBILITY)
+                rewrite_ty(
+                    rw_info,
+                    Some(bounds),
+                    Some(&op),
+                    rhs_hi,
+                    &DEFAULT_VISIBILITY,
+                )
             } else {
-                rewrite_ty(rw_info, Some(bounds), ty_opt, vis)
+                rewrite_ty(rw_info, Some(bounds), ty_opt, rhs_hi, vis)
             }?;
             match defaultness {
-                ast::Defaultness::Default(..) => Some(format!("default {result}")),
-                _ => Some(result),
+                ast::Defaultness::Default(..) => Ok(format!("default {result}")),
+                _ => Ok(result),
             }
         }
     }
@@ -1721,17 +1759,16 @@ fn rewrite_ty<R: Rewrite>(
     rw_info: &TyAliasRewriteInfo<'_, '_>,
     generic_bounds_opt: Option<&ast::GenericBounds>,
     rhs: Option<&R>,
+    // the span of the end of the RHS (or the end of the generics, if there is no RHS)
+    rhs_hi: BytePos,
     vis: &ast::Visibility,
-) -> Option<String> {
+) -> RewriteResult {
     let mut result = String::with_capacity(128);
     let TyAliasRewriteInfo(context, indent, generics, where_clauses, ident, span) = *rw_info;
     let (before_where_predicates, after_where_predicates) = generics
         .where_clause
         .predicates
         .split_at(where_clauses.split);
-    if !after_where_predicates.is_empty() {
-        return None;
-    }
     result.push_str(&format!("{}type ", format_visibility(context, vis)));
     let ident_str = rewrite_ident(context, ident);
 
@@ -1739,9 +1776,11 @@ fn rewrite_ty<R: Rewrite>(
         result.push_str(ident_str)
     } else {
         // 2 = `= `
-        let g_shape = Shape::indented(indent, context.config)
-            .offset_left(result.len())?
-            .sub_width(2)?;
+        let g_shape = Shape::indented(indent, context.config);
+        let g_shape = g_shape
+            .offset_left(result.len())
+            .and_then(|s| s.sub_width(2))
+            .max_width_error(g_shape.width, span)?;
         let generics_str = rewrite_generics(context, ident_str, generics, g_shape)?;
         result.push_str(&generics_str);
     }
@@ -1749,8 +1788,13 @@ fn rewrite_ty<R: Rewrite>(
     if let Some(bounds) = generic_bounds_opt {
         if !bounds.is_empty() {
             // 2 = `: `
-            let shape = Shape::indented(indent, context.config).offset_left(result.len() + 2)?;
-            let type_bounds = bounds.rewrite(context, shape).map(|s| format!(": {}", s))?;
+            let shape = Shape::indented(indent, context.config);
+            let shape = shape
+                .offset_left(result.len() + 2)
+                .max_width_error(shape.width, span)?;
+            let type_bounds = bounds
+                .rewrite_result(context, shape)
+                .map(|s| format!(": {}", s))?;
             result.push_str(&type_bounds);
         }
     }
@@ -1760,7 +1804,7 @@ fn rewrite_ty<R: Rewrite>(
     if rhs.is_none() {
         option.suppress_comma();
     }
-    let where_clause_str = rewrite_where_clause(
+    let before_where_clause_str = rewrite_where_clause(
         context,
         before_where_predicates,
         where_clauses.before.span,
@@ -1772,14 +1816,20 @@ fn rewrite_ty<R: Rewrite>(
         generics.span.hi(),
         option,
     )?;
-    result.push_str(&where_clause_str);
+    result.push_str(&before_where_clause_str);
 
-    if let Some(ty) = rhs {
-        // If there's a where clause, add a newline before the assignment. Otherwise just add a
-        // space.
-        let has_where = !before_where_predicates.is_empty();
-        if has_where {
+    let mut result = if let Some(ty) = rhs {
+        // If there are any where clauses, add a newline before the assignment.
+        // If there is a before where clause, do not indent, but if there is
+        // only an after where clause, additionally indent the type.
+        if !before_where_predicates.is_empty() {
             result.push_str(&indent.to_string_with_newline(context.config));
+        } else if !after_where_predicates.is_empty() {
+            result.push_str(
+                &indent
+                    .block_indent(context.config)
+                    .to_string_with_newline(context.config),
+            );
         } else {
             result.push(' ');
         }
@@ -1791,13 +1841,20 @@ fn rewrite_ty<R: Rewrite>(
 
         let lhs = match comment_span {
             Some(comment_span)
-                if contains_comment(context.snippet_provider.span_to_snippet(comment_span)?) =>
+                if contains_comment(
+                    context
+                        .snippet_provider
+                        .span_to_snippet(comment_span)
+                        .unknown_error()?,
+                ) =>
             {
-                let comment_shape = if has_where {
+                let comment_shape = if !before_where_predicates.is_empty() {
                     Shape::indented(indent, context.config)
                 } else {
-                    Shape::indented(indent, context.config)
-                        .block_left(context.config.tab_spaces())?
+                    let shape = Shape::indented(indent, context.config);
+                    shape
+                        .block_left(context.config.tab_spaces())
+                        .max_width_error(shape.width, span)?
                 };
 
                 combine_strs_with_missing_comments(
@@ -1812,12 +1869,39 @@ fn rewrite_ty<R: Rewrite>(
             _ => format!("{result}="),
         };
 
-        // 1 = `;`
-        let shape = Shape::indented(indent, context.config).sub_width(1)?;
-        rewrite_assign_rhs(context, lhs, &*ty, &RhsAssignKind::Ty, shape).map(|s| s + ";")
+        // 1 = `;` unless there's a trailing where clause
+        let shape = Shape::indented(indent, context.config);
+        let shape = if after_where_predicates.is_empty() {
+            Shape::indented(indent, context.config)
+                .sub_width(1)
+                .max_width_error(shape.width, span)?
+        } else {
+            shape
+        };
+        rewrite_assign_rhs(context, lhs, &*ty, &RhsAssignKind::Ty, shape)?
     } else {
-        Some(format!("{result};"))
+        result
+    };
+
+    if !after_where_predicates.is_empty() {
+        let option = WhereClauseOption::new(true, WhereClauseSpace::Newline);
+        let after_where_clause_str = rewrite_where_clause(
+            context,
+            after_where_predicates,
+            where_clauses.after.span,
+            context.config.brace_style(),
+            Shape::indented(indent, context.config),
+            false,
+            ";",
+            None,
+            rhs_hi,
+            option,
+        )?;
+        result.push_str(&after_where_clause_str);
     }
+
+    result += ";";
+    Ok(result)
 }
 
 fn type_annotation_spacing(config: &Config) -> (&str, &str) {
@@ -1830,10 +1914,10 @@ fn type_annotation_spacing(config: &Config) -> (&str, &str) {
 pub(crate) fn rewrite_struct_field_prefix(
     context: &RewriteContext<'_>,
     field: &ast::FieldDef,
-) -> Option<String> {
+) -> RewriteResult {
     let vis = format_visibility(context, &field.vis);
     let type_annotation_spacing = type_annotation_spacing(context.config);
-    Some(match field.ident {
+    Ok(match field.ident {
         Some(name) => format!(
             "{}{}{}:",
             vis,
@@ -1846,6 +1930,10 @@ pub(crate) fn rewrite_struct_field_prefix(
 
 impl Rewrite for ast::FieldDef {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         rewrite_struct_field(context, self, shape, 0)
     }
 }
@@ -1855,15 +1943,15 @@ pub(crate) fn rewrite_struct_field(
     field: &ast::FieldDef,
     shape: Shape,
     lhs_max_width: usize,
-) -> Option<String> {
+) -> RewriteResult {
     if contains_skip(&field.attrs) {
-        return Some(context.snippet(field.span()).to_owned());
+        return Ok(context.snippet(field.span()).to_owned());
     }
 
     let type_annotation_spacing = type_annotation_spacing(context.config);
     let prefix = rewrite_struct_field_prefix(context, field)?;
 
-    let attrs_str = field.attrs.rewrite(context, shape)?;
+    let attrs_str = field.attrs.rewrite_result(context, shape)?;
     let attrs_extendable = field.ident.is_none() && is_attributes_extendable(&attrs_str);
     let missing_span = if field.attrs.is_empty() {
         mk_sp(field.span.lo(), field.span.lo())
@@ -1893,12 +1981,14 @@ pub(crate) fn rewrite_struct_field(
     if prefix.is_empty() && !attrs_str.is_empty() && attrs_extendable && spacing.is_empty() {
         spacing.push(' ');
     }
+
     let orig_ty = shape
         .offset_left(overhead + spacing.len())
-        .and_then(|ty_shape| field.ty.rewrite(context, ty_shape));
+        .and_then(|ty_shape| field.ty.rewrite_result(context, ty_shape).ok());
+
     if let Some(ref ty) = orig_ty {
         if !ty.contains('\n') && !contains_comment(context.snippet(missing_span)) {
-            return Some(attr_prefix + &spacing + ty);
+            return Ok(attr_prefix + &spacing + ty);
         }
     }
 
@@ -2045,7 +2135,8 @@ fn rewrite_static(
             comments_span,
             true,
         )
-        .and_then(|res| recover_comment_removed(res, static_parts.span, context))
+        .ok()
+        .map(|res| recover_comment_removed(res, static_parts.span, context))
         .map(|s| if s.ends_with(';') { s } else { s + ";" })
     } else {
         Some(format!("{prefix}{ty_str};"))
@@ -2072,19 +2163,34 @@ impl<'a> Rewrite for OpaqueType<'a> {
 
 impl Rewrite for ast::FnRetTy {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         match *self {
-            ast::FnRetTy::Default(_) => Some(String::new()),
+            ast::FnRetTy::Default(_) => Ok(String::new()),
             ast::FnRetTy::Ty(ref ty) => {
-                if context.config.version() == Version::One
+                let arrow_width = "-> ".len();
+                if context.config.style_edition() <= StyleEdition::Edition2021
                     || context.config.indent_style() == IndentStyle::Visual
                 {
-                    let inner_width = shape.width.checked_sub(3)?;
+                    let inner_width = shape
+                        .width
+                        .checked_sub(arrow_width)
+                        .max_width_error(shape.width, self.span())?;
                     return ty
-                        .rewrite(context, Shape::legacy(inner_width, shape.indent + 3))
+                        .rewrite_result(
+                            context,
+                            Shape::legacy(inner_width, shape.indent + arrow_width),
+                        )
                         .map(|r| format!("-> {}", r));
                 }
 
-                ty.rewrite(context, shape.offset_left(3)?)
+                let shape = shape
+                    .offset_left(arrow_width)
+                    .max_width_error(shape.width, self.span())?;
+
+                ty.rewrite_result(context, shape)
                     .map(|s| format!("-> {}", s))
             }
         }
@@ -2126,9 +2232,11 @@ fn get_missing_param_comments(
     };
 
     let comment_before_colon = rewrite_missing_comment(span_before_colon, shape, context)
+        .ok()
         .filter(|comment| !comment.is_empty())
         .map_or(String::new(), |comment| format!(" {}", comment));
     let comment_after_colon = rewrite_missing_comment(span_after_colon, shape, context)
+        .ok()
         .filter(|comment| !comment.is_empty())
         .map_or(String::new(), |comment| format!("{} ", comment));
     (comment_before_colon, comment_after_colon)
@@ -2136,9 +2244,13 @@ fn get_missing_param_comments(
 
 impl Rewrite for ast::Param {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         let param_attrs_result = self
             .attrs
-            .rewrite(context, Shape::legacy(shape.width, shape.indent))?;
+            .rewrite_result(context, Shape::legacy(shape.width, shape.indent))?;
         // N.B. Doc comments aren't typically valid syntax, but could appear
         // in the presence of certain macros - https://github.com/rust-lang/rustfmt/issues/4936
         let (span, has_multiple_attr_lines, has_doc_comments) = if !self.attrs.is_empty() {
@@ -2164,7 +2276,7 @@ impl Rewrite for ast::Param {
         } else if is_named_param(self) {
             let param_name = &self
                 .pat
-                .rewrite(context, Shape::legacy(shape.width, shape.indent))?;
+                .rewrite_result(context, Shape::legacy(shape.width, shape.indent))?;
             let mut result = combine_strs_with_missing_comments(
                 context,
                 &param_attrs_result,
@@ -2181,10 +2293,13 @@ impl Rewrite for ast::Param {
                 result.push_str(colon_spaces(context.config));
                 result.push_str(&after_comment);
                 let overhead = last_line_width(&result);
-                let max_width = shape.width.checked_sub(overhead)?;
-                if let Some(ty_str) = self
+                let max_width = shape
+                    .width
+                    .checked_sub(overhead)
+                    .max_width_error(shape.width, self.span())?;
+                if let Ok(ty_str) = self
                     .ty
-                    .rewrite(context, Shape::legacy(max_width, shape.indent))
+                    .rewrite_result(context, Shape::legacy(max_width, shape.indent))
                 {
                     result.push_str(&ty_str);
                 } else {
@@ -2206,17 +2321,20 @@ impl Rewrite for ast::Param {
                     result.push_str(colon_spaces(context.config));
                     result.push_str(&after_comment);
                     let overhead = last_line_width(&result);
-                    let max_width = shape.width.checked_sub(overhead)?;
+                    let max_width = shape
+                        .width
+                        .checked_sub(overhead)
+                        .max_width_error(shape.width, self.span())?;
                     let ty_str = self
                         .ty
-                        .rewrite(context, Shape::legacy(max_width, shape.indent))?;
+                        .rewrite_result(context, Shape::legacy(max_width, shape.indent))?;
                     result.push_str(&ty_str);
                 }
             }
 
-            Some(result)
+            Ok(result)
         } else {
-            self.ty.rewrite(context, shape)
+            self.ty.rewrite_result(context, shape)
         }
     }
 }
@@ -2228,17 +2346,17 @@ fn rewrite_explicit_self(
     span: Span,
     shape: Shape,
     has_multiple_attr_lines: bool,
-) -> Option<String> {
+) -> RewriteResult {
     match explicit_self.node {
         ast::SelfKind::Region(lt, m) => {
             let mut_str = format_mutability(m);
             match lt {
                 Some(ref l) => {
-                    let lifetime_str = l.rewrite(
+                    let lifetime_str = l.rewrite_result(
                         context,
                         Shape::legacy(context.config.max_width(), Indent::empty()),
                     )?;
-                    Some(combine_strs_with_missing_comments(
+                    Ok(combine_strs_with_missing_comments(
                         context,
                         param_attrs,
                         &format!("&{lifetime_str} {mut_str}self"),
@@ -2247,7 +2365,7 @@ fn rewrite_explicit_self(
                         !has_multiple_attr_lines,
                     )?)
                 }
-                None => Some(combine_strs_with_missing_comments(
+                None => Ok(combine_strs_with_missing_comments(
                     context,
                     param_attrs,
                     &format!("&{mut_str}self"),
@@ -2258,12 +2376,12 @@ fn rewrite_explicit_self(
             }
         }
         ast::SelfKind::Explicit(ref ty, mutability) => {
-            let type_str = ty.rewrite(
+            let type_str = ty.rewrite_result(
                 context,
                 Shape::legacy(context.config.max_width(), Indent::empty()),
             )?;
 
-            Some(combine_strs_with_missing_comments(
+            Ok(combine_strs_with_missing_comments(
                 context,
                 param_attrs,
                 &format!("{}self: {}", format_mutability(mutability), type_str),
@@ -2272,7 +2390,7 @@ fn rewrite_explicit_self(
                 !has_multiple_attr_lines,
             )?)
         }
-        ast::SelfKind::Value(mutability) => Some(combine_strs_with_missing_comments(
+        ast::SelfKind::Value(mutability) => Ok(combine_strs_with_missing_comments(
             context,
             param_attrs,
             &format!("{}self", format_mutability(mutability)),
@@ -2326,7 +2444,7 @@ fn rewrite_fn_base(
     fn_sig: &FnSig<'_>,
     span: Span,
     fn_brace_style: FnBraceStyle,
-) -> Option<(String, bool, bool)> {
+) -> Result<(String, bool, bool), RewriteError> {
     let mut force_new_line_for_brace = false;
 
     let where_clause = &fn_sig.generics.where_clause;
@@ -2370,7 +2488,7 @@ fn rewrite_fn_base(
     // return type later anyway.
     let ret_str = fd
         .output
-        .rewrite(context, Shape::indented(indent, context.config))?;
+        .rewrite_result(context, Shape::indented(indent, context.config))?;
 
     let multi_line_ret_str = ret_str.contains('\n');
     let ret_str_len = if multi_line_ret_str { 0 } else { ret_str.len() };
@@ -2383,7 +2501,7 @@ fn rewrite_fn_base(
         ret_str_len,
         fn_brace_style,
         multi_line_ret_str,
-    )?;
+    );
 
     debug!(
         "rewrite_fn_base: one_line_budget: {}, multi_line_budget: {}, param_indent: {:?}",
@@ -2452,7 +2570,7 @@ fn rewrite_fn_base(
             .last()
             .map_or(false, |last_line| last_line.contains("//"));
 
-        if context.config.version() == Version::Two {
+        if context.config.style_edition() >= StyleEdition::Edition2024 {
             if closing_paren_overflow_max_width {
                 result.push(')');
                 result.push_str(&indent.to_string_with_newline(context.config));
@@ -2495,7 +2613,7 @@ fn rewrite_fn_base(
             }
         };
         let ret_shape = if ret_should_indent {
-            if context.config.version() == Version::One
+            if context.config.style_edition() <= StyleEdition::Edition2021
                 || context.config.indent_style() == IndentStyle::Visual
             {
                 let indent = if param_str.is_empty() {
@@ -2528,7 +2646,7 @@ fn rewrite_fn_base(
                 ret_shape
             }
         } else {
-            if context.config.version() == Version::Two {
+            if context.config.style_edition() >= StyleEdition::Edition2024 {
                 if !param_str.is_empty() || !no_params_and_over_max_width {
                     result.push(' ');
                 }
@@ -2545,7 +2663,7 @@ fn rewrite_fn_base(
         if multi_line_ret_str || ret_should_indent {
             // Now that we know the proper indent and width, we need to
             // re-layout the return type.
-            let ret_str = fd.output.rewrite(context, ret_shape)?;
+            let ret_str = fd.output.rewrite_result(context, ret_shape)?;
             result.push_str(&ret_str);
         } else {
             result.push_str(&ret_str);
@@ -2617,7 +2735,7 @@ fn rewrite_fn_base(
                 context,
                 last_line_width(&result),
             ) {
-                Some(ref missing_comment) if !missing_comment.is_empty() => {
+                Ok(ref missing_comment) if !missing_comment.is_empty() => {
                     result.push_str(missing_comment);
                     force_new_line_for_brace = true;
                 }
@@ -2632,7 +2750,7 @@ fn rewrite_fn_base(
     force_new_line_for_brace |= ends_with_comment;
     force_new_line_for_brace |=
         is_params_multi_lined && context.config.where_single_line() && !where_clause_str.is_empty();
-    Some((result, ends_with_comment, force_new_line_for_brace))
+    Ok((result, ends_with_comment, force_new_line_for_brace))
 }
 
 /// Kind of spaces to put before `where`.
@@ -2703,7 +2821,7 @@ fn rewrite_params(
     param_indent: Indent,
     span: Span,
     variadic: bool,
-) -> Option<String> {
+) -> RewriteResult {
     if params.is_empty() {
         let comment = context
             .snippet(mk_sp(
@@ -2712,7 +2830,7 @@ fn rewrite_params(
                 span.hi() - BytePos(1),
             ))
             .trim();
-        return Some(comment.to_owned());
+        return Ok(comment.to_owned());
     }
     let param_items: Vec<_> = itemize_list(
         context.snippet_provider,
@@ -2723,8 +2841,8 @@ fn rewrite_params(
         |param| param.ty.span.hi(),
         |param| {
             param
-                .rewrite(context, Shape::legacy(multi_line_budget, param_indent))
-                .or_else(|| Some(context.snippet(param.span()).to_owned()))
+                .rewrite_result(context, Shape::legacy(multi_line_budget, param_indent))
+                .or_else(|_| Ok(context.snippet(param.span()).to_owned()))
         },
         span.lo(),
         span.hi(),
@@ -2772,7 +2890,7 @@ fn compute_budgets_for_params(
     ret_str_len: usize,
     fn_brace_style: FnBraceStyle,
     force_vertical_layout: bool,
-) -> Option<(usize, usize, Indent)> {
+) -> (usize, usize, Indent) {
     debug!(
         "compute_budgets_for_params {} {:?}, {}, {:?}",
         result.len(),
@@ -2809,7 +2927,7 @@ fn compute_budgets_for_params(
                 }
             };
 
-            return Some((one_line_budget, multi_line_budget, indent));
+            return (one_line_budget, multi_line_budget, indent);
         }
     }
 
@@ -2821,7 +2939,7 @@ fn compute_budgets_for_params(
         // Account for `)` and possibly ` {`.
         IndentStyle::Visual => new_indent.width() + if ret_str_len == 0 { 1 } else { 3 },
     };
-    Some((0, context.budget(used_space), new_indent))
+    (0, context.budget(used_space), new_indent)
 }
 
 fn newline_for_brace(config: &Config, where_clause: &ast::WhereClause) -> FnBraceStyle {
@@ -2846,12 +2964,12 @@ fn rewrite_generics(
     ident: &str,
     generics: &ast::Generics,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     // FIXME: convert bounds to where-clauses where they get too big or if
     // there is a where-clause at all.
 
     if generics.params.is_empty() {
-        return Some(ident.to_owned());
+        return Ok(ident.to_owned());
     }
 
     let params = generics.params.iter();
@@ -2881,7 +2999,7 @@ fn rewrite_where_clause_rfc_style(
     span_end: Option<BytePos>,
     span_end_before_where: BytePos,
     where_clause_option: WhereClauseOption,
-) -> Option<String> {
+) -> RewriteResult {
     let (where_keyword, allow_single_line) = rewrite_where_keyword(
         context,
         predicates,
@@ -2895,8 +3013,9 @@ fn rewrite_where_clause_rfc_style(
     let clause_shape = shape
         .block()
         .with_max_width(context.config)
-        .block_left(context.config.tab_spaces())?
-        .sub_width(1)?;
+        .block_left(context.config.tab_spaces())
+        .and_then(|s| s.sub_width(1))
+        .max_width_error(shape.width, where_span)?;
     let force_single_line = context.config.where_single_line()
         && predicates.len() == 1
         && !where_clause_option.veto_single_line;
@@ -2921,7 +3040,7 @@ fn rewrite_where_clause_rfc_style(
             clause_shape.indent.to_string_with_newline(context.config)
         };
 
-    Some(format!("{where_keyword}{clause_sep}{preds_str}"))
+    Ok(format!("{where_keyword}{clause_sep}{preds_str}"))
 }
 
 /// Rewrite `where` and comment around it.
@@ -2932,12 +3051,13 @@ fn rewrite_where_keyword(
     shape: Shape,
     span_end_before_where: BytePos,
     where_clause_option: WhereClauseOption,
-) -> Option<(String, bool)> {
+) -> Result<(String, bool), RewriteError> {
     let block_shape = shape.block().with_max_width(context.config);
     // 1 = `,`
     let clause_shape = block_shape
-        .block_left(context.config.tab_spaces())?
-        .sub_width(1)?;
+        .block_left(context.config.tab_spaces())
+        .and_then(|s| s.sub_width(1))
+        .max_width_error(block_shape.width, where_span)?;
 
     let comment_separator = |comment: &str, shape: Shape| {
         if comment.is_empty() {
@@ -2968,7 +3088,7 @@ fn rewrite_where_keyword(
         && comment_before.is_empty()
         && comment_after.is_empty();
 
-    Some((result, allow_single_line))
+    Ok((result, allow_single_line))
 }
 
 /// Rewrite bounds on a where clause.
@@ -2980,7 +3100,7 @@ fn rewrite_bounds_on_where_clause(
     span_end: Option<BytePos>,
     where_clause_option: WhereClauseOption,
     force_single_line: bool,
-) -> Option<String> {
+) -> RewriteResult {
     let span_start = predicates[0].span().lo();
     // If we don't have the start of the next span, then use the end of the
     // predicates, but that means we miss comments.
@@ -2994,7 +3114,7 @@ fn rewrite_bounds_on_where_clause(
         ",",
         |pred| pred.span().lo(),
         |pred| pred.span().hi(),
-        |pred| pred.rewrite(context, shape),
+        |pred| pred.rewrite_result(context, shape),
         span_start,
         span_end,
         false,
@@ -3013,7 +3133,7 @@ fn rewrite_bounds_on_where_clause(
         DefinitiveListTactic::Vertical
     };
 
-    let preserve_newline = context.config.version() == Version::One;
+    let preserve_newline = context.config.style_edition() <= StyleEdition::Edition2021;
 
     let fmt = ListFormatting::new(shape, context.config)
         .tactic(shape_tactic)
@@ -3033,9 +3153,9 @@ fn rewrite_where_clause(
     span_end: Option<BytePos>,
     span_end_before_where: BytePos,
     where_clause_option: WhereClauseOption,
-) -> Option<String> {
+) -> RewriteResult {
     if predicates.is_empty() {
-        return Some(String::new());
+        return Ok(String::new());
     }
 
     if context.config.indent_style() == IndentStyle::Block {
@@ -3075,7 +3195,7 @@ fn rewrite_where_clause(
         ",",
         |pred| pred.span().lo(),
         |pred| pred.span().hi(),
-        |pred| pred.rewrite(context, Shape::legacy(budget, offset)),
+        |pred| pred.rewrite_result(context, Shape::legacy(budget, offset)),
         span_start,
         span_end,
         false,
@@ -3113,13 +3233,13 @@ fn rewrite_where_clause(
         || preds_str.contains('\n')
         || shape.indent.width() + " where ".len() + preds_str.len() + end_length > shape.width
     {
-        Some(format!(
+        Ok(format!(
             "\n{}where {}",
             (shape.indent + extra_indent).to_string(context.config),
             preds_str
         ))
     } else {
-        Some(format!(" where {preds_str}"))
+        Ok(format!(" where {preds_str}"))
     }
 }
 
@@ -3140,14 +3260,14 @@ fn rewrite_comments_before_after_where(
     span_before_where: Span,
     span_after_where: Span,
     shape: Shape,
-) -> Option<(String, String)> {
+) -> Result<(String, String), RewriteError> {
     let before_comment = rewrite_missing_comment(span_before_where, shape, context)?;
     let after_comment = rewrite_missing_comment(
         span_after_where,
         shape.block_indent(context.config.tab_spaces()),
         context,
     )?;
-    Some((before_comment, after_comment))
+    Ok((before_comment, after_comment))
 }
 
 fn format_header(
@@ -3169,7 +3289,7 @@ fn format_header(
         .opt_span_before(mk_sp(vis.span.lo(), ident.span.hi()), item_name.trim())
     {
         let missing_span = mk_sp(after_vis, before_item_name);
-        if let Some(result_with_comment) = combine_strs_with_missing_comments(
+        if let Ok(result_with_comment) = combine_strs_with_missing_comments(
             context,
             &result,
             item_name,
@@ -3203,7 +3323,7 @@ fn format_generics(
     used_width: usize,
 ) -> Option<String> {
     let shape = Shape::legacy(context.budget(used_width + offset.width()), offset);
-    let mut result = rewrite_generics(context, "", generics, shape)?;
+    let mut result = rewrite_generics(context, "", generics, shape).ok()?;
 
     // If the generics are not parameterized then generics.span.hi() == 0,
     // so we use span.lo(), which is the position after `struct Foo`.
@@ -3229,7 +3349,8 @@ fn format_generics(
             Some(span.hi()),
             span_end_before_where,
             option,
-        )?;
+        )
+        .ok()?;
         result.push_str(&where_clause_str);
         (
             brace_pos == BracePos::ForceSameLine || brace_style == BraceStyle::PreferSameLine,
@@ -3253,7 +3374,8 @@ fn format_generics(
                 ),
                 shape,
                 context,
-            ),
+            )
+            .ok(),
         )
     };
     // add missing comments
@@ -3295,7 +3417,11 @@ fn format_generics(
 
 impl Rewrite for ast::ForeignItem {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
-        let attrs_str = self.attrs.rewrite(context, shape)?;
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
+        let attrs_str = self.attrs.rewrite_result(context, shape)?;
         // Drop semicolon or it will be interpreted as comment.
         // FIXME: this may be a faulty span from libsyntax.
         let span = mk_sp(self.span.lo(), self.span.hi() - BytePos(1));
@@ -3328,7 +3454,7 @@ impl Rewrite for ast::ForeignItem {
                         defaultness,
                         Some(&inner_attrs),
                     );
-                    Some(visitor.buffer.to_owned())
+                    Ok(visitor.buffer.to_owned())
                 } else {
                     rewrite_fn_base(
                         context,
@@ -3360,7 +3486,9 @@ impl Rewrite for ast::ForeignItem {
                     prefix,
                     &static_foreign_item.ty,
                     &RhsAssignKind::Ty,
-                    shape.sub_width(1)?,
+                    shape
+                        .sub_width(1)
+                        .max_width_error(shape.width, static_foreign_item.ty.span)?,
                 )
                 .map(|s| s + ";")
             }
@@ -3421,6 +3549,7 @@ fn rewrite_attrs(
         shape,
         allow_extend,
     )
+    .ok()
 }
 
 /// Rewrite an inline mod.
diff --git a/src/tools/rustfmt/src/lib.rs b/src/tools/rustfmt/src/lib.rs
index 4263a49fd72..08cda6913b9 100644
--- a/src/tools/rustfmt/src/lib.rs
+++ b/src/tools/rustfmt/src/lib.rs
@@ -5,9 +5,6 @@
 #![allow(clippy::match_like_matches_macro)]
 #![allow(unreachable_pub)]
 
-// #[macro_use]
-// extern crate tracing;
-
 // N.B. these crates are loaded from the sysroot, so they need extern crate.
 extern crate rustc_ast;
 extern crate rustc_ast_pretty;
@@ -48,8 +45,8 @@ use crate::shape::Indent;
 use crate::utils::indent_next_line;
 
 pub use crate::config::{
-    load_config, CliOptions, Color, Config, Edition, EmitMode, FileLines, FileName, NewlineStyle,
-    Range, Verbosity,
+    CliOptions, Color, Config, Edition, EmitMode, FileLines, FileName, NewlineStyle, Range,
+    StyleEdition, Verbosity, Version, load_config,
 };
 
 pub use crate::format_report_formatter::{FormatReportFormatter, FormatReportFormatterBuilder};
@@ -94,6 +91,7 @@ mod rewrite;
 pub(crate) mod rustfmt_diff;
 mod shape;
 mod skip;
+mod sort;
 pub(crate) mod source_file;
 pub(crate) mod source_map;
 mod spanned;
diff --git a/src/tools/rustfmt/src/lists.rs b/src/tools/rustfmt/src/lists.rs
index 41afef279e9..415144a8abc 100644
--- a/src/tools/rustfmt/src/lists.rs
+++ b/src/tools/rustfmt/src/lists.rs
@@ -5,10 +5,10 @@ use std::iter::Peekable;
 
 use rustc_span::BytePos;
 
-use crate::comment::{find_comment_end, rewrite_comment, FindUncommented};
+use crate::comment::{FindUncommented, find_comment_end, rewrite_comment};
 use crate::config::lists::*;
 use crate::config::{Config, IndentStyle};
-use crate::rewrite::RewriteContext;
+use crate::rewrite::{RewriteContext, RewriteError, RewriteResult};
 use crate::shape::{Indent, Shape};
 use crate::utils::{
     count_newlines, first_line_width, last_line_width, mk_sp, starts_with_newline,
@@ -125,18 +125,18 @@ pub(crate) struct ListItem {
     pub(crate) pre_comment_style: ListItemCommentStyle,
     // Item should include attributes and doc comments. None indicates a failed
     // rewrite.
-    pub(crate) item: Option<String>,
+    pub(crate) item: RewriteResult,
     pub(crate) post_comment: Option<String>,
     // Whether there is extra whitespace before this item.
     pub(crate) new_lines: bool,
 }
 
 impl ListItem {
-    pub(crate) fn empty() -> ListItem {
+    pub(crate) fn from_item(item: RewriteResult) -> ListItem {
         ListItem {
             pre_comment: None,
             pre_comment_style: ListItemCommentStyle::None,
-            item: None,
+            item: item,
             post_comment: None,
             new_lines: false,
         }
@@ -185,7 +185,7 @@ impl ListItem {
         ListItem {
             pre_comment: None,
             pre_comment_style: ListItemCommentStyle::None,
-            item: Some(s.into()),
+            item: Ok(s.into()),
             post_comment: None,
             new_lines: false,
         }
@@ -197,7 +197,11 @@ impl ListItem {
             !matches!(*s, Some(ref s) if !s.is_empty())
         }
 
-        !(empty(&self.pre_comment) && empty(&self.item) && empty(&self.post_comment))
+        fn empty_result(s: &RewriteResult) -> bool {
+            !matches!(*s, Ok(ref s) if !s.is_empty())
+        }
+
+        !(empty(&self.pre_comment) && empty_result(&self.item) && empty(&self.post_comment))
     }
 }
 
@@ -257,7 +261,7 @@ where
 }
 
 // Format a list of commented items into a string.
-pub(crate) fn write_list<I, T>(items: I, formatting: &ListFormatting<'_>) -> Option<String>
+pub(crate) fn write_list<I, T>(items: I, formatting: &ListFormatting<'_>) -> RewriteResult
 where
     I: IntoIterator<Item = T> + Clone,
     T: AsRef<ListItem>,
@@ -281,7 +285,7 @@ where
     let indent_str = &formatting.shape.indent.to_string(formatting.config);
     while let Some((i, item)) = iter.next() {
         let item = item.as_ref();
-        let inner_item = item.item.as_ref()?;
+        let inner_item = item.item.as_ref().or_else(|err| Err(err.clone()))?;
         let first = i == 0;
         let last = iter.peek().is_none();
         let mut separate = match sep_place {
@@ -516,7 +520,7 @@ where
         prev_item_is_nested_import = inner_item.contains("::");
     }
 
-    Some(result)
+    Ok(result)
 }
 
 fn max_width_of_item_with_post_comment<I, T>(
@@ -741,7 +745,7 @@ where
     I: Iterator<Item = T>,
     F1: Fn(&T) -> BytePos,
     F2: Fn(&T) -> BytePos,
-    F3: Fn(&T) -> Option<String>,
+    F3: Fn(&T) -> RewriteResult,
 {
     type Item = ListItem;
 
@@ -775,8 +779,9 @@ where
             ListItem {
                 pre_comment,
                 pre_comment_style,
+                // leave_last is set to true only for rewrite_items
                 item: if self.inner.peek().is_none() && self.leave_last {
-                    None
+                    Err(RewriteError::SkipFormatting)
                 } else {
                     (self.get_item_string)(&item)
                 },
@@ -805,7 +810,7 @@ where
     I: Iterator<Item = T>,
     F1: Fn(&T) -> BytePos,
     F2: Fn(&T) -> BytePos,
-    F3: Fn(&T) -> Option<String>,
+    F3: Fn(&T) -> RewriteResult,
 {
     ListItems {
         snippet_provider,
diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs
index 524fc666fae..5a35e115d8f 100644
--- a/src/tools/rustfmt/src/macros.rs
+++ b/src/tools/rustfmt/src/macros.rs
@@ -10,35 +10,37 @@
 // and those with brackets will be formatted as array literals.
 
 use std::collections::HashMap;
-use std::panic::{catch_unwind, AssertUnwindSafe};
+use std::panic::{AssertUnwindSafe, catch_unwind};
 
 use rustc_ast::token::{BinOpToken, Delimiter, Token, TokenKind};
 use rustc_ast::tokenstream::{RefTokenTreeCursor, TokenStream, TokenTree};
 use rustc_ast::{ast, ptr};
 use rustc_ast_pretty::pprust;
 use rustc_span::{
+    BytePos, DUMMY_SP, Span, Symbol,
     symbol::{self, kw},
-    BytePos, Span, Symbol, DUMMY_SP,
 };
 use tracing::debug;
 
 use crate::comment::{
-    contains_comment, CharClasses, FindUncommented, FullCodeCharKind, LineClasses,
+    CharClasses, FindUncommented, FullCodeCharKind, LineClasses, contains_comment,
 };
+use crate::config::StyleEdition;
 use crate::config::lists::*;
-use crate::config::Version;
-use crate::expr::{rewrite_array, rewrite_assign_rhs, RhsAssignKind};
-use crate::lists::{itemize_list, write_list, ListFormatting};
+use crate::expr::{RhsAssignKind, rewrite_array, rewrite_assign_rhs};
+use crate::lists::{ListFormatting, itemize_list, write_list};
 use crate::overflow;
 use crate::parse::macros::lazy_static::parse_lazy_static;
-use crate::parse::macros::{parse_expr, parse_macro_args, ParsedMacroArgs};
-use crate::rewrite::{Rewrite, RewriteContext};
+use crate::parse::macros::{ParsedMacroArgs, parse_expr, parse_macro_args};
+use crate::rewrite::{
+    MacroErrorKind, Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult,
+};
 use crate::shape::{Indent, Shape};
 use crate::source_map::SpanUtils;
 use crate::spanned::Spanned;
 use crate::utils::{
-    filtered_str_fits, format_visibility, indent_next_line, is_empty_line, mk_sp,
-    remove_trailing_white_spaces, rewrite_ident, trim_left_preserve_layout, NodeIdExt,
+    NodeIdExt, filtered_str_fits, format_visibility, indent_next_line, is_empty_line, mk_sp,
+    remove_trailing_white_spaces, rewrite_ident, trim_left_preserve_layout,
 };
 use crate::visitor::FmtVisitor;
 
@@ -72,22 +74,30 @@ impl MacroArg {
 
 impl Rewrite for ast::Item {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         let mut visitor = crate::visitor::FmtVisitor::from_context(context);
         visitor.block_indent = shape.indent;
         visitor.last_pos = self.span().lo();
         visitor.visit_item(self);
-        Some(visitor.buffer.to_owned())
+        Ok(visitor.buffer.to_owned())
     }
 }
 
 impl Rewrite for MacroArg {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         match *self {
-            MacroArg::Expr(ref expr) => expr.rewrite(context, shape),
-            MacroArg::Ty(ref ty) => ty.rewrite(context, shape),
-            MacroArg::Pat(ref pat) => pat.rewrite(context, shape),
-            MacroArg::Item(ref item) => item.rewrite(context, shape),
-            MacroArg::Keyword(ident, _) => Some(ident.name.to_string()),
+            MacroArg::Expr(ref expr) => expr.rewrite_result(context, shape),
+            MacroArg::Ty(ref ty) => ty.rewrite_result(context, shape),
+            MacroArg::Pat(ref pat) => pat.rewrite_result(context, shape),
+            MacroArg::Item(ref item) => item.rewrite_result(context, shape),
+            MacroArg::Keyword(ident, _) => Ok(ident.name.to_string()),
         }
     }
 }
@@ -111,12 +121,14 @@ fn rewrite_macro_name(
 }
 
 // Use this on failing to format the macro call.
+// TODO(ding-young) We should also report macro parse failure to tell users why given snippet
+// is left unformatted. One possible improvement is appending formatting error to context.report
 fn return_macro_parse_failure_fallback(
     context: &RewriteContext<'_>,
     indent: Indent,
     position: MacroPosition,
     span: Span,
-) -> Option<String> {
+) -> RewriteResult {
     // Mark this as a failure however we format it
     context.macro_rewrite_failure.replace(true);
 
@@ -134,7 +146,8 @@ fn return_macro_parse_failure_fallback(
         })
         .unwrap_or(false);
     if is_like_block_indent_style {
-        return trim_left_preserve_layout(context.snippet(span), indent, context.config);
+        return trim_left_preserve_layout(context.snippet(span), indent, context.config)
+            .macro_error(MacroErrorKind::Unknown, span);
     }
 
     context.skipped_range.borrow_mut().push((
@@ -147,7 +160,7 @@ fn return_macro_parse_failure_fallback(
     if position == MacroPosition::Item {
         snippet.push(';');
     }
-    Some(snippet)
+    Ok(snippet)
 }
 
 pub(crate) fn rewrite_macro(
@@ -156,13 +169,13 @@ pub(crate) fn rewrite_macro(
     context: &RewriteContext<'_>,
     shape: Shape,
     position: MacroPosition,
-) -> Option<String> {
+) -> RewriteResult {
     let should_skip = context
         .skip_context
         .macros
         .skip(context.snippet(mac.path.span));
     if should_skip {
-        None
+        Err(RewriteError::SkipFormatting)
     } else {
         let guard = context.enter_macro();
         let result = catch_unwind(AssertUnwindSafe(|| {
@@ -176,9 +189,16 @@ pub(crate) fn rewrite_macro(
             )
         }));
         match result {
-            Err(..) | Ok(None) => {
+            Err(..) => {
                 context.macro_rewrite_failure.replace(true);
-                None
+                Err(RewriteError::MacroFailure {
+                    kind: MacroErrorKind::Unknown,
+                    span: mac.span(),
+                })
+            }
+            Ok(Err(e)) => {
+                context.macro_rewrite_failure.replace(true);
+                Err(e)
             }
             Ok(rw) => rw,
         }
@@ -192,11 +212,11 @@ fn rewrite_macro_inner(
     shape: Shape,
     position: MacroPosition,
     is_nested_macro: bool,
-) -> Option<String> {
+) -> RewriteResult {
     if context.config.use_try_shorthand() {
         if let Some(expr) = convert_try_mac(mac, context) {
             context.leave_macro();
-            return expr.rewrite(context, shape);
+            return expr.rewrite_result(context, shape);
         }
     }
 
@@ -216,21 +236,27 @@ fn rewrite_macro_inner(
     if ts.is_empty() && !has_comment {
         return match style {
             Delimiter::Parenthesis if position == MacroPosition::Item => {
-                Some(format!("{macro_name}();"))
+                Ok(format!("{macro_name}();"))
             }
-            Delimiter::Bracket if position == MacroPosition::Item => {
-                Some(format!("{macro_name}[];"))
-            }
-            Delimiter::Parenthesis => Some(format!("{macro_name}()")),
-            Delimiter::Bracket => Some(format!("{macro_name}[]")),
-            Delimiter::Brace => Some(format!("{macro_name} {{}}")),
+            Delimiter::Bracket if position == MacroPosition::Item => Ok(format!("{macro_name}[];")),
+            Delimiter::Parenthesis => Ok(format!("{macro_name}()")),
+            Delimiter::Bracket => Ok(format!("{macro_name}[]")),
+            Delimiter::Brace => Ok(format!("{macro_name} {{}}")),
             _ => unreachable!(),
         };
     }
     // Format well-known macros which cannot be parsed as a valid AST.
     if macro_name == "lazy_static!" && !has_comment {
-        if let success @ Some(..) = format_lazy_static(context, shape, ts.clone()) {
-            return success;
+        match format_lazy_static(context, shape, ts.clone(), mac.span()) {
+            Ok(rw) => return Ok(rw),
+            Err(err) => match err {
+                // We will move on to parsing macro args just like other macros
+                // if we could not parse lazy_static! with known syntax
+                RewriteError::MacroFailure { kind, span: _ }
+                    if kind == MacroErrorKind::ParseFailure => {}
+                // If formatting fails even though parsing succeeds, return the err early
+                _ => return Err(err),
+            },
         }
     }
 
@@ -267,7 +293,7 @@ fn rewrite_macro_inner(
         Delimiter::Parenthesis => {
             // Handle special case: `vec!(expr; expr)`
             if vec_with_semi {
-                handle_vec_semi(context, shape, arg_vec, macro_name, style)
+                handle_vec_semi(context, shape, arg_vec, macro_name, style, mac.span())
             } else {
                 // Format macro invocation as function call, preserve the trailing
                 // comma because not all macros support them.
@@ -293,7 +319,7 @@ fn rewrite_macro_inner(
         Delimiter::Bracket => {
             // Handle special case: `vec![expr; expr]`
             if vec_with_semi {
-                handle_vec_semi(context, shape, arg_vec, macro_name, style)
+                handle_vec_semi(context, shape, arg_vec, macro_name, style, mac.span())
             } else {
                 // If we are rewriting `vec!` macro or other special macros,
                 // then we can rewrite this as a usual array literal.
@@ -323,7 +349,7 @@ fn rewrite_macro_inner(
                     _ => "",
                 };
 
-                Some(format!("{rewrite}{comma}"))
+                Ok(format!("{rewrite}{comma}"))
             }
         }
         Delimiter::Brace => {
@@ -332,8 +358,8 @@ fn rewrite_macro_inner(
             // anything in between the braces (for now).
             let snippet = context.snippet(mac.span()).trim_start_matches(|c| c != '{');
             match trim_left_preserve_layout(snippet, shape.indent, context.config) {
-                Some(macro_body) => Some(format!("{macro_name} {macro_body}")),
-                None => Some(format!("{macro_name} {snippet}")),
+                Some(macro_body) => Ok(format!("{macro_name} {macro_body}")),
+                None => Ok(format!("{macro_name} {snippet}")),
             }
         }
         _ => unreachable!(),
@@ -346,28 +372,32 @@ fn handle_vec_semi(
     arg_vec: Vec<MacroArg>,
     macro_name: String,
     delim_token: Delimiter,
-) -> Option<String> {
+    span: Span,
+) -> RewriteResult {
     let (left, right) = match delim_token {
         Delimiter::Parenthesis => ("(", ")"),
         Delimiter::Bracket => ("[", "]"),
         _ => unreachable!(),
     };
 
-    let mac_shape = shape.offset_left(macro_name.len())?;
+    // Should we return MaxWidthError, Or Macro failure
+    let mac_shape = shape
+        .offset_left(macro_name.len())
+        .max_width_error(shape.width, span)?;
     // 8 = `vec![]` + `; ` or `vec!()` + `; `
     let total_overhead = 8;
     let nested_shape = mac_shape.block_indent(context.config.tab_spaces());
-    let lhs = arg_vec[0].rewrite(context, nested_shape)?;
-    let rhs = arg_vec[1].rewrite(context, nested_shape)?;
+    let lhs = arg_vec[0].rewrite_result(context, nested_shape)?;
+    let rhs = arg_vec[1].rewrite_result(context, nested_shape)?;
     if !lhs.contains('\n')
         && !rhs.contains('\n')
         && lhs.len() + rhs.len() + total_overhead <= shape.width
     {
         // macro_name(lhs; rhs) or macro_name[lhs; rhs]
-        Some(format!("{macro_name}{left}{lhs}; {rhs}{right}"))
+        Ok(format!("{macro_name}{left}{lhs}; {rhs}{right}"))
     } else {
         // macro_name(\nlhs;\nrhs\n) or macro_name[\nlhs;\nrhs\n]
-        Some(format!(
+        Ok(format!(
             "{}{}{}{};{}{}{}{}",
             macro_name,
             left,
@@ -385,7 +415,7 @@ fn rewrite_empty_macro_def_body(
     context: &RewriteContext<'_>,
     span: Span,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     // Create an empty, dummy `ast::Block` representing an empty macro body
     let block = ast::Block {
         stmts: vec![].into(),
@@ -395,7 +425,7 @@ fn rewrite_empty_macro_def_body(
         tokens: None,
         could_be_bare_literal: false,
     };
-    block.rewrite(context, shape)
+    block.rewrite_result(context, shape)
 }
 
 pub(crate) fn rewrite_macro_def(
@@ -406,8 +436,8 @@ pub(crate) fn rewrite_macro_def(
     ident: symbol::Ident,
     vis: &ast::Visibility,
     span: Span,
-) -> Option<String> {
-    let snippet = Some(remove_trailing_white_spaces(context.snippet(span)));
+) -> RewriteResult {
+    let snippet = Ok(remove_trailing_white_spaces(context.snippet(span)));
     if snippet.as_ref().map_or(true, |s| s.ends_with(';')) {
         return snippet;
     }
@@ -442,7 +472,7 @@ pub(crate) fn rewrite_macro_def(
         let lo = context.snippet_provider.span_before(span, "{");
         result += " ";
         result += &rewrite_empty_macro_def_body(context, span.with_lo(lo), shape)?;
-        return Some(result);
+        return Ok(result);
     }
 
     let branch_items = itemize_list(
@@ -453,13 +483,14 @@ pub(crate) fn rewrite_macro_def(
         |branch| branch.span.lo(),
         |branch| branch.span.hi(),
         |branch| match branch.rewrite(context, arm_shape, multi_branch_style) {
-            Some(v) => Some(v),
+            Ok(v) => Ok(v),
             // if the rewrite returned None because a macro could not be rewritten, then return the
             // original body
-            None if context.macro_rewrite_failure.get() => {
-                Some(context.snippet(branch.body).trim().to_string())
+            // TODO(ding-young) report rewrite error even if we return Ok with original snippet
+            Err(_) if context.macro_rewrite_failure.get() => {
+                Ok(context.snippet(branch.body).trim().to_string())
             }
-            None => None,
+            Err(e) => Err(e),
         },
         context.snippet_provider.span_after(span, "{"),
         span.hi(),
@@ -478,8 +509,8 @@ pub(crate) fn rewrite_macro_def(
     }
 
     match write_list(&branch_items, &fmt) {
-        Some(ref s) => result += s,
-        None => return snippet,
+        Ok(ref s) => result += s,
+        Err(_) => return snippet,
     }
 
     if multi_branch_style {
@@ -487,7 +518,7 @@ pub(crate) fn rewrite_macro_def(
         result += "}";
     }
 
-    Some(result)
+    Ok(result)
 }
 
 fn register_metavariable(
@@ -639,12 +670,13 @@ impl MacroArgKind {
         context: &RewriteContext<'_>,
         shape: Shape,
         use_multiple_lines: bool,
-    ) -> Option<String> {
-        let rewrite_delimited_inner = |delim_tok, args| -> Option<(String, String, String)> {
+    ) -> RewriteResult {
+        type DelimitedArgsRewrite = Result<(String, String, String), RewriteError>;
+        let rewrite_delimited_inner = |delim_tok, args| -> DelimitedArgsRewrite {
             let inner = wrap_macro_args(context, args, shape)?;
             let (lhs, rhs) = delim_token_to_str(context, delim_tok, shape, false, inner.is_empty());
             if lhs.len() + inner.len() + rhs.len() <= shape.width {
-                return Some((lhs, inner, rhs));
+                return Ok((lhs, inner, rhs));
             }
 
             let (lhs, rhs) = delim_token_to_str(context, delim_tok, shape, true, false);
@@ -652,27 +684,27 @@ impl MacroArgKind {
                 .block_indent(context.config.tab_spaces())
                 .with_max_width(context.config);
             let inner = wrap_macro_args(context, args, nested_shape)?;
-            Some((lhs, inner, rhs))
+            Ok((lhs, inner, rhs))
         };
 
         match *self {
-            MacroArgKind::MetaVariable(ty, ref name) => Some(format!("${name}:{ty}")),
+            MacroArgKind::MetaVariable(ty, ref name) => Ok(format!("${name}:{ty}")),
             MacroArgKind::Repeat(delim_tok, ref args, ref another, ref tok) => {
                 let (lhs, inner, rhs) = rewrite_delimited_inner(delim_tok, args)?;
                 let another = another
                     .as_ref()
-                    .and_then(|a| a.rewrite(context, shape, use_multiple_lines))
+                    .and_then(|a| a.rewrite(context, shape, use_multiple_lines).ok())
                     .unwrap_or_else(|| "".to_owned());
                 let repeat_tok = pprust::token_to_string(tok);
 
-                Some(format!("${lhs}{inner}{rhs}{another}{repeat_tok}"))
+                Ok(format!("${lhs}{inner}{rhs}{another}{repeat_tok}"))
             }
             MacroArgKind::Delimited(delim_tok, ref args) => {
                 rewrite_delimited_inner(delim_tok, args)
                     .map(|(lhs, inner, rhs)| format!("{}{}{}", lhs, inner, rhs))
             }
-            MacroArgKind::Separator(ref sep, ref prefix) => Some(format!("{prefix}{sep} ")),
-            MacroArgKind::Other(ref inner, ref prefix) => Some(format!("{prefix}{inner}")),
+            MacroArgKind::Separator(ref sep, ref prefix) => Ok(format!("{prefix}{sep} ")),
+            MacroArgKind::Other(ref inner, ref prefix) => Ok(format!("{prefix}{inner}")),
         }
     }
 }
@@ -688,7 +720,7 @@ impl ParsedMacroArg {
         context: &RewriteContext<'_>,
         shape: Shape,
         use_multiple_lines: bool,
-    ) -> Option<String> {
+    ) -> RewriteResult {
         self.kind.rewrite(context, shape, use_multiple_lines)
     }
 }
@@ -966,9 +998,9 @@ fn wrap_macro_args(
     context: &RewriteContext<'_>,
     args: &[ParsedMacroArg],
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     wrap_macro_args_inner(context, args, shape, false)
-        .or_else(|| wrap_macro_args_inner(context, args, shape, true))
+        .or_else(|_| wrap_macro_args_inner(context, args, shape, true))
 }
 
 fn wrap_macro_args_inner(
@@ -976,7 +1008,7 @@ fn wrap_macro_args_inner(
     args: &[ParsedMacroArg],
     shape: Shape,
     use_multiple_lines: bool,
-) -> Option<String> {
+) -> RewriteResult {
     let mut result = String::with_capacity(128);
     let mut iter = args.iter().peekable();
     let indent_str = shape.indent.to_string_with_newline(context.config);
@@ -1002,9 +1034,9 @@ fn wrap_macro_args_inner(
     }
 
     if !use_multiple_lines && result.len() >= shape.width {
-        None
+        Err(RewriteError::Unknown)
     } else {
-        Some(result)
+        Ok(result)
     }
 }
 
@@ -1012,22 +1044,21 @@ fn wrap_macro_args_inner(
 // for some common cases. I hope the basic logic is sufficient. Note that the
 // meaning of some tokens is a bit different here from usual Rust, e.g., `*`
 // and `(`/`)` have special meaning.
-//
-// We always try and format on one line.
-// FIXME: Use multi-line when every thing does not fit on one line.
 fn format_macro_args(
     context: &RewriteContext<'_>,
     token_stream: TokenStream,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
+    let span = span_for_token_stream(&token_stream);
     if !context.config.format_macro_matchers() {
-        let span = span_for_token_stream(&token_stream);
-        return Some(match span {
+        return Ok(match span {
             Some(span) => context.snippet(span).to_owned(),
             None => String::new(),
         });
     }
-    let parsed_args = MacroArgParser::new().parse(token_stream)?;
+    let parsed_args = MacroArgParser::new()
+        .parse(token_stream)
+        .macro_error(MacroErrorKind::ParseFailure, span.unwrap())?;
     wrap_macro_args(context, &parsed_args, shape)
 }
 
@@ -1132,9 +1163,9 @@ pub(crate) fn convert_try_mac(
 
 pub(crate) fn macro_style(mac: &ast::MacCall, context: &RewriteContext<'_>) -> Delimiter {
     let snippet = context.snippet(mac.span());
-    let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::max_value());
-    let bracket_pos = snippet.find_uncommented("[").unwrap_or(usize::max_value());
-    let brace_pos = snippet.find_uncommented("{").unwrap_or(usize::max_value());
+    let paren_pos = snippet.find_uncommented("(").unwrap_or(usize::MAX);
+    let bracket_pos = snippet.find_uncommented("[").unwrap_or(usize::MAX);
+    let brace_pos = snippet.find_uncommented("{").unwrap_or(usize::MAX);
 
     if paren_pos < bracket_pos && paren_pos < brace_pos {
         Delimiter::Parenthesis
@@ -1242,23 +1273,31 @@ impl MacroBranch {
         context: &RewriteContext<'_>,
         shape: Shape,
         multi_branch_style: bool,
-    ) -> Option<String> {
+    ) -> RewriteResult {
         // Only attempt to format function-like macros.
         if self.args_paren_kind != Delimiter::Parenthesis {
             // FIXME(#1539): implement for non-sugared macros.
-            return None;
+            return Err(RewriteError::MacroFailure {
+                kind: MacroErrorKind::Unknown,
+                span: self.span,
+            });
         }
 
         let old_body = context.snippet(self.body).trim();
         let has_block_body = old_body.starts_with('{');
         let mut prefix_width = 5; // 5 = " => {"
-        if context.config.version() == Version::Two {
+        if context.config.style_edition() >= StyleEdition::Edition2024 {
             if has_block_body {
                 prefix_width = 6; // 6 = " => {{"
             }
         }
-        let mut result =
-            format_macro_args(context, self.args.clone(), shape.sub_width(prefix_width)?)?;
+        let mut result = format_macro_args(
+            context,
+            self.args.clone(),
+            shape
+                .sub_width(prefix_width)
+                .max_width_error(shape.width, self.span)?,
+        )?;
 
         if multi_branch_style {
             result += " =>";
@@ -1267,7 +1306,7 @@ impl MacroBranch {
         if !context.config.format_macro_bodies() {
             result += " ";
             result += context.snippet(self.whole_body);
-            return Some(result);
+            return Ok(result);
         }
 
         // The macro body is the most interesting part. It might end up as various
@@ -1276,7 +1315,8 @@ impl MacroBranch {
         // `$$`). We'll try and format like an AST node, but we'll substitute
         // variables for new names with the same length first.
 
-        let (body_str, substs) = replace_names(old_body)?;
+        let (body_str, substs) =
+            replace_names(old_body).macro_error(MacroErrorKind::ReplaceMacroVariable, self.span)?;
 
         let mut config = context.config.clone();
         config.set().show_parse_errors(false);
@@ -1299,13 +1339,21 @@ impl MacroBranch {
                 config.set().max_width(new_width);
                 match crate::format_code_block(&body_str, &config, true) {
                     Some(new_body) => new_body,
-                    None => return None,
+                    None => {
+                        return Err(RewriteError::MacroFailure {
+                            kind: MacroErrorKind::Unknown,
+                            span: self.span,
+                        });
+                    }
                 }
             }
         };
 
         if !filtered_str_fits(&new_body_snippet.snippet, config.max_width(), shape) {
-            return None;
+            return Err(RewriteError::ExceedsMaxWidth {
+                configured_width: shape.width,
+                span: self.span,
+            });
         }
 
         // Indent the body since it is in a block.
@@ -1331,7 +1379,10 @@ impl MacroBranch {
         for (old, new) in &substs {
             if old_body.contains(new) {
                 debug!("rewrite_macro_def: bailing matching variable: `{}`", new);
-                return None;
+                return Err(RewriteError::MacroFailure {
+                    kind: MacroErrorKind::ReplaceMacroVariable,
+                    span: self.span,
+                });
             }
             new_body = new_body.replace(new, old);
         }
@@ -1346,7 +1397,7 @@ impl MacroBranch {
 
         result += "}";
 
-        Some(result)
+        Ok(result)
     }
 }
 
@@ -1366,7 +1417,8 @@ fn format_lazy_static(
     context: &RewriteContext<'_>,
     shape: Shape,
     ts: TokenStream,
-) -> Option<String> {
+    span: Span,
+) -> RewriteResult {
     let mut result = String::with_capacity(1024);
     let nested_shape = shape
         .block_indent(context.config.tab_spaces())
@@ -1375,7 +1427,8 @@ fn format_lazy_static(
     result.push_str("lazy_static! {");
     result.push_str(&nested_shape.indent.to_string_with_newline(context.config));
 
-    let parsed_elems = parse_lazy_static(context, ts)?;
+    let parsed_elems =
+        parse_lazy_static(context, ts).macro_error(MacroErrorKind::ParseFailure, span)?;
     let last = parsed_elems.len() - 1;
     for (i, (vis, id, ty, expr)) in parsed_elems.iter().enumerate() {
         // Rewrite as a static item.
@@ -1385,14 +1438,16 @@ fn format_lazy_static(
             "{}static ref {}: {} =",
             vis,
             id,
-            ty.rewrite(context, nested_shape)?
+            ty.rewrite_result(context, nested_shape)?
         ));
         result.push_str(&rewrite_assign_rhs(
             context,
             stmt,
             &*expr,
             &RhsAssignKind::Expr(&expr.kind, expr.span),
-            nested_shape.sub_width(1)?,
+            nested_shape
+                .sub_width(1)
+                .max_width_error(nested_shape.width, expr.span)?,
         )?);
         result.push(';');
         if i != last {
@@ -1403,7 +1458,7 @@ fn format_lazy_static(
     result.push_str(&shape.indent.to_string_with_newline(context.config));
     result.push('}');
 
-    Some(result)
+    Ok(result)
 }
 
 fn rewrite_macro_with_items(
@@ -1415,12 +1470,12 @@ fn rewrite_macro_with_items(
     original_style: Delimiter,
     position: MacroPosition,
     span: Span,
-) -> Option<String> {
+) -> RewriteResult {
     let style_to_delims = |style| match style {
-        Delimiter::Parenthesis => Some(("(", ")")),
-        Delimiter::Bracket => Some(("[", "]")),
-        Delimiter::Brace => Some((" {", "}")),
-        _ => None,
+        Delimiter::Parenthesis => Ok(("(", ")")),
+        Delimiter::Bracket => Ok(("[", "]")),
+        Delimiter::Brace => Ok((" {", "}")),
+        _ => Err(RewriteError::Unknown),
     };
 
     let (opener, closer) = style_to_delims(style)?;
@@ -1442,7 +1497,7 @@ fn rewrite_macro_with_items(
     for item in items {
         let item = match item {
             MacroArg::Item(item) => item,
-            _ => return None,
+            _ => return Err(RewriteError::Unknown),
         };
         visitor.visit_item(item);
     }
@@ -1455,5 +1510,5 @@ fn rewrite_macro_with_items(
     result.push_str(&shape.indent.to_string_with_newline(context.config));
     result.push_str(closer);
     result.push_str(trailing_semicolon);
-    Some(result)
+    Ok(result)
 }
diff --git a/src/tools/rustfmt/src/matches.rs b/src/tools/rustfmt/src/matches.rs
index 30bf6271b2e..8f62648e576 100644
--- a/src/tools/rustfmt/src/matches.rs
+++ b/src/tools/rustfmt/src/matches.rs
@@ -2,19 +2,19 @@
 
 use std::iter::repeat;
 
-use rustc_ast::{ast, ptr, MatchKind};
+use rustc_ast::{MatchKind, ast, ptr};
 use rustc_span::{BytePos, Span};
 use tracing::debug;
 
-use crate::comment::{combine_strs_with_missing_comments, rewrite_comment, FindUncommented};
+use crate::comment::{FindUncommented, combine_strs_with_missing_comments, rewrite_comment};
 use crate::config::lists::*;
-use crate::config::{Config, ControlBraceStyle, IndentStyle, MatchArmLeadingPipe, Version};
+use crate::config::{Config, ControlBraceStyle, IndentStyle, MatchArmLeadingPipe, StyleEdition};
 use crate::expr::{
-    format_expr, is_empty_block, is_simple_block, is_unsafe_block, prefer_next_line, rewrite_cond,
-    ExprType, RhsTactics,
+    ExprType, RhsTactics, format_expr, is_empty_block, is_simple_block, is_unsafe_block,
+    prefer_next_line, rewrite_cond,
 };
-use crate::lists::{itemize_list, write_list, ListFormatting};
-use crate::rewrite::{Rewrite, RewriteContext};
+use crate::lists::{ListFormatting, itemize_list, write_list};
+use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult};
 use crate::shape::Shape;
 use crate::source_map::SpanUtils;
 use crate::spanned::Spanned;
@@ -56,6 +56,10 @@ impl<'a> Spanned for ArmWrapper<'a> {
 
 impl<'a> Rewrite for ArmWrapper<'a> {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         rewrite_match_arm(
             context,
             self.arm,
@@ -74,7 +78,7 @@ pub(crate) fn rewrite_match(
     span: Span,
     attrs: &[ast::Attribute],
     match_kind: MatchKind,
-) -> Option<String> {
+) -> RewriteResult {
     // Do not take the rhs overhead from the upper expressions into account
     // when rewriting match condition.
     let cond_shape = Shape {
@@ -83,10 +87,14 @@ pub(crate) fn rewrite_match(
     };
     // 6 = `match `
     let cond_shape = match context.config.indent_style() {
-        IndentStyle::Visual => cond_shape.shrink_left(6)?,
-        IndentStyle::Block => cond_shape.offset_left(6)?,
+        IndentStyle::Visual => cond_shape
+            .shrink_left(6)
+            .max_width_error(shape.width, span)?,
+        IndentStyle::Block => cond_shape
+            .offset_left(6)
+            .max_width_error(shape.width, span)?,
     };
-    let cond_str = cond.rewrite(context, cond_shape)?;
+    let cond_str = cond.rewrite_result(context, cond_shape)?;
     let alt_block_sep = &shape.indent.to_string_with_newline(context.config);
     let block_sep = match context.config.control_brace_style() {
         ControlBraceStyle::AlwaysNextLine => alt_block_sep,
@@ -105,12 +113,13 @@ pub(crate) fn rewrite_match(
     let inner_attrs_str = if inner_attrs.is_empty() {
         String::new()
     } else {
-        let shape = match context.config.version() {
-            Version::One => shape,
-            _ => shape.block_indent(context.config.tab_spaces()),
+        let shape = if context.config.style_edition() <= StyleEdition::Edition2021 {
+            shape
+        } else {
+            shape.block_indent(context.config.tab_spaces())
         };
         inner_attrs
-            .rewrite(context, shape)
+            .rewrite_result(context, shape)
             .map(|s| format!("{}{}\n", nested_indent_str, s))?
     };
 
@@ -130,16 +139,16 @@ pub(crate) fn rewrite_match(
     if arms.is_empty() {
         let snippet = context.snippet(mk_sp(open_brace_pos, span.hi() - BytePos(1)));
         if snippet.trim().is_empty() {
-            Some(format!("match {cond_str} {{}}"))
+            Ok(format!("match {cond_str} {{}}"))
         } else {
             // Empty match with comments or inner attributes? We are not going to bother, sorry ;)
-            Some(context.snippet(span).to_owned())
+            Ok(context.snippet(span).to_owned())
         }
     } else {
         let span_after_cond = mk_sp(cond.span.hi(), span.hi());
 
         match match_kind {
-            MatchKind::Prefix => Some(format!(
+            MatchKind::Prefix => Ok(format!(
                 "match {}{}{{\n{}{}{}\n{}}}",
                 cond_str,
                 block_sep,
@@ -148,7 +157,7 @@ pub(crate) fn rewrite_match(
                 rewrite_match_arms(context, arms, shape, span_after_cond, open_brace_pos)?,
                 shape.indent.to_string(context.config),
             )),
-            MatchKind::Postfix => Some(format!(
+            MatchKind::Postfix => Ok(format!(
                 "{}.match{}{{\n{}{}{}\n{}}}",
                 cond_str,
                 block_sep,
@@ -198,7 +207,7 @@ fn rewrite_match_arms(
     shape: Shape,
     span: Span,
     open_brace_pos: BytePos,
-) -> Option<String> {
+) -> RewriteResult {
     let arm_shape = shape
         .block_indent(context.config.tab_spaces())
         .with_max_width(context.config);
@@ -218,7 +227,7 @@ fn rewrite_match_arms(
         "|",
         |arm| arm.span().lo(),
         |arm| arm.span().hi(),
-        |arm| arm.rewrite(context, arm_shape),
+        |arm| arm.rewrite_result(context, arm_shape),
         open_brace_pos,
         span.hi(),
         false,
@@ -238,19 +247,19 @@ fn rewrite_match_arm(
     shape: Shape,
     is_last: bool,
     has_leading_pipe: bool,
-) -> Option<String> {
+) -> RewriteResult {
     let (missing_span, attrs_str) = if !arm.attrs.is_empty() {
         if contains_skip(&arm.attrs) {
-            let (_, body) = flatten_arm_body(context, arm.body.as_deref()?, None);
+            let (_, body) = flatten_arm_body(context, arm.body.as_deref().unknown_error()?, None);
             // `arm.span()` does not include trailing comma, add it manually.
-            return Some(format!(
+            return Ok(format!(
                 "{}{}",
                 context.snippet(arm.span()),
                 arm_comma(context.config, body, is_last),
             ));
         }
         let missing_span = mk_sp(arm.attrs[arm.attrs.len() - 1].span.hi(), arm.pat.span.lo());
-        (missing_span, arm.attrs.rewrite(context, shape)?)
+        (missing_span, arm.attrs.rewrite_result(context, shape)?)
     } else {
         (mk_sp(arm.span().lo(), arm.span().lo()), String::new())
     };
@@ -264,19 +273,25 @@ fn rewrite_match_arm(
     };
 
     // Patterns
-    let pat_shape = match &arm.body.as_ref()?.kind {
+    let pat_shape = match &arm.body.as_ref().unknown_error()?.kind {
         ast::ExprKind::Block(_, Some(label)) => {
             // Some block with a label ` => 'label: {`
             // 7 = ` => : {`
             let label_len = label.ident.as_str().len();
-            shape.sub_width(7 + label_len)?.offset_left(pipe_offset)?
+            shape
+                .sub_width(7 + label_len)
+                .and_then(|s| s.offset_left(pipe_offset))
+                .max_width_error(shape.width, arm.span)?
         }
         _ => {
             // 5 = ` => {`
-            shape.sub_width(5)?.offset_left(pipe_offset)?
+            shape
+                .sub_width(5)
+                .and_then(|s| s.offset_left(pipe_offset))
+                .max_width_error(shape.width, arm.span)?
         }
     };
-    let pats_str = arm.pat.rewrite(context, pat_shape)?;
+    let pats_str = arm.pat.rewrite_result(context, pat_shape)?;
 
     // Guard
     let block_like_pat = trimmed_last_line_width(&pats_str) <= context.config.tab_spaces();
@@ -298,10 +313,13 @@ fn rewrite_match_arm(
         false,
     )?;
 
-    let arrow_span = mk_sp(arm.pat.span.hi(), arm.body.as_ref()?.span().lo());
+    let arrow_span = mk_sp(
+        arm.pat.span.hi(),
+        arm.body.as_ref().unknown_error()?.span().lo(),
+    );
     rewrite_match_body(
         context,
-        arm.body.as_ref()?,
+        arm.body.as_ref().unknown_error()?,
         &lhs_str,
         shape,
         guard_str.contains('\n'),
@@ -382,7 +400,7 @@ fn rewrite_match_body(
     has_guard: bool,
     arrow_span: Span,
     is_last: bool,
-) -> Option<String> {
+) -> RewriteResult {
     let (extend, body) = flatten_arm_body(
         context,
         body,
@@ -403,7 +421,7 @@ fn rewrite_match_body(
             _ => " ",
         };
 
-        Some(format!("{} =>{}{}{}", pats_str, block_sep, body_str, comma))
+        Ok(format!("{} =>{}{}{}", pats_str, block_sep, body_str, comma))
     };
 
     let next_line_indent = if !is_block || is_empty_block {
@@ -420,7 +438,7 @@ fn rewrite_match_body(
         let arrow_snippet = context.snippet(arrow_span).trim();
         // search for the arrow starting from the end of the snippet since there may be a match
         // expression within the guard
-        let arrow_index = if context.config.version() == Version::One {
+        let arrow_index = if context.config.style_edition() <= StyleEdition::Edition2021 {
             arrow_snippet.rfind("=>").unwrap()
         } else {
             arrow_snippet.find_last_uncommented("=>").unwrap()
@@ -447,7 +465,7 @@ fn rewrite_match_body(
             result.push_str(&nested_indent_str);
             result.push_str(body_str);
             result.push_str(comma);
-            return Some(result);
+            return Ok(result);
         }
 
         let indent_str = shape.indent.to_string_with_newline(context.config);
@@ -458,7 +476,7 @@ fn rewrite_match_body(
                 } else {
                     ""
                 };
-                let semicolon = if context.config.version() == Version::One {
+                let semicolon = if context.config.style_edition() <= StyleEdition::Edition2021 {
                     ""
                 } else {
                     if semicolon_for_expr(context, body) {
@@ -490,7 +508,7 @@ fn rewrite_match_body(
         result.push_str(&block_sep);
         result.push_str(body_str);
         result.push_str(&body_suffix);
-        Some(result)
+        Ok(result)
     };
 
     // Let's try and get the arm body on the same line as the condition.
@@ -499,7 +517,7 @@ fn rewrite_match_body(
         .offset_left(extra_offset(pats_str, shape) + 4)
         .and_then(|shape| shape.sub_width(comma.len()));
     let orig_body = if forbid_same_line || !arrow_comment.is_empty() {
-        None
+        Err(RewriteError::Unknown)
     } else if let Some(body_shape) = orig_body_shape {
         let rewrite = nop_block_collapse(
             format_expr(body, ExprType::Statement, context, body_shape),
@@ -507,7 +525,7 @@ fn rewrite_match_body(
         );
 
         match rewrite {
-            Some(ref body_str)
+            Ok(ref body_str)
                 if is_block
                     || (!body_str.contains('\n')
                         && unicode_str_width(body_str) <= body_shape.width) =>
@@ -517,7 +535,7 @@ fn rewrite_match_body(
             _ => rewrite,
         }
     } else {
-        None
+        Err(RewriteError::Unknown)
     };
     let orig_budget = orig_body_shape.map_or(0, |shape| shape.width);
 
@@ -528,20 +546,23 @@ fn rewrite_match_body(
         next_line_body_shape.width,
     );
     match (orig_body, next_line_body) {
-        (Some(ref orig_str), Some(ref next_line_str))
+        (Ok(ref orig_str), Ok(ref next_line_str))
             if prefer_next_line(orig_str, next_line_str, RhsTactics::Default) =>
         {
             combine_next_line_body(next_line_str)
         }
-        (Some(ref orig_str), _) if extend && first_line_width(orig_str) <= orig_budget => {
+        (Ok(ref orig_str), _) if extend && first_line_width(orig_str) <= orig_budget => {
             combine_orig_body(orig_str)
         }
-        (Some(ref orig_str), Some(ref next_line_str)) if orig_str.contains('\n') => {
+        (Ok(ref orig_str), Ok(ref next_line_str)) if orig_str.contains('\n') => {
             combine_next_line_body(next_line_str)
         }
-        (None, Some(ref next_line_str)) => combine_next_line_body(next_line_str),
-        (None, None) => None,
-        (Some(ref orig_str), _) => combine_orig_body(orig_str),
+        (Err(_), Ok(ref next_line_str)) => combine_next_line_body(next_line_str),
+        // When both orig_body and next_line_body result in errors, we currently propagate the
+        // error from the second attempt since it is more generous with width constraints.
+        // This decision is somewhat arbitrary and is open to change.
+        (Err(_), Err(next_line_err)) => Err(next_line_err),
+        (Ok(ref orig_str), _) => combine_orig_body(orig_str),
     }
 }
 
@@ -554,7 +575,7 @@ fn rewrite_guard(
     // the arm (excludes offset).
     pattern_width: usize,
     multiline_pattern: bool,
-) -> Option<String> {
+) -> RewriteResult {
     if let Some(ref guard) = *guard {
         // First try to fit the guard string on the same line as the pattern.
         // 4 = ` if `, 5 = ` => {`
@@ -563,9 +584,9 @@ fn rewrite_guard(
             .and_then(|s| s.sub_width(5));
         if !multiline_pattern {
             if let Some(cond_shape) = cond_shape {
-                if let Some(cond_str) = guard.rewrite(context, cond_shape) {
+                if let Ok(cond_str) = guard.rewrite_result(context, cond_shape) {
                     if !cond_str.contains('\n') || pattern_width <= context.config.tab_spaces() {
-                        return Some(format!(" if {cond_str}"));
+                        return Ok(format!(" if {cond_str}"));
                     }
                 }
             }
@@ -575,24 +596,20 @@ fn rewrite_guard(
         // 3 = `if `, 5 = ` => {`
         let cond_shape = Shape::indented(shape.indent.block_indent(context.config), context.config)
             .offset_left(3)
-            .and_then(|s| s.sub_width(5));
-        if let Some(cond_shape) = cond_shape {
-            if let Some(cond_str) = guard.rewrite(context, cond_shape) {
-                return Some(format!(
-                    "{}if {}",
-                    cond_shape.indent.to_string_with_newline(context.config),
-                    cond_str
-                ));
-            }
-        }
-
-        None
+            .and_then(|s| s.sub_width(5))
+            .max_width_error(shape.width, guard.span)?;
+        let cond_str = guard.rewrite_result(context, cond_shape)?;
+        Ok(format!(
+            "{}if {}",
+            cond_shape.indent.to_string_with_newline(context.config),
+            cond_str
+        ))
     } else {
-        Some(String::new())
+        Ok(String::new())
     }
 }
 
-fn nop_block_collapse(block_str: Option<String>, budget: usize) -> Option<String> {
+fn nop_block_collapse(block_str: RewriteResult, budget: usize) -> RewriteResult {
     debug!("nop_block_collapse {:?} {}", block_str, budget);
     block_str.map(|block_str| {
         if block_str.starts_with('{')
diff --git a/src/tools/rustfmt/src/missed_spans.rs b/src/tools/rustfmt/src/missed_spans.rs
index 56adb2e5e69..384de1ce9ae 100644
--- a/src/tools/rustfmt/src/missed_spans.rs
+++ b/src/tools/rustfmt/src/missed_spans.rs
@@ -1,10 +1,10 @@
 use rustc_span::{BytePos, Pos, Span};
 use tracing::debug;
 
-use crate::comment::{is_last_comment_block, rewrite_comment, CodeCharKind, CommentCodeSlices};
-use crate::config::file_lines::FileLines;
+use crate::comment::{CodeCharKind, CommentCodeSlices, is_last_comment_block, rewrite_comment};
 use crate::config::FileName;
-use crate::config::Version;
+use crate::config::StyleEdition;
+use crate::config::file_lines::FileLines;
 use crate::coverage::transform_missing_snippet;
 use crate::shape::{Indent, Shape};
 use crate::source_map::LineRangeUtils;
@@ -247,7 +247,9 @@ impl<'a> FmtVisitor<'a> {
             let indent_str = self.block_indent.to_string(self.config);
             self.push_str(&indent_str);
             self.block_indent
-        } else if self.config.version() == Version::Two && !snippet.starts_with('\n') {
+        } else if self.config.style_edition() >= StyleEdition::Edition2024
+            && !snippet.starts_with('\n')
+        {
             // The comment appears on the same line as the previous formatted code.
             // Assuming that comment is logically associated with that code, we want to keep it on
             // the same level and avoid mixing it with possible other comment.
@@ -283,13 +285,13 @@ impl<'a> FmtVisitor<'a> {
                     let other_lines = &subslice[offset + 1..];
                     let comment_str =
                         rewrite_comment(other_lines, false, comment_shape, self.config)
-                            .unwrap_or_else(|| String::from(other_lines));
+                            .unwrap_or_else(|_| String::from(other_lines));
                     self.push_str(&comment_str);
                 }
             }
         } else {
             let comment_str = rewrite_comment(subslice, false, comment_shape, self.config)
-                .unwrap_or_else(|| String::from(subslice));
+                .unwrap_or_else(|_| String::from(subslice));
             self.push_str(&comment_str);
         }
 
diff --git a/src/tools/rustfmt/src/modules.rs b/src/tools/rustfmt/src/modules.rs
index 0590f28ee05..493b04f16c6 100644
--- a/src/tools/rustfmt/src/modules.rs
+++ b/src/tools/rustfmt/src/modules.rs
@@ -4,8 +4,8 @@ use std::path::{Path, PathBuf};
 
 use rustc_ast::ast;
 use rustc_ast::visit::Visitor;
-use rustc_span::symbol::{self, sym, Symbol};
 use rustc_span::Span;
+use rustc_span::symbol::{self, Symbol, sym};
 use thin_vec::ThinVec;
 use thiserror::Error;
 
diff --git a/src/tools/rustfmt/src/overflow.rs b/src/tools/rustfmt/src/overflow.rs
index cdb735be8a4..fdc8e23e72b 100644
--- a/src/tools/rustfmt/src/overflow.rs
+++ b/src/tools/rustfmt/src/overflow.rs
@@ -9,22 +9,22 @@ use rustc_span::Span;
 use tracing::debug;
 
 use crate::closures;
-use crate::config::Version;
-use crate::config::{lists::*, Config};
+use crate::config::StyleEdition;
+use crate::config::{Config, lists::*};
 use crate::expr::{
     can_be_overflowed_expr, is_every_expr_simple, is_method_call, is_nested_call, is_simple_expr,
     rewrite_cond,
 };
 use crate::lists::{
-    definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator,
+    ListFormatting, ListItem, Separator, definitive_tactic, itemize_list, write_list,
 };
 use crate::macros::MacroArg;
-use crate::patterns::{can_be_overflowed_pat, TuplePatField};
-use crate::rewrite::{Rewrite, RewriteContext};
+use crate::patterns::{TuplePatField, can_be_overflowed_pat};
+use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult};
 use crate::shape::Shape;
 use crate::source_map::SpanUtils;
 use crate::spanned::Spanned;
-use crate::types::{can_be_overflowed_type, SegmentParam};
+use crate::types::{SegmentParam, can_be_overflowed_type};
 use crate::utils::{count_newlines, extra_offset, first_line_width, last_line_width, mk_sp};
 
 /// A list of `format!`-like macros, that take a long format string and a list of arguments to
@@ -91,6 +91,10 @@ impl<'a> Rewrite for OverflowableItem<'a> {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
         self.map(|item| item.rewrite(context, shape))
     }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
+        self.map(|item| item.rewrite_result(context, shape))
+    }
 }
 
 impl<'a> Spanned for OverflowableItem<'a> {
@@ -201,8 +205,12 @@ impl<'a> OverflowableItem<'a> {
             OverflowableItem::NestedMetaItem(..) => SPECIAL_CASE_ATTR,
             _ => &[],
         };
-        let additional_cases = match (self, config.version()) {
-            (OverflowableItem::MacroArg(..), Version::Two) => SPECIAL_CASE_MACROS_V2,
+        let additional_cases = match self {
+            OverflowableItem::MacroArg(..)
+                if config.style_edition() >= StyleEdition::Edition2024 =>
+            {
+                SPECIAL_CASE_MACROS_V2
+            }
             _ => &[],
         };
         base_cases.iter().chain(additional_cases)
@@ -278,7 +286,7 @@ pub(crate) fn rewrite_with_parens<'a, T: 'a + IntoOverflowableItem<'a>>(
     span: Span,
     item_max_width: usize,
     force_separator_tactic: Option<SeparatorTactic>,
-) -> Option<String> {
+) -> RewriteResult {
     Context::new(
         context,
         items,
@@ -300,7 +308,7 @@ pub(crate) fn rewrite_with_angle_brackets<'a, T: 'a + IntoOverflowableItem<'a>>(
     items: impl Iterator<Item = &'a T>,
     shape: Shape,
     span: Span,
-) -> Option<String> {
+) -> RewriteResult {
     Context::new(
         context,
         items,
@@ -324,7 +332,7 @@ pub(crate) fn rewrite_with_square_brackets<'a, T: 'a + IntoOverflowableItem<'a>>
     span: Span,
     force_separator_tactic: Option<SeparatorTactic>,
     delim_token: Option<Delimiter>,
-) -> Option<String> {
+) -> RewriteResult {
     let (lhs, rhs) = match delim_token {
         Some(Delimiter::Parenthesis) => ("(", ")"),
         Some(Delimiter::Brace) => ("{", "}"),
@@ -428,7 +436,7 @@ impl<'a> Context<'a> {
                         if closures::args_have_many_closure(&self.items) {
                             None
                         } else {
-                            closures::rewrite_last_closure(self.context, expr, shape)
+                            closures::rewrite_last_closure(self.context, expr, shape).ok()
                         }
                     }
 
@@ -457,7 +465,7 @@ impl<'a> Context<'a> {
 
         if let Some(rewrite) = rewrite {
             // splitn(2, *).next().unwrap() is always safe.
-            let rewrite_first_line = Some(rewrite.splitn(2, '\n').next().unwrap().to_owned());
+            let rewrite_first_line = Ok(rewrite.splitn(2, '\n').next().unwrap().to_owned());
             last_list_item.item = rewrite_first_line;
             Some(rewrite)
         } else {
@@ -495,7 +503,7 @@ impl<'a> Context<'a> {
                 Some(OverflowableItem::MacroArg(MacroArg::Expr(expr)))
                     if !combine_arg_with_callee
                         && is_method_call(expr)
-                        && self.context.config.version() == Version::Two =>
+                        && self.context.config.style_edition() >= StyleEdition::Edition2024 =>
                 {
                     self.context.force_one_line_chain.replace(true);
                 }
@@ -545,22 +553,23 @@ impl<'a> Context<'a> {
                         .and_then(|last_item| last_item.rewrite(self.context, self.nested_shape));
                     let no_newline = rw.as_ref().map_or(false, |s| !s.contains('\n'));
                     if no_newline {
-                        list_items[self.items.len() - 1].item = rw;
+                        list_items[self.items.len() - 1].item = rw.unknown_error();
                     } else {
-                        list_items[self.items.len() - 1].item = Some(overflowed.to_owned());
+                        list_items[self.items.len() - 1].item = Ok(overflowed.to_owned());
                     }
                 } else {
-                    list_items[self.items.len() - 1].item = Some(overflowed.to_owned());
+                    list_items[self.items.len() - 1].item = Ok(overflowed.to_owned());
                 }
             }
             (true, DefinitiveListTactic::Horizontal, placeholder @ Some(..)) => {
-                list_items[self.items.len() - 1].item = placeholder;
+                list_items[self.items.len() - 1].item = placeholder.unknown_error();
             }
             _ if !self.items.is_empty() => {
                 list_items[self.items.len() - 1].item = self
                     .items
                     .last()
-                    .and_then(|last_item| last_item.rewrite(self.context, self.nested_shape));
+                    .and_then(|last_item| last_item.rewrite(self.context, self.nested_shape))
+                    .unknown_error();
 
                 // Use horizontal layout for a function with a single argument as long as
                 // everything fits in a single line.
@@ -613,7 +622,7 @@ impl<'a> Context<'a> {
         tactic
     }
 
-    fn rewrite_items(&self) -> Option<(bool, String)> {
+    fn rewrite_items(&self) -> Result<(bool, String), RewriteError> {
         let span = self.items_span();
         debug!("items: {:?}", self.items);
 
@@ -624,7 +633,7 @@ impl<'a> Context<'a> {
             ",",
             |item| item.span().lo(),
             |item| item.span().hi(),
-            |item| item.rewrite(self.context, self.nested_shape),
+            |item| item.rewrite_result(self.context, self.nested_shape),
             span.lo(),
             span.hi(),
             true,
@@ -689,7 +698,8 @@ impl<'a> Context<'a> {
         );
         result.push_str(self.ident);
         result.push_str(prefix);
-        let force_single_line = if self.context.config.version() == Version::Two {
+        let force_single_line = if self.context.config.style_edition() >= StyleEdition::Edition2024
+        {
             !self.context.use_block_indent() || (is_extendable && extend_width <= shape.width)
         } else {
             // 2 = `()`
@@ -711,7 +721,7 @@ impl<'a> Context<'a> {
         result
     }
 
-    fn rewrite(&self, shape: Shape) -> Option<String> {
+    fn rewrite(&self, shape: Shape) -> RewriteResult {
         let (extendable, items_str) = self.rewrite_items()?;
 
         // If we are using visual indent style and failed to format, retry with block indent.
@@ -725,7 +735,7 @@ impl<'a> Context<'a> {
             return result;
         }
 
-        Some(self.wrap_items(&items_str, shape, extendable))
+        Ok(self.wrap_items(&items_str, shape, extendable))
     }
 }
 
diff --git a/src/tools/rustfmt/src/pairs.rs b/src/tools/rustfmt/src/pairs.rs
index bfc2ffed383..9c51298416b 100644
--- a/src/tools/rustfmt/src/pairs.rs
+++ b/src/tools/rustfmt/src/pairs.rs
@@ -1,9 +1,11 @@
 use rustc_ast::ast;
+use rustc_span::Span;
 
-use crate::config::lists::*;
 use crate::config::IndentStyle;
-use crate::rewrite::{Rewrite, RewriteContext};
+use crate::config::lists::*;
+use crate::rewrite::{Rewrite, RewriteContext, RewriteErrorExt, RewriteResult};
 use crate::shape::Shape;
+use crate::spanned::Spanned;
 use crate::utils::{
     first_line_width, is_single_line, last_line_width, trimmed_last_line_width, wrap_str,
 };
@@ -40,16 +42,19 @@ pub(crate) fn rewrite_all_pairs(
     expr: &ast::Expr,
     shape: Shape,
     context: &RewriteContext<'_>,
-) -> Option<String> {
-    expr.flatten(context, shape).and_then(|list| {
-        if list.let_chain_count() > 0 && !list.can_rewrite_let_chain_single_line() {
-            rewrite_pairs_multiline(&list, shape, context)
-        } else {
-            // First we try formatting on one line.
-            rewrite_pairs_one_line(&list, shape, context)
-                .or_else(|| rewrite_pairs_multiline(&list, shape, context))
-        }
-    })
+) -> RewriteResult {
+    expr.flatten(context, shape)
+        .unknown_error()
+        .and_then(|list| {
+            if list.let_chain_count() > 0 && !list.can_rewrite_let_chain_single_line() {
+                rewrite_pairs_multiline(&list, shape, context)
+            } else {
+                // First we try formatting on one line.
+                rewrite_pairs_one_line(&list, shape, context)
+                    .unknown_error()
+                    .or_else(|_| rewrite_pairs_multiline(&list, shape, context))
+            }
+        })
 }
 
 // This may return a multi-line result since we allow the last expression to go
@@ -65,7 +70,7 @@ fn rewrite_pairs_one_line<T: Rewrite>(
     let base_shape = shape.block();
 
     for ((_, rewrite), s) in list.list.iter().zip(list.separators.iter()) {
-        if let Some(rewrite) = rewrite {
+        if let Ok(rewrite) = rewrite {
             if !is_single_line(rewrite) || result.len() > shape.width {
                 return None;
             }
@@ -104,19 +109,20 @@ fn rewrite_pairs_multiline<T: Rewrite>(
     list: &PairList<'_, '_, T>,
     shape: Shape,
     context: &RewriteContext<'_>,
-) -> Option<String> {
+) -> RewriteResult {
     let rhs_offset = shape.rhs_overhead(context.config);
     let nested_shape = (match context.config.indent_style() {
         IndentStyle::Visual => shape.visual_indent(0),
         IndentStyle::Block => shape.block_indent(context.config.tab_spaces()),
     })
     .with_max_width(context.config)
-    .sub_width(rhs_offset)?;
+    .sub_width(rhs_offset)
+    .max_width_error(shape.width, list.span)?;
 
     let indent_str = nested_shape.indent.to_string_with_newline(context.config);
     let mut result = String::new();
 
-    result.push_str(list.list[0].1.as_ref()?);
+    result.push_str(list.list[0].1.as_ref().map_err(|err| err.clone())?);
 
     for ((e, default_rw), s) in list.list[1..].iter().zip(list.separators.iter()) {
         // The following test checks if we should keep two subexprs on the same
@@ -132,7 +138,7 @@ fn rewrite_pairs_multiline<T: Rewrite>(
             if let Some(line_shape) =
                 shape.offset_left(s.len() + 2 + trimmed_last_line_width(&result))
             {
-                if let Some(rewrite) = e.rewrite(context, line_shape) {
+                if let Ok(rewrite) = e.rewrite_result(context, line_shape) {
                     result.push(' ');
                     result.push_str(s);
                     result.push(' ');
@@ -155,9 +161,9 @@ fn rewrite_pairs_multiline<T: Rewrite>(
             }
         }
 
-        result.push_str(default_rw.as_ref()?);
+        result.push_str(default_rw.as_ref().map_err(|err| err.clone())?);
     }
-    Some(result)
+    Ok(result)
 }
 
 // Rewrites a single pair.
@@ -168,10 +174,10 @@ pub(crate) fn rewrite_pair<LHS, RHS>(
     context: &RewriteContext<'_>,
     shape: Shape,
     separator_place: SeparatorPlace,
-) -> Option<String>
+) -> RewriteResult
 where
-    LHS: Rewrite,
-    RHS: Rewrite,
+    LHS: Rewrite + Spanned,
+    RHS: Rewrite + Spanned,
 {
     let tab_spaces = context.config.tab_spaces();
     let lhs_overhead = match separator_place {
@@ -183,15 +189,17 @@ where
         ..shape
     };
     let lhs_result = lhs
-        .rewrite(context, lhs_shape)
+        .rewrite_result(context, lhs_shape)
         .map(|lhs_str| format!("{}{}", pp.prefix, lhs_str))?;
 
     // Try to put both lhs and rhs on the same line.
     let rhs_orig_result = shape
         .offset_left(last_line_width(&lhs_result) + pp.infix.len())
         .and_then(|s| s.sub_width(pp.suffix.len()))
-        .and_then(|rhs_shape| rhs.rewrite(context, rhs_shape));
-    if let Some(ref rhs_result) = rhs_orig_result {
+        .max_width_error(shape.width, rhs.span())
+        .and_then(|rhs_shape| rhs.rewrite_result(context, rhs_shape));
+
+    if let Ok(ref rhs_result) = rhs_orig_result {
         // If the length of the lhs is equal to or shorter than the tab width or
         // the rhs looks like block expression, we put the rhs on the same
         // line with the lhs even if the rhs is multi-lined.
@@ -207,7 +215,7 @@ where
                 + first_line_width(rhs_result)
                 + pp.suffix.len();
             if one_line_width <= shape.width {
-                return Some(format!(
+                return Ok(format!(
                     "{}{}{}{}",
                     lhs_result, pp.infix, rhs_result, pp.suffix
                 ));
@@ -219,13 +227,15 @@ where
     // Re-evaluate the rhs because we have more space now:
     let mut rhs_shape = match context.config.indent_style() {
         IndentStyle::Visual => shape
-            .sub_width(pp.suffix.len() + pp.prefix.len())?
+            .sub_width(pp.suffix.len() + pp.prefix.len())
+            .max_width_error(shape.width, rhs.span())?
             .visual_indent(pp.prefix.len()),
         IndentStyle::Block => {
             // Try to calculate the initial constraint on the right hand side.
             let rhs_overhead = shape.rhs_overhead(context.config);
             Shape::indented(shape.indent.block_indent(context.config), context.config)
-                .sub_width(rhs_overhead)?
+                .sub_width(rhs_overhead)
+                .max_width_error(shape.width, rhs.span())?
         }
     };
     let infix = match separator_place {
@@ -233,15 +243,17 @@ where
         SeparatorPlace::Front => pp.infix.trim_start(),
     };
     if separator_place == SeparatorPlace::Front {
-        rhs_shape = rhs_shape.offset_left(infix.len())?;
+        rhs_shape = rhs_shape
+            .offset_left(infix.len())
+            .max_width_error(rhs_shape.width, rhs.span())?;
     }
-    let rhs_result = rhs.rewrite(context, rhs_shape)?;
+    let rhs_result = rhs.rewrite_result(context, rhs_shape)?;
     let indent_str = rhs_shape.indent.to_string_with_newline(context.config);
     let infix_with_sep = match separator_place {
         SeparatorPlace::Back => format!("{infix}{indent_str}"),
         SeparatorPlace::Front => format!("{indent_str}{infix}"),
     };
-    Some(format!(
+    Ok(format!(
         "{}{}{}{}",
         lhs_result, infix_with_sep, rhs_result, pp.suffix
     ))
@@ -255,8 +267,9 @@ trait FlattenPair: Rewrite + Sized {
 }
 
 struct PairList<'a, 'b, T: Rewrite> {
-    list: Vec<(&'b T, Option<String>)>,
+    list: Vec<(&'b T, RewriteResult)>,
     separators: Vec<&'a str>,
+    span: Span,
 }
 
 fn is_ident(expr: &ast::Expr) -> bool {
@@ -303,7 +316,7 @@ impl FlattenPair for ast::Expr {
 
         let default_rewrite = |node: &ast::Expr, sep: usize, is_first: bool| {
             if is_first {
-                return node.rewrite(context, shape);
+                return node.rewrite_result(context, shape);
             }
             let nested_overhead = sep + 1;
             let rhs_offset = shape.rhs_overhead(context.config);
@@ -312,12 +325,17 @@ impl FlattenPair for ast::Expr {
                 IndentStyle::Block => shape.block_indent(context.config.tab_spaces()),
             })
             .with_max_width(context.config)
-            .sub_width(rhs_offset)?;
+            .sub_width(rhs_offset)
+            .max_width_error(shape.width, node.span)?;
             let default_shape = match context.config.binop_separator() {
-                SeparatorPlace::Back => nested_shape.sub_width(nested_overhead)?,
-                SeparatorPlace::Front => nested_shape.offset_left(nested_overhead)?,
+                SeparatorPlace::Back => nested_shape
+                    .sub_width(nested_overhead)
+                    .max_width_error(nested_shape.width, node.span)?,
+                SeparatorPlace::Front => nested_shape
+                    .offset_left(nested_overhead)
+                    .max_width_error(nested_shape.width, node.span)?,
             };
-            node.rewrite(context, default_shape)
+            node.rewrite_result(context, default_shape)
         };
 
         // Turn a tree of binop expressions into a list using a depth-first,
@@ -326,6 +344,7 @@ impl FlattenPair for ast::Expr {
         let mut list = vec![];
         let mut separators = vec![];
         let mut node = self;
+        let span = self.span();
         loop {
             match node.kind {
                 ast::ExprKind::Binary(op, ref lhs, _) if op.node == top_op => {
@@ -352,7 +371,11 @@ impl FlattenPair for ast::Expr {
         }
 
         assert_eq!(list.len() - 1, separators.len());
-        Some(PairList { list, separators })
+        Some(PairList {
+            list,
+            separators,
+            span,
+        })
     }
 }
 
diff --git a/src/tools/rustfmt/src/parse/macros/asm.rs b/src/tools/rustfmt/src/parse/macros/asm.rs
index 6373d0251f8..5ee083da539 100644
--- a/src/tools/rustfmt/src/parse/macros/asm.rs
+++ b/src/tools/rustfmt/src/parse/macros/asm.rs
@@ -1,5 +1,5 @@
 use rustc_ast::ast;
-use rustc_builtin_macros::asm::{parse_asm_args, AsmArgs};
+use rustc_builtin_macros::asm::{AsmArgs, parse_asm_args};
 
 use crate::rewrite::RewriteContext;
 
diff --git a/src/tools/rustfmt/src/parse/macros/cfg_if.rs b/src/tools/rustfmt/src/parse/macros/cfg_if.rs
index b91d203d531..ec771f96a3f 100644
--- a/src/tools/rustfmt/src/parse/macros/cfg_if.rs
+++ b/src/tools/rustfmt/src/parse/macros/cfg_if.rs
@@ -1,4 +1,4 @@
-use std::panic::{catch_unwind, AssertUnwindSafe};
+use std::panic::{AssertUnwindSafe, catch_unwind};
 
 use rustc_ast::ast;
 use rustc_ast::token::{Delimiter, TokenKind};
diff --git a/src/tools/rustfmt/src/parse/macros/mod.rs b/src/tools/rustfmt/src/parse/macros/mod.rs
index 8d5f7f90958..7271e73db8d 100644
--- a/src/tools/rustfmt/src/parse/macros/mod.rs
+++ b/src/tools/rustfmt/src/parse/macros/mod.rs
@@ -1,11 +1,11 @@
 use rustc_ast::token::{Delimiter, NonterminalKind, NtExprKind::*, NtPatKind::*, TokenKind};
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::{ast, ptr};
-use rustc_parse::parser::{ForceCollect, Parser, Recovery};
 use rustc_parse::MACRO_ARGUMENTS;
+use rustc_parse::parser::{ForceCollect, Parser, Recovery};
 use rustc_session::parse::ParseSess;
-use rustc_span::symbol::{self, kw};
 use rustc_span::Symbol;
+use rustc_span::symbol::{self, kw};
 
 use crate::macros::MacroArg;
 use crate::rewrite::RewriteContext;
diff --git a/src/tools/rustfmt/src/parse/parser.rs b/src/tools/rustfmt/src/parse/parser.rs
index 6051241309d..28b4c2b612f 100644
--- a/src/tools/rustfmt/src/parse/parser.rs
+++ b/src/tools/rustfmt/src/parse/parser.rs
@@ -1,4 +1,4 @@
-use std::panic::{catch_unwind, AssertUnwindSafe};
+use std::panic::{AssertUnwindSafe, catch_unwind};
 use std::path::{Path, PathBuf};
 
 use rustc_ast::token::TokenKind;
@@ -6,11 +6,11 @@ use rustc_ast::{ast, attr, ptr};
 use rustc_errors::Diag;
 use rustc_parse::parser::Parser as RawParser;
 use rustc_parse::{new_parser_from_file, new_parser_from_source_str, unwrap_or_emit_fatal};
-use rustc_span::{sym, Span};
+use rustc_span::{Span, sym};
 use thin_vec::ThinVec;
 
-use crate::parse::session::ParseSess;
 use crate::Input;
+use crate::parse::session::ParseSess;
 
 pub(crate) type DirectoryOwnership = rustc_expand::module::DirOwnership;
 pub(crate) type ModulePathSuccess = rustc_expand::module::ModulePathSuccess;
diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs
index 05cf467167c..9f27a05939e 100644
--- a/src/tools/rustfmt/src/parse/session.rs
+++ b/src/tools/rustfmt/src/parse/session.rs
@@ -2,13 +2,14 @@ use std::path::Path;
 use std::sync::atomic::{AtomicBool, Ordering};
 
 use rustc_data_structures::sync::{IntoDynSyncSend, Lrc};
-use rustc_errors::emitter::{stderr_destination, DynEmitter, Emitter, HumanEmitter, SilentEmitter};
+use rustc_errors::emitter::{DynEmitter, Emitter, HumanEmitter, SilentEmitter, stderr_destination};
 use rustc_errors::translation::Translate;
 use rustc_errors::{ColorConfig, Diag, DiagCtxt, DiagInner, Level as DiagnosticLevel};
 use rustc_session::parse::ParseSess as RawParseSess;
 use rustc_span::{
+    BytePos, Span,
     source_map::{FilePathMapping, SourceMap},
-    symbol, BytePos, Span,
+    symbol,
 };
 
 use crate::config::file_lines::LineRange;
@@ -394,7 +395,9 @@ mod tests {
         }
 
         fn get_ignore_list(config: &str) -> IgnoreList {
-            Config::from_toml(config, Path::new("")).unwrap().ignore()
+            Config::from_toml(config, Path::new("./rustfmt.toml"))
+                .unwrap()
+                .ignore()
         }
 
         #[test]
diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs
index d8cb26a20f1..6fe2d4a8520 100644
--- a/src/tools/rustfmt/src/patterns.rs
+++ b/src/tools/rustfmt/src/patterns.rs
@@ -2,22 +2,22 @@ use rustc_ast::ast::{self, BindingMode, ByRef, Pat, PatField, PatKind, RangeEnd,
 use rustc_ast::ptr;
 use rustc_span::{BytePos, Span};
 
-use crate::comment::{combine_strs_with_missing_comments, FindUncommented};
+use crate::comment::{FindUncommented, combine_strs_with_missing_comments};
+use crate::config::StyleEdition;
 use crate::config::lists::*;
-use crate::config::Version;
 use crate::expr::{can_be_overflowed_expr, rewrite_unary_prefix, wrap_struct_field};
 use crate::lists::{
-    definitive_tactic, itemize_list, shape_for_tactic, struct_lit_formatting, struct_lit_shape,
-    struct_lit_tactic, write_list, ListFormatting, ListItem, Separator,
+    ListFormatting, ListItem, Separator, definitive_tactic, itemize_list, shape_for_tactic,
+    struct_lit_formatting, struct_lit_shape, struct_lit_tactic, write_list,
 };
-use crate::macros::{rewrite_macro, MacroPosition};
+use crate::macros::{MacroPosition, rewrite_macro};
 use crate::overflow;
-use crate::pairs::{rewrite_pair, PairParts};
-use crate::rewrite::{Rewrite, RewriteContext};
+use crate::pairs::{PairParts, rewrite_pair};
+use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult};
 use crate::shape::Shape;
 use crate::source_map::SpanUtils;
 use crate::spanned::Spanned;
-use crate::types::{rewrite_path, PathContext};
+use crate::types::{PathContext, rewrite_path};
 use crate::utils::{format_mutability, mk_sp, mk_sp_lo_plus_one, rewrite_ident};
 
 /// Returns `true` if the given pattern is "short".
@@ -61,25 +61,36 @@ fn is_short_pattern_inner(pat: &ast::Pat) -> bool {
     }
 }
 
-struct RangeOperand<'a>(&'a Option<ptr::P<ast::Expr>>);
+pub(crate) struct RangeOperand<'a> {
+    operand: &'a Option<ptr::P<ast::Expr>>,
+    pub(crate) span: Span,
+}
 
 impl<'a> Rewrite for RangeOperand<'a> {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
-        match &self.0 {
-            None => Some("".to_owned()),
-            Some(ref exp) => exp.rewrite(context, shape),
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
+        match &self.operand {
+            None => Ok("".to_owned()),
+            Some(ref exp) => exp.rewrite_result(context, shape),
         }
     }
 }
 
 impl Rewrite for Pat {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         match self.kind {
             PatKind::Or(ref pats) => {
                 let pat_strs = pats
                     .iter()
-                    .map(|p| p.rewrite(context, shape))
-                    .collect::<Option<Vec<_>>>()?;
+                    .map(|p| p.rewrite_result(context, shape))
+                    .collect::<Result<Vec<_>, RewriteError>>()?;
 
                 let use_mixed_layout = pats
                     .iter()
@@ -115,14 +126,21 @@ impl Rewrite for Pat {
                 let sub_pat = match *sub_pat {
                     Some(ref p) => {
                         // 2 - `@ `.
-                        let width = shape.width.checked_sub(
-                            mut_prefix.len() + ref_kw.len() + mut_infix.len() + id_str.len() + 2,
-                        )?;
+                        let width = shape
+                            .width
+                            .checked_sub(
+                                mut_prefix.len()
+                                    + ref_kw.len()
+                                    + mut_infix.len()
+                                    + id_str.len()
+                                    + 2,
+                            )
+                            .max_width_error(shape.width, p.span())?;
                         let lo = context.snippet_provider.span_after(self.span, "@");
                         combine_strs_with_missing_comments(
                             context,
                             "@",
-                            &p.rewrite(context, Shape::legacy(width, shape.indent))?,
+                            &p.rewrite_result(context, Shape::legacy(width, shape.indent))?,
                             mk_sp(lo, p.span.lo()),
                             shape,
                             true,
@@ -207,19 +225,25 @@ impl Rewrite for Pat {
             }
             PatKind::Wild => {
                 if 1 <= shape.width {
-                    Some("_".to_owned())
+                    Ok("_".to_owned())
                 } else {
-                    None
+                    Err(RewriteError::ExceedsMaxWidth {
+                        configured_width: 1,
+                        span: self.span,
+                    })
                 }
             }
             PatKind::Rest => {
                 if 1 <= shape.width {
-                    Some("..".to_owned())
+                    Ok("..".to_owned())
                 } else {
-                    None
+                    Err(RewriteError::ExceedsMaxWidth {
+                        configured_width: 1,
+                        span: self.span,
+                    })
                 }
             }
-            PatKind::Never => None,
+            PatKind::Never => Err(RewriteError::Unknown),
             PatKind::Range(ref lhs, ref rhs, ref end_kind) => {
                 let infix = match end_kind.node {
                     RangeEnd::Included(RangeSyntax::DotDotDot) => "...",
@@ -239,9 +263,17 @@ impl Rewrite for Pat {
                 } else {
                     infix.to_owned()
                 };
+                let lspan = self.span.with_hi(end_kind.span.lo());
+                let rspan = self.span.with_lo(end_kind.span.hi());
                 rewrite_pair(
-                    &RangeOperand(lhs),
-                    &RangeOperand(rhs),
+                    &RangeOperand {
+                        operand: lhs,
+                        span: lspan,
+                    },
+                    &RangeOperand {
+                        operand: rhs,
+                        span: rspan,
+                    },
                     PairParts::infix(&infix),
                     context,
                     shape,
@@ -260,19 +292,21 @@ impl Rewrite for Pat {
                 let path_str = rewrite_path(context, PathContext::Expr, q_self, path, shape)?;
                 rewrite_tuple_pat(pat_vec, Some(path_str), self.span, context, shape)
             }
-            PatKind::Lit(ref expr) => expr.rewrite(context, shape),
-            PatKind::Slice(ref slice_pat) if context.config.version() == Version::One => {
+            PatKind::Lit(ref expr) => expr.rewrite_result(context, shape),
+            PatKind::Slice(ref slice_pat)
+                if context.config.style_edition() <= StyleEdition::Edition2021 =>
+            {
                 let rw: Vec<String> = slice_pat
                     .iter()
                     .map(|p| {
-                        if let Some(rw) = p.rewrite(context, shape) {
+                        if let Ok(rw) = p.rewrite_result(context, shape) {
                             rw
                         } else {
                             context.snippet(p.span).to_string()
                         }
                     })
                     .collect();
-                Some(format!("[{}]", rw.join(", ")))
+                Ok(format!("[{}]", rw.join(", ")))
             }
             PatKind::Slice(ref slice_pat) => overflow::rewrite_with_square_brackets(
                 context,
@@ -296,10 +330,16 @@ impl Rewrite for Pat {
                 rewrite_macro(mac, None, context, shape, MacroPosition::Pat)
             }
             PatKind::Paren(ref pat) => pat
-                .rewrite(context, shape.offset_left(1)?.sub_width(1)?)
+                .rewrite_result(
+                    context,
+                    shape
+                        .offset_left(1)
+                        .and_then(|s| s.sub_width(1))
+                        .max_width_error(shape.width, self.span)?,
+                )
                 .map(|inner_pat| format!("({})", inner_pat)),
-            PatKind::Err(_) => None,
-            PatKind::Deref(_) => None,
+            PatKind::Err(_) => Err(RewriteError::Unknown),
+            PatKind::Deref(_) => Err(RewriteError::Unknown),
         }
     }
 }
@@ -312,20 +352,21 @@ fn rewrite_struct_pat(
     span: Span,
     context: &RewriteContext<'_>,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     // 2 =  ` {`
-    let path_shape = shape.sub_width(2)?;
+    let path_shape = shape.sub_width(2).max_width_error(shape.width, span)?;
     let path_str = rewrite_path(context, PathContext::Expr, qself, path, path_shape)?;
 
     if fields.is_empty() && !ellipsis {
-        return Some(format!("{path_str} {{}}"));
+        return Ok(format!("{path_str} {{}}"));
     }
 
     let (ellipsis_str, terminator) = if ellipsis { (", ..", "..") } else { ("", "}") };
 
     // 3 = ` { `, 2 = ` }`.
     let (h_shape, v_shape) =
-        struct_lit_shape(shape, context, path_str.len() + 3, ellipsis_str.len() + 2)?;
+        struct_lit_shape(shape, context, path_str.len() + 3, ellipsis_str.len() + 2)
+            .max_width_error(shape.width, span)?;
 
     let items = itemize_list(
         context.snippet_provider,
@@ -340,7 +381,7 @@ fn rewrite_struct_pat(
             }
         },
         |f| f.span.hi(),
-        |f| f.rewrite(context, v_shape),
+        |f| f.rewrite_result(context, v_shape),
         context.snippet_provider.span_after(span, "{"),
         span.hi(),
         false,
@@ -379,11 +420,15 @@ fn rewrite_struct_pat(
 
     // ast::Pat doesn't have attrs so use &[]
     let fields_str = wrap_struct_field(context, &[], &fields_str, shape, v_shape, one_line_width)?;
-    Some(format!("{path_str} {{{fields_str}}}"))
+    Ok(format!("{path_str} {{{fields_str}}}"))
 }
 
 impl Rewrite for PatField {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         let hi_pos = if let Some(last) = self.attrs.last() {
             last.span.hi()
         } else {
@@ -393,10 +438,10 @@ impl Rewrite for PatField {
         let attrs_str = if self.attrs.is_empty() {
             String::from("")
         } else {
-            self.attrs.rewrite(context, shape)?
+            self.attrs.rewrite_result(context, shape)?
         };
 
-        let pat_str = self.pat.rewrite(context, shape)?;
+        let pat_str = self.pat.rewrite_result(context, shape)?;
         if self.is_shorthand {
             combine_strs_with_missing_comments(
                 context,
@@ -417,7 +462,7 @@ impl Rewrite for PatField {
                     "{}:\n{}{}",
                     id_str,
                     nested_shape.indent.to_string(context.config),
-                    self.pat.rewrite(context, nested_shape)?
+                    self.pat.rewrite_result(context, nested_shape)?
                 )
             };
             combine_strs_with_missing_comments(
@@ -440,9 +485,13 @@ pub(crate) enum TuplePatField<'a> {
 
 impl<'a> Rewrite for TuplePatField<'a> {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         match *self {
-            TuplePatField::Pat(p) => p.rewrite(context, shape),
-            TuplePatField::Dotdot(_) => Some("..".to_string()),
+            TuplePatField::Pat(p) => p.rewrite_result(context, shape),
+            TuplePatField::Dotdot(_) => Ok("..".to_string()),
         }
     }
 }
@@ -492,9 +541,9 @@ fn rewrite_tuple_pat(
     span: Span,
     context: &RewriteContext<'_>,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     if pats.is_empty() {
-        return Some(format!("{}()", path_str.unwrap_or_default()));
+        return Ok(format!("{}()", path_str.unwrap_or_default()));
     }
     let mut pat_vec: Vec<_> = pats.iter().map(TuplePatField::Pat).collect();
 
@@ -548,7 +597,7 @@ fn count_wildcard_suffix_len(
         ",",
         |item| item.span().lo(),
         |item| item.span().hi(),
-        |item| item.rewrite(context, shape),
+        |item| item.rewrite_result(context, shape),
         context.snippet_provider.span_after(span, "("),
         span.hi() - BytePos(1),
         false,
@@ -558,7 +607,7 @@ fn count_wildcard_suffix_len(
     for item in items
         .iter()
         .rev()
-        .take_while(|i| matches!(i.item, Some(ref internal_string) if internal_string == "_"))
+        .take_while(|i| matches!(i.item, Ok(ref internal_string) if internal_string == "_"))
     {
         suffix_len += 1;
 
diff --git a/src/tools/rustfmt/src/reorder.rs b/src/tools/rustfmt/src/reorder.rs
index fdbed939af5..8a31e0ac816 100644
--- a/src/tools/rustfmt/src/reorder.rs
+++ b/src/tools/rustfmt/src/reorder.rs
@@ -9,13 +9,13 @@
 use std::cmp::Ordering;
 
 use rustc_ast::{ast, attr};
-use rustc_span::{symbol::sym, Span};
+use rustc_span::{Span, symbol::sym};
 
 use crate::config::{Config, GroupImportsTactic};
-use crate::imports::{normalize_use_trees_with_granularity, UseSegmentKind, UseTree};
+use crate::imports::{UseSegmentKind, UseTree, normalize_use_trees_with_granularity};
 use crate::items::{is_mod_decl, rewrite_extern_crate, rewrite_mod};
-use crate::lists::{itemize_list, write_list, ListFormatting, ListItem};
-use crate::rewrite::RewriteContext;
+use crate::lists::{ListFormatting, ListItem, itemize_list, write_list};
+use crate::rewrite::{RewriteContext, RewriteErrorExt};
 use crate::shape::Shape;
 use crate::source_map::LineRangeUtils;
 use crate::spanned::Spanned;
@@ -59,7 +59,7 @@ fn wrap_reorderable_items(
     let fmt = ListFormatting::new(shape, context.config)
         .separator("")
         .align_comments(false);
-    write_list(list_items, &fmt)
+    write_list(list_items, &fmt).ok()
 }
 
 fn rewrite_reorderable_item(
@@ -99,7 +99,7 @@ fn rewrite_reorderable_or_regroupable_items(
                 ";",
                 |item| item.span().lo(),
                 |item| item.span().hi(),
-                |_item| Some("".to_owned()),
+                |_item| Ok("".to_owned()),
                 span.lo(),
                 span.hi(),
                 false,
@@ -131,9 +131,16 @@ fn rewrite_reorderable_or_regroupable_items(
                 .map(|use_group| {
                     let item_vec: Vec<_> = use_group
                         .into_iter()
-                        .map(|use_tree| ListItem {
-                            item: use_tree.rewrite_top_level(context, nested_shape),
-                            ..use_tree.list_item.unwrap_or_else(ListItem::empty)
+                        .map(|use_tree| {
+                            let item = use_tree.rewrite_top_level(context, nested_shape);
+                            if let Some(list_item) = use_tree.list_item {
+                                ListItem {
+                                    item: item,
+                                    ..list_item
+                                }
+                            } else {
+                                ListItem::from_item(item)
+                            }
                         })
                         .collect();
                     wrap_reorderable_items(context, &item_vec, nested_shape)
@@ -151,7 +158,7 @@ fn rewrite_reorderable_or_regroupable_items(
                 ";",
                 |item| item.span().lo(),
                 |item| item.span().hi(),
-                |item| rewrite_reorderable_item(context, item, shape),
+                |item| rewrite_reorderable_item(context, item, shape).unknown_error(),
                 span.lo(),
                 span.hi(),
                 false,
diff --git a/src/tools/rustfmt/src/rewrite.rs b/src/tools/rustfmt/src/rewrite.rs
index e2498a3500a..83020709797 100644
--- a/src/tools/rustfmt/src/rewrite.rs
+++ b/src/tools/rustfmt/src/rewrite.rs
@@ -5,17 +5,23 @@ use std::rc::Rc;
 
 use rustc_ast::ptr;
 use rustc_span::Span;
+use thiserror::Error;
 
+use crate::FormatReport;
 use crate::config::{Config, IndentStyle};
 use crate::parse::session::ParseSess;
 use crate::shape::Shape;
 use crate::skip::SkipContext;
 use crate::visitor::SnippetProvider;
-use crate::FormatReport;
 
+pub(crate) type RewriteResult = Result<String, RewriteError>;
 pub(crate) trait Rewrite {
     /// Rewrite self into shape.
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>;
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
+        self.rewrite(context, shape).unknown_error()
+    }
 }
 
 impl<T: Rewrite> Rewrite for ptr::P<T> {
@@ -24,6 +30,66 @@ impl<T: Rewrite> Rewrite for ptr::P<T> {
     }
 }
 
+#[derive(Clone, Debug, PartialEq)]
+pub(crate) enum MacroErrorKind {
+    ParseFailure,
+    ReplaceMacroVariable,
+    Unknown,
+}
+
+impl std::fmt::Display for MacroErrorKind {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        match self {
+            MacroErrorKind::ParseFailure => write!(f, "(parse failure)"),
+            MacroErrorKind::ReplaceMacroVariable => write!(f, "(replacing macro variables with $)"),
+            MacroErrorKind::Unknown => write!(f, ""),
+        }
+    }
+}
+
+#[derive(Clone, Error, Debug)]
+pub(crate) enum RewriteError {
+    #[error("Formatting was skipped due to skip attribute or out of file range.")]
+    SkipFormatting,
+
+    #[error("It exceeds the required width of {configured_width} for the span: {span:?}")]
+    ExceedsMaxWidth { configured_width: usize, span: Span },
+
+    #[error("Failed to format given macro{} at: {span:?}", kind)]
+    MacroFailure { kind: MacroErrorKind, span: Span },
+
+    /// Format failure that does not fit to above categories.
+    #[error("An unknown error occurred during formatting.")]
+    Unknown,
+}
+
+/// Extension trait used to conveniently convert to RewriteError
+pub(crate) trait RewriteErrorExt<T> {
+    fn max_width_error(self, width: usize, span: Span) -> Result<T, RewriteError>;
+    fn macro_error(self, kind: MacroErrorKind, span: Span) -> Result<T, RewriteError>;
+    fn unknown_error(self) -> Result<T, RewriteError>;
+}
+
+impl<T> RewriteErrorExt<T> for Option<T> {
+    fn max_width_error(self, width: usize, span: Span) -> Result<T, RewriteError> {
+        self.ok_or_else(|| RewriteError::ExceedsMaxWidth {
+            configured_width: width,
+            span: span,
+        })
+    }
+
+    fn macro_error(self, kind: MacroErrorKind, span: Span) -> Result<T, RewriteError> {
+        self.ok_or_else(|| RewriteError::MacroFailure {
+            kind: kind,
+            span: span,
+        })
+    }
+
+    fn unknown_error(self) -> Result<T, RewriteError> {
+        self.ok_or_else(|| RewriteError::Unknown)
+    }
+}
+
 #[derive(Clone)]
 pub(crate) struct RewriteContext<'a> {
     pub(crate) psess: &'a ParseSess,
diff --git a/src/tools/rustfmt/src/rustfmt_diff.rs b/src/tools/rustfmt/src/rustfmt_diff.rs
index c9883452185..4624683fa05 100644
--- a/src/tools/rustfmt/src/rustfmt_diff.rs
+++ b/src/tools/rustfmt/src/rustfmt_diff.rs
@@ -282,7 +282,7 @@ where
 #[cfg(test)]
 mod test {
     use super::DiffLine::*;
-    use super::{make_diff, Mismatch};
+    use super::{Mismatch, make_diff};
     use super::{ModifiedChunk, ModifiedLines};
 
     #[test]
diff --git a/src/tools/rustfmt/src/sort.rs b/src/tools/rustfmt/src/sort.rs
new file mode 100644
index 00000000000..670f664a119
--- /dev/null
+++ b/src/tools/rustfmt/src/sort.rs
@@ -0,0 +1,368 @@
+use itertools::EitherOrBoth;
+use itertools::Itertools;
+
+/// Iterator which breaks an identifier into various [VersionChunk]s.
+struct VersionChunkIter<'a> {
+    ident: &'a str,
+    start: usize,
+}
+
+impl<'a> VersionChunkIter<'a> {
+    pub(crate) fn new(ident: &'a str) -> Self {
+        Self { ident, start: 0 }
+    }
+
+    fn parse_numeric_chunk(
+        &mut self,
+        mut chars: std::str::CharIndices<'a>,
+    ) -> Option<VersionChunk<'a>> {
+        let mut end = self.start;
+        let mut is_end_of_chunk = false;
+
+        while let Some((idx, c)) = chars.next() {
+            end = self.start + idx;
+
+            if c.is_ascii_digit() {
+                continue;
+            }
+
+            is_end_of_chunk = true;
+            break;
+        }
+
+        let source = if is_end_of_chunk {
+            let value = &self.ident[self.start..end];
+            self.start = end;
+            value
+        } else {
+            let value = &self.ident[self.start..];
+            self.start = self.ident.len();
+            value
+        };
+
+        let zeros = source.chars().take_while(|c| *c == '0').count();
+        let value = source.parse::<usize>().ok()?;
+
+        Some(VersionChunk::Number {
+            value,
+            zeros,
+            source,
+        })
+    }
+
+    fn parse_str_chunk(
+        &mut self,
+        mut chars: std::str::CharIndices<'a>,
+    ) -> Option<VersionChunk<'a>> {
+        let mut end = self.start;
+        let mut is_end_of_chunk = false;
+
+        while let Some((idx, c)) = chars.next() {
+            end = self.start + idx;
+
+            if c == '_' {
+                is_end_of_chunk = true;
+                break;
+            }
+
+            if !c.is_numeric() {
+                continue;
+            }
+
+            is_end_of_chunk = true;
+            break;
+        }
+
+        let source = if is_end_of_chunk {
+            let value = &self.ident[self.start..end];
+            self.start = end;
+            value
+        } else {
+            let value = &self.ident[self.start..];
+            self.start = self.ident.len();
+            value
+        };
+
+        Some(VersionChunk::Str(source))
+    }
+}
+
+impl<'a> Iterator for VersionChunkIter<'a> {
+    type Item = VersionChunk<'a>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let mut chars = self.ident[self.start..].char_indices();
+        let (_, next) = chars.next()?;
+
+        if next == '_' {
+            self.start = self.start + next.len_utf8();
+            return Some(VersionChunk::Underscore);
+        }
+
+        if next.is_ascii_digit() {
+            return self.parse_numeric_chunk(chars);
+        }
+
+        self.parse_str_chunk(chars)
+    }
+}
+
+/// Represents a chunk in the version-sort algorithm
+#[derive(Debug, PartialEq, Eq)]
+enum VersionChunk<'a> {
+    /// A single `_` in an identifier. Underscores are sorted before all other characters.
+    Underscore,
+    /// A &str chunk in the version sort.
+    Str(&'a str),
+    /// A numeric chunk in the version sort. Keeps track of the numeric value and leading zeros.
+    Number {
+        value: usize,
+        zeros: usize,
+        source: &'a str,
+    },
+}
+
+/// Determine which side of the version-sort comparison had more leading zeros.
+#[derive(Debug, PartialEq, Eq)]
+enum MoreLeadingZeros {
+    Left,
+    Right,
+    Equal,
+}
+
+/// Compare two identifiers based on the version sorting algorithm described in [the style guide]
+///
+/// [the style guide]: https://doc.rust-lang.org/nightly/style-guide/#sorting
+pub(crate) fn version_sort(a: &str, b: &str) -> std::cmp::Ordering {
+    let iter_a = VersionChunkIter::new(a);
+    let iter_b = VersionChunkIter::new(b);
+    let mut more_leading_zeros = MoreLeadingZeros::Equal;
+
+    for either_or_both in iter_a.zip_longest(iter_b) {
+        match either_or_both {
+            EitherOrBoth::Left(_) => return std::cmp::Ordering::Greater,
+            EitherOrBoth::Right(_) => return std::cmp::Ordering::Less,
+            EitherOrBoth::Both(a, b) => match (a, b) {
+                (VersionChunk::Underscore, VersionChunk::Underscore) => {
+                    continue;
+                }
+                (VersionChunk::Underscore, _) => return std::cmp::Ordering::Less,
+                (_, VersionChunk::Underscore) => return std::cmp::Ordering::Greater,
+                (VersionChunk::Str(ca), VersionChunk::Str(cb))
+                | (VersionChunk::Str(ca), VersionChunk::Number { source: cb, .. })
+                | (VersionChunk::Number { source: ca, .. }, VersionChunk::Str(cb)) => {
+                    match ca.cmp(&cb) {
+                        std::cmp::Ordering::Equal => {
+                            continue;
+                        }
+                        order @ _ => return order,
+                    }
+                }
+                (
+                    VersionChunk::Number {
+                        value: va,
+                        zeros: lza,
+                        ..
+                    },
+                    VersionChunk::Number {
+                        value: vb,
+                        zeros: lzb,
+                        ..
+                    },
+                ) => match va.cmp(&vb) {
+                    std::cmp::Ordering::Equal => {
+                        if lza == lzb {
+                            continue;
+                        }
+
+                        if more_leading_zeros == MoreLeadingZeros::Equal && lza > lzb {
+                            more_leading_zeros = MoreLeadingZeros::Left;
+                        } else if more_leading_zeros == MoreLeadingZeros::Equal && lza < lzb {
+                            more_leading_zeros = MoreLeadingZeros::Right;
+                        }
+                        continue;
+                    }
+                    order @ _ => return order,
+                },
+            },
+        }
+    }
+
+    match more_leading_zeros {
+        MoreLeadingZeros::Equal => std::cmp::Ordering::Equal,
+        MoreLeadingZeros::Left => std::cmp::Ordering::Less,
+        MoreLeadingZeros::Right => std::cmp::Ordering::Greater,
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+
+    #[test]
+    fn test_chunks() {
+        let mut iter = VersionChunkIter::new("x86_128");
+        assert_eq!(iter.next(), Some(VersionChunk::Str("x")));
+        assert_eq!(
+            iter.next(),
+            Some(VersionChunk::Number {
+                value: 86,
+                zeros: 0,
+                source: "86"
+            })
+        );
+        assert_eq!(iter.next(), Some(VersionChunk::Underscore));
+        assert_eq!(
+            iter.next(),
+            Some(VersionChunk::Number {
+                value: 128,
+                zeros: 0,
+                source: "128"
+            })
+        );
+        assert_eq!(iter.next(), None);
+
+        let mut iter = VersionChunkIter::new("w005s09t");
+        assert_eq!(iter.next(), Some(VersionChunk::Str("w")));
+        assert_eq!(
+            iter.next(),
+            Some(VersionChunk::Number {
+                value: 5,
+                zeros: 2,
+                source: "005"
+            })
+        );
+        assert_eq!(iter.next(), Some(VersionChunk::Str("s")));
+        assert_eq!(
+            iter.next(),
+            Some(VersionChunk::Number {
+                value: 9,
+                zeros: 1,
+                source: "09"
+            })
+        );
+        assert_eq!(iter.next(), Some(VersionChunk::Str("t")));
+        assert_eq!(iter.next(), None);
+
+        let mut iter = VersionChunkIter::new("ZY_WX");
+        assert_eq!(iter.next(), Some(VersionChunk::Str("ZY")));
+        assert_eq!(iter.next(), Some(VersionChunk::Underscore));
+        assert_eq!(iter.next(), Some(VersionChunk::Str("WX")));
+
+        let mut iter = VersionChunkIter::new("_v1");
+        assert_eq!(iter.next(), Some(VersionChunk::Underscore));
+        assert_eq!(iter.next(), Some(VersionChunk::Str("v")));
+        assert_eq!(
+            iter.next(),
+            Some(VersionChunk::Number {
+                value: 1,
+                zeros: 0,
+                source: "1"
+            })
+        );
+
+        let mut iter = VersionChunkIter::new("_1v");
+        assert_eq!(iter.next(), Some(VersionChunk::Underscore));
+        assert_eq!(
+            iter.next(),
+            Some(VersionChunk::Number {
+                value: 1,
+                zeros: 0,
+                source: "1"
+            })
+        );
+        assert_eq!(iter.next(), Some(VersionChunk::Str("v")));
+
+        let mut iter = VersionChunkIter::new("v009");
+        assert_eq!(iter.next(), Some(VersionChunk::Str("v")));
+        assert_eq!(
+            iter.next(),
+            Some(VersionChunk::Number {
+                value: 9,
+                zeros: 2,
+                source: "009"
+            })
+        );
+    }
+
+    #[test]
+    fn test_version_sort() {
+        let mut input = vec!["", "b", "a"];
+        let expected = vec!["", "a", "b"];
+        input.sort_by(|a, b| version_sort(a, b));
+        assert_eq!(input, expected);
+
+        let mut input = vec!["x7x", "xxx"];
+        let expected = vec!["x7x", "xxx"];
+        input.sort_by(|a, b| version_sort(a, b));
+        assert_eq!(input, expected);
+
+        let mut input = vec!["applesauce", "apple"];
+        let expected = vec!["apple", "applesauce"];
+        input.sort_by(|a, b| version_sort(a, b));
+        assert_eq!(input, expected);
+
+        let mut input = vec!["aaaaa", "aaa_a"];
+        let expected = vec!["aaa_a", "aaaaa"];
+        input.sort_by(|a, b| version_sort(a, b));
+        assert_eq!(input, expected);
+
+        let mut input = vec!["AAAAA", "AAA1A", "BBBBB", "BB_BB", "C3CCC"];
+        let expected = vec!["AAA1A", "AAAAA", "BB_BB", "BBBBB", "C3CCC"];
+        input.sort_by(|a, b| version_sort(a, b));
+        assert_eq!(input, expected);
+
+        let mut input = vec!["1_000_000", "1_010_001"];
+        let expected = vec!["1_000_000", "1_010_001"];
+        input.sort_by(|a, b| version_sort(a, b));
+        assert_eq!(input, expected);
+
+        let mut input = vec![
+            "5", "50", "500", "5_000", "5_005", "5_050", "5_500", "50_000", "50_005", "50_050",
+            "50_500",
+        ];
+        let expected = vec![
+            "5", "5_000", "5_005", "5_050", "5_500", "50", "50_000", "50_005", "50_050", "50_500",
+            "500",
+        ];
+        input.sort_by(|a, b| version_sort(a, b));
+        assert_eq!(input, expected);
+
+        let mut input = vec!["X86_64", "x86_64", "X86_128", "x86_128"];
+        let expected = vec!["X86_64", "X86_128", "x86_64", "x86_128"];
+        input.sort_by(|a, b| version_sort(a, b));
+        assert_eq!(input, expected);
+
+        let mut input = vec!["__", "_"];
+        let expected = vec!["_", "__"];
+        input.sort_by(|a, b| version_sort(a, b));
+        assert_eq!(input, expected);
+
+        let mut input = vec!["foo_", "foo"];
+        let expected = vec!["foo", "foo_"];
+        input.sort_by(|a, b| version_sort(a, b));
+        assert_eq!(input, expected);
+
+        let mut input = vec!["A", "AA", "B", "a", "aA", "aa", "b"];
+        let expected = vec!["A", "AA", "B", "a", "aA", "aa", "b"];
+        input.sort_by(|a, b| version_sort(a, b));
+        assert_eq!(input, expected);
+
+        let mut input = vec![
+            "x86_128", "usize", "uz", "v000", "v00", "v0", "v0s", "v00t", "v0u", "v001", "v01",
+            "v1", "v009", "x87", "zyxw", "_ZYXW", "_abcd", "A2", "ABCD", "Z_YXW", "ZY_XW", "ZY_XW",
+            "ZYXW", "v09", "v9", "v010", "v10", "w005s09t", "w5s009t", "x64", "x86", "x86_32",
+            "ua", "x86_64", "ZYXW_", "a1", "abcd", "u_zzz", "u8", "u16", "u32", "u64", "u128",
+            "u256",
+        ];
+        let expected = vec![
+            "_ZYXW", "_abcd", "A2", "ABCD", "Z_YXW", "ZY_XW", "ZY_XW", "ZYXW", "ZYXW_", "a1",
+            "abcd", "u_zzz", "u8", "u16", "u32", "u64", "u128", "u256", "ua", "usize", "uz",
+            "v000", "v00", "v0", "v0s", "v00t", "v0u", "v001", "v01", "v1", "v009", "v09", "v9",
+            "v010", "v10", "w005s09t", "w5s009t", "x64", "x86", "x86_32", "x86_64", "x86_128",
+            "x87", "zyxw",
+        ];
+        input.sort_by(|a, b| version_sort(a, b));
+        assert_eq!(input, expected)
+    }
+}
diff --git a/src/tools/rustfmt/src/source_file.rs b/src/tools/rustfmt/src/source_file.rs
index 5eea8021b32..73f8ecb5529 100644
--- a/src/tools/rustfmt/src/source_file.rs
+++ b/src/tools/rustfmt/src/source_file.rs
@@ -2,10 +2,10 @@ use std::fs;
 use std::io::{self, Write};
 use std::path::Path;
 
+use crate::NewlineStyle;
 use crate::config::FileName;
 use crate::emitter::{self, Emitter};
 use crate::parse::session::ParseSess;
-use crate::NewlineStyle;
 
 #[cfg(test)]
 use crate::config::Config;
diff --git a/src/tools/rustfmt/src/spanned.rs b/src/tools/rustfmt/src/spanned.rs
index 1ee691b4ade..b4424e476ee 100644
--- a/src/tools/rustfmt/src/spanned.rs
+++ b/src/tools/rustfmt/src/spanned.rs
@@ -1,9 +1,10 @@
 use std::cmp::max;
 
 use rustc_ast::{ast, ptr};
-use rustc_span::{source_map, Span};
+use rustc_span::{Span, source_map};
 
 use crate::macros::MacroArg;
+use crate::patterns::RangeOperand;
 use crate::utils::{mk_sp, outer_attributes};
 
 /// Spanned returns a span including attributes, if available.
@@ -212,3 +213,9 @@ impl Spanned for ast::PreciseCapturingArg {
         }
     }
 }
+
+impl<'a> Spanned for RangeOperand<'a> {
+    fn span(&self) -> Span {
+        self.span
+    }
+}
diff --git a/src/tools/rustfmt/src/stmt.rs b/src/tools/rustfmt/src/stmt.rs
index 73a9cce416c..2788159018d 100644
--- a/src/tools/rustfmt/src/stmt.rs
+++ b/src/tools/rustfmt/src/stmt.rs
@@ -2,9 +2,9 @@ use rustc_ast::ast;
 use rustc_span::Span;
 
 use crate::comment::recover_comment_removed;
-use crate::config::Version;
-use crate::expr::{format_expr, is_simple_block, ExprType};
-use crate::rewrite::{Rewrite, RewriteContext};
+use crate::config::StyleEdition;
+use crate::expr::{ExprType, format_expr, is_simple_block};
+use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult};
 use crate::shape::Shape;
 use crate::source_map::LineRangeUtils;
 use crate::spanned::Spanned;
@@ -90,11 +90,20 @@ impl<'a> Stmt<'a> {
 
 impl<'a> Rewrite for Stmt<'a> {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
-        let expr_type = if context.config.version() == Version::Two && self.is_last_expr() {
-            ExprType::SubExpression
-        } else {
-            ExprType::Statement
-        };
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(
+        &self,
+        context: &RewriteContext<'_>,
+        shape: Shape,
+    ) -> crate::rewrite::RewriteResult {
+        let expr_type =
+            if context.config.style_edition() >= StyleEdition::Edition2024 && self.is_last_expr() {
+                ExprType::SubExpression
+            } else {
+                ExprType::Statement
+            };
         format_stmt(
             context,
             shape,
@@ -111,11 +120,11 @@ fn format_stmt(
     stmt: &ast::Stmt,
     expr_type: ExprType,
     is_last_expr: bool,
-) -> Option<String> {
-    skip_out_of_file_lines_range!(context, stmt.span());
+) -> RewriteResult {
+    skip_out_of_file_lines_range_err!(context, stmt.span());
 
     let result = match stmt.kind {
-        ast::StmtKind::Let(ref local) => local.rewrite(context, shape),
+        ast::StmtKind::Let(ref local) => local.rewrite_result(context, shape),
         ast::StmtKind::Expr(ref ex) | ast::StmtKind::Semi(ref ex) => {
             let suffix = if semicolon_for_stmt(context, stmt, is_last_expr) {
                 ";"
@@ -123,10 +132,14 @@ fn format_stmt(
                 ""
             };
 
-            let shape = shape.sub_width(suffix.len())?;
+            let shape = shape
+                .sub_width(suffix.len())
+                .max_width_error(shape.width, ex.span())?;
             format_expr(ex, expr_type, context, shape).map(|s| s + suffix)
         }
-        ast::StmtKind::MacCall(..) | ast::StmtKind::Item(..) | ast::StmtKind::Empty => None,
+        ast::StmtKind::MacCall(..) | ast::StmtKind::Item(..) | ast::StmtKind::Empty => {
+            Err(RewriteError::Unknown)
+        }
     };
-    result.and_then(|res| recover_comment_removed(res, stmt.span(), context))
+    result.map(|res| recover_comment_removed(res, stmt.span(), context))
 }
diff --git a/src/tools/rustfmt/src/string.rs b/src/tools/rustfmt/src/string.rs
index cb666fff695..3b971188cd5 100644
--- a/src/tools/rustfmt/src/string.rs
+++ b/src/tools/rustfmt/src/string.rs
@@ -84,7 +84,7 @@ pub(crate) fn rewrite_string<'a>(
         stripped_str
             .len()
             .checked_next_power_of_two()
-            .unwrap_or(usize::max_value()),
+            .unwrap_or(usize::MAX),
     );
     result.push_str(fmt.opener);
 
@@ -375,7 +375,7 @@ fn graphemes_width(graphemes: &[&str]) -> usize {
 
 #[cfg(test)]
 mod test {
-    use super::{break_string, detect_url, rewrite_string, SnippetState, StringFormat};
+    use super::{SnippetState, StringFormat, break_string, detect_url, rewrite_string};
     use crate::config::Config;
     use crate::shape::{Indent, Shape};
     use unicode_segmentation::UnicodeSegmentation;
diff --git a/src/tools/rustfmt/src/test/configuration_snippet.rs b/src/tools/rustfmt/src/test/configuration_snippet.rs
index e4a390ada66..5b93703de0b 100644
--- a/src/tools/rustfmt/src/test/configuration_snippet.rs
+++ b/src/tools/rustfmt/src/test/configuration_snippet.rs
@@ -4,9 +4,9 @@ use std::io::{BufRead, BufReader, Write};
 use std::iter::Enumerate;
 use std::path::{Path, PathBuf};
 
-use super::{print_mismatches, write_message, DIFF_CONTEXT_SIZE};
+use super::{DIFF_CONTEXT_SIZE, print_mismatches, write_message};
 use crate::config::{Config, EmitMode, Verbosity};
-use crate::rustfmt_diff::{make_diff, Mismatch};
+use crate::rustfmt_diff::{Mismatch, make_diff};
 use crate::{Input, Session};
 
 const CONFIGURATIONS_FILE_NAME: &str = "Configurations.md";
diff --git a/src/tools/rustfmt/src/test/mod.rs b/src/tools/rustfmt/src/test/mod.rs
index 286e8b8760a..d62da08fff8 100644
--- a/src/tools/rustfmt/src/test/mod.rs
+++ b/src/tools/rustfmt/src/test/mod.rs
@@ -6,14 +6,17 @@ use std::iter::Peekable;
 use std::mem;
 use std::path::{Path, PathBuf};
 use std::process::{Command, Stdio};
-use std::str::Chars;
+use std::str::{Chars, FromStr};
 use std::thread;
 
 use crate::config::{Color, Config, EmitMode, FileName, NewlineStyle};
 use crate::formatting::{ReportedErrors, SourceFile};
-use crate::rustfmt_diff::{make_diff, print_diff, DiffLine, Mismatch, ModifiedChunk, OutputWriter};
+use crate::rustfmt_diff::{DiffLine, Mismatch, ModifiedChunk, OutputWriter, make_diff, print_diff};
 use crate::source_file;
-use crate::{is_nightly_channel, FormatReport, FormatReportFormatterBuilder, Input, Session};
+use crate::{
+    Edition, FormatReport, FormatReportFormatterBuilder, Input, Session, StyleEdition, Version,
+    is_nightly_channel,
+};
 
 use rustfmt_config_proc_macro::nightly_only_test;
 use tracing::{debug, warn};
@@ -102,10 +105,9 @@ fn is_file_skip(path: &Path) -> bool {
 fn get_test_files(path: &Path, recursive: bool) -> Vec<PathBuf> {
     let mut files = vec![];
     if path.is_dir() {
-        for entry in fs::read_dir(path).expect(&format!(
-            "couldn't read directory {}",
-            path.to_str().unwrap()
-        )) {
+        for entry in
+            fs::read_dir(path).expect(&format!("couldn't read directory {}", path.display()))
+        {
             let entry = entry.expect("couldn't get `DirEntry`");
             let path = entry.path();
             if path.is_dir() && recursive {
@@ -119,10 +121,7 @@ fn get_test_files(path: &Path, recursive: bool) -> Vec<PathBuf> {
 }
 
 fn verify_config_used(path: &Path, config_name: &str) {
-    for entry in fs::read_dir(path).expect(&format!(
-        "couldn't read {} directory",
-        path.to_str().unwrap()
-    )) {
+    for entry in fs::read_dir(path).expect(&format!("couldn't read {} directory", path.display())) {
         let entry = entry.expect("couldn't get directory entry");
         let path = entry.path();
         if path.extension().map_or(false, |f| f == "rs") {
@@ -711,13 +710,24 @@ fn print_mismatches<T: Fn(u32) -> String>(
 
 fn read_config(filename: &Path) -> Config {
     let sig_comments = read_significant_comments(filename);
+    let (edition, style_edition, version) = get_editions_from_comments(&sig_comments);
     // Look for a config file. If there is a 'config' property in the significant comments, use
     // that. Otherwise, if there are no significant comments at all, look for a config file with
     // the same name as the test file.
     let mut config = if !sig_comments.is_empty() {
-        get_config(sig_comments.get("config").map(Path::new))
+        get_config(
+            sig_comments.get("config").map(Path::new),
+            edition,
+            style_edition,
+            version,
+        )
     } else {
-        get_config(filename.with_extension("toml").file_name().map(Path::new))
+        get_config(
+            filename.with_extension("toml").file_name().map(Path::new),
+            edition,
+            style_edition,
+            version,
+        )
     };
 
     for (key, val) in &sig_comments {
@@ -748,13 +758,31 @@ enum IdempotentCheckError {
     Parse,
 }
 
+fn get_editions_from_comments(
+    comments: &HashMap<String, String>,
+) -> (Option<Edition>, Option<StyleEdition>, Option<Version>) {
+    (
+        comments
+            .get("edition")
+            .map(|e| Edition::from_str(e).expect(&format!("invalid edition value: '{}'", e))),
+        comments.get("style_edition").map(|se| {
+            StyleEdition::from_str(se).expect(&format!("invalid style_edition value: '{}'", se))
+        }),
+        comments
+            .get("version")
+            .map(|v| Version::from_str(v).expect(&format!("invalid version value: '{}'", v))),
+    )
+}
+
 fn idempotent_check(
     filename: &PathBuf,
     opt_config: &Option<PathBuf>,
 ) -> Result<FormatReport, IdempotentCheckError> {
     let sig_comments = read_significant_comments(filename);
     let config = if let Some(ref config_file_path) = opt_config {
-        Config::from_toml_path(config_file_path).expect("`rustfmt.toml` not found")
+        let (edition, style_edition, version) = get_editions_from_comments(&sig_comments);
+        Config::from_toml_path(config_file_path, edition, style_edition, version)
+            .expect("`rustfmt.toml` not found")
     } else {
         read_config(filename)
     };
@@ -778,14 +806,19 @@ fn idempotent_check(
 // Reads test config file using the supplied (optional) file name. If there's no file name or the
 // file doesn't exist, just return the default config. Otherwise, the file must be read
 // successfully.
-fn get_config(config_file: Option<&Path>) -> Config {
+fn get_config(
+    config_file: Option<&Path>,
+    edition: Option<Edition>,
+    style_edition: Option<StyleEdition>,
+    version: Option<Version>,
+) -> Config {
     let config_file_name = match config_file {
-        None => return Default::default(),
+        None => return Config::default_for_possible_style_edition(style_edition, edition, version),
         Some(file_name) => {
             let mut full_path = PathBuf::from("tests/config/");
             full_path.push(file_name);
             if !full_path.exists() {
-                return Default::default();
+                return Config::default_for_possible_style_edition(style_edition, edition, version);
             };
             full_path
         }
@@ -797,7 +830,14 @@ fn get_config(config_file: Option<&Path>) -> Config {
         .read_to_string(&mut def_config)
         .expect("Couldn't read config");
 
-    Config::from_toml(&def_config, Path::new("tests/config/")).expect("invalid TOML")
+    Config::from_toml_for_style_edition(
+        &def_config,
+        Path::new("tests/config/"),
+        edition,
+        style_edition,
+        version,
+    )
+    .expect("invalid TOML")
 }
 
 // Reads significant comments of the form: `// rustfmt-key: value` into a hash map.
diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs
index 7730aa467ce..07b483b2b37 100644
--- a/src/tools/rustfmt/src/types.rs
+++ b/src/tools/rustfmt/src/types.rs
@@ -2,23 +2,23 @@ use std::ops::Deref;
 
 use rustc_ast::ast::{self, FnRetTy, Mutability, Term};
 use rustc_ast::ptr;
-use rustc_span::{symbol::kw, BytePos, Pos, Span};
+use rustc_span::{BytePos, Pos, Span, symbol::kw};
 use tracing::debug;
 
 use crate::comment::{combine_strs_with_missing_comments, contains_comment};
 use crate::config::lists::*;
-use crate::config::{IndentStyle, TypeDensity, Version};
+use crate::config::{IndentStyle, StyleEdition, TypeDensity};
 use crate::expr::{
-    format_expr, rewrite_assign_rhs, rewrite_call, rewrite_tuple, rewrite_unary_prefix, ExprType,
-    RhsAssignKind,
+    ExprType, RhsAssignKind, format_expr, rewrite_assign_rhs, rewrite_call, rewrite_tuple,
+    rewrite_unary_prefix,
 };
 use crate::lists::{
-    definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator,
+    ListFormatting, ListItem, Separator, definitive_tactic, itemize_list, write_list,
 };
-use crate::macros::{rewrite_macro, MacroPosition};
+use crate::macros::{MacroPosition, rewrite_macro};
 use crate::overflow;
-use crate::pairs::{rewrite_pair, PairParts};
-use crate::rewrite::{Rewrite, RewriteContext};
+use crate::pairs::{PairParts, rewrite_pair};
+use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult};
 use crate::shape::Shape;
 use crate::source_map::SpanUtils;
 use crate::spanned::Spanned;
@@ -41,7 +41,7 @@ pub(crate) fn rewrite_path(
     qself: &Option<ptr::P<ast::QSelf>>,
     path: &ast::Path,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     let skip_count = qself.as_ref().map_or(0, |x| x.position);
 
     // 32 covers almost all path lengths measured when compiling core, and there isn't a big
@@ -57,7 +57,7 @@ pub(crate) fn rewrite_path(
     if let Some(qself) = qself {
         result.push('<');
 
-        let fmt_ty = qself.ty.rewrite(context, shape)?;
+        let fmt_ty = qself.ty.rewrite_result(context, shape)?;
         result.push_str(&fmt_ty);
 
         if skip_count > 0 {
@@ -67,7 +67,7 @@ pub(crate) fn rewrite_path(
             }
 
             // 3 = ">::".len()
-            let shape = shape.sub_width(3)?;
+            let shape = shape.sub_width(3).max_width_error(shape.width, path.span)?;
 
             result = rewrite_path_segments(
                 PathContext::Type,
@@ -103,7 +103,7 @@ fn rewrite_path_segments<'a, I>(
     span_hi: BytePos,
     context: &RewriteContext<'_>,
     shape: Shape,
-) -> Option<String>
+) -> RewriteResult
 where
     I: Iterator<Item = &'a ast::PathSegment>,
 {
@@ -122,7 +122,9 @@ where
         }
 
         let extra_offset = extra_offset(&buffer, shape);
-        let new_shape = shape.shrink_left(extra_offset)?;
+        let new_shape = shape
+            .shrink_left(extra_offset)
+            .max_width_error(shape.width, mk_sp(span_lo, span_hi))?;
         let segment_string = rewrite_segment(
             path_context,
             segment,
@@ -135,7 +137,7 @@ where
         buffer.push_str(&segment_string);
     }
 
-    Some(buffer)
+    Ok(buffer)
 }
 
 #[derive(Debug)]
@@ -169,19 +171,27 @@ impl<'a> Spanned for SegmentParam<'a> {
 
 impl<'a> Rewrite for SegmentParam<'a> {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         match *self {
-            SegmentParam::Const(const_) => const_.rewrite(context, shape),
-            SegmentParam::LifeTime(lt) => lt.rewrite(context, shape),
-            SegmentParam::Type(ty) => ty.rewrite(context, shape),
-            SegmentParam::Binding(atc) => atc.rewrite(context, shape),
+            SegmentParam::Const(const_) => const_.rewrite_result(context, shape),
+            SegmentParam::LifeTime(lt) => lt.rewrite_result(context, shape),
+            SegmentParam::Type(ty) => ty.rewrite_result(context, shape),
+            SegmentParam::Binding(atc) => atc.rewrite_result(context, shape),
         }
     }
 }
 
 impl Rewrite for ast::PreciseCapturingArg {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         match self {
-            ast::PreciseCapturingArg::Lifetime(lt) => lt.rewrite(context, shape),
+            ast::PreciseCapturingArg::Lifetime(lt) => lt.rewrite_result(context, shape),
             ast::PreciseCapturingArg::Arg(p, _) => {
                 rewrite_path(context, PathContext::Type, &None, p, shape)
             }
@@ -191,13 +201,20 @@ impl Rewrite for ast::PreciseCapturingArg {
 
 impl Rewrite for ast::AssocItemConstraint {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         use ast::AssocItemConstraintKind::{Bound, Equality};
 
         let mut result = String::with_capacity(128);
         result.push_str(rewrite_ident(context, self.ident));
 
         if let Some(ref gen_args) = self.gen_args {
-            let budget = shape.width.checked_sub(result.len())?;
+            let budget = shape
+                .width
+                .checked_sub(result.len())
+                .max_width_error(shape.width, self.span)?;
             let shape = Shape::legacy(budget, shape.indent + result.len());
             let gen_str = rewrite_generic_args(gen_args, context, shape, gen_args.span())?;
             result.push_str(&gen_str);
@@ -210,23 +227,30 @@ impl Rewrite for ast::AssocItemConstraint {
         };
         result.push_str(infix);
 
-        let budget = shape.width.checked_sub(result.len())?;
+        let budget = shape
+            .width
+            .checked_sub(result.len())
+            .max_width_error(shape.width, self.span)?;
         let shape = Shape::legacy(budget, shape.indent + result.len());
-        let rewrite = self.kind.rewrite(context, shape)?;
+        let rewrite = self.kind.rewrite_result(context, shape)?;
         result.push_str(&rewrite);
 
-        Some(result)
+        Ok(result)
     }
 }
 
 impl Rewrite for ast::AssocItemConstraintKind {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         match self {
             ast::AssocItemConstraintKind::Equality { term } => match term {
-                Term::Ty(ty) => ty.rewrite(context, shape),
-                Term::Const(c) => c.rewrite(context, shape),
+                Term::Ty(ty) => ty.rewrite_result(context, shape),
+                Term::Const(c) => c.rewrite_result(context, shape),
             },
-            ast::AssocItemConstraintKind::Bound { bounds } => bounds.rewrite(context, shape),
+            ast::AssocItemConstraintKind::Bound { bounds } => bounds.rewrite_result(context, shape),
         }
     }
 }
@@ -248,16 +272,17 @@ fn rewrite_segment(
     span_hi: BytePos,
     context: &RewriteContext<'_>,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     let mut result = String::with_capacity(128);
     result.push_str(rewrite_ident(context, segment.ident));
 
     let ident_len = result.len();
     let shape = if context.use_block_indent() {
-        shape.offset_left(ident_len)?
+        shape.offset_left(ident_len)
     } else {
-        shape.shrink_left(ident_len)?
-    };
+        shape.shrink_left(ident_len)
+    }
+    .max_width_error(shape.width, mk_sp(*span_lo, span_hi))?;
 
     if let Some(ref args) = segment.args {
         let generics_str = rewrite_generic_args(args, context, shape, mk_sp(*span_lo, span_hi))?;
@@ -288,7 +313,7 @@ fn rewrite_segment(
         result.push_str(&generics_str)
     }
 
-    Some(result)
+    Ok(result)
 }
 
 fn format_function_type<'a, I>(
@@ -298,7 +323,7 @@ fn format_function_type<'a, I>(
     span: Span,
     context: &RewriteContext<'_>,
     shape: Shape,
-) -> Option<String>
+) -> RewriteResult
 where
     I: ExactSizeIterator,
     <I as Iterator>::Item: Deref,
@@ -308,12 +333,12 @@ where
 
     let ty_shape = match context.config.indent_style() {
         // 4 = " -> "
-        IndentStyle::Block => shape.offset_left(4)?,
-        IndentStyle::Visual => shape.block_left(4)?,
+        IndentStyle::Block => shape.offset_left(4).max_width_error(shape.width, span)?,
+        IndentStyle::Visual => shape.block_left(4).max_width_error(shape.width, span)?,
     };
     let output = match *output {
         FnRetTy::Ty(ref ty) => {
-            let type_str = ty.rewrite(context, ty_shape)?;
+            let type_str = ty.rewrite_result(context, ty_shape)?;
             format!(" -> {type_str}")
         }
         FnRetTy::Default(..) => String::new(),
@@ -326,7 +351,10 @@ where
         )
     } else {
         // 2 for ()
-        let budget = shape.width.checked_sub(2)?;
+        let budget = shape
+            .width
+            .checked_sub(2)
+            .max_width_error(shape.width, span)?;
         // 1 for (
         let offset = shape.indent + 1;
         Shape::legacy(budget, offset)
@@ -339,7 +367,8 @@ where
         let list_hi = context.snippet_provider.span_before(span, ")");
         let comment = context
             .snippet_provider
-            .span_to_snippet(mk_sp(list_lo, list_hi))?
+            .span_to_snippet(mk_sp(list_lo, list_hi))
+            .unknown_error()?
             .trim();
         let comment = if comment.starts_with("//") {
             format!(
@@ -360,7 +389,7 @@ where
             ",",
             |arg| arg.span().lo(),
             |arg| arg.span().hi(),
-            |arg| arg.rewrite(context, list_shape),
+            |arg| arg.rewrite_result(context, list_shape),
             list_lo,
             span.hi(),
             false,
@@ -396,9 +425,9 @@ where
         )
     };
     if output.is_empty() || last_line_width(&args) + first_line_width(&output) <= shape.width {
-        Some(format!("{args}{output}"))
+        Ok(format!("{args}{output}"))
     } else {
-        Some(format!(
+        Ok(format!(
             "{}\n{}{}",
             args,
             list_shape.indent.to_string(context.config),
@@ -429,6 +458,10 @@ fn get_tactics(item_vec: &[ListItem], output: &str, shape: Shape) -> DefinitiveL
 
 impl Rewrite for ast::WherePredicate {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         // FIXME: dead spans?
         let result = match *self {
             ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
@@ -437,7 +470,7 @@ impl Rewrite for ast::WherePredicate {
                 ref bounds,
                 ..
             }) => {
-                let type_str = bounded_ty.rewrite(context, shape)?;
+                let type_str = bounded_ty.rewrite_result(context, shape)?;
                 let colon = type_bound_colon(context).trim_end();
                 let lhs = if let Some(binder_str) =
                     rewrite_bound_params(context, shape, bound_generic_params)
@@ -452,28 +485,34 @@ impl Rewrite for ast::WherePredicate {
             ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
                 ref lifetime,
                 ref bounds,
-                ..
-            }) => rewrite_bounded_lifetime(lifetime, bounds, context, shape)?,
+                span,
+            }) => rewrite_bounded_lifetime(lifetime, bounds, span, context, shape)?,
             ast::WherePredicate::EqPredicate(ast::WhereEqPredicate {
                 ref lhs_ty,
                 ref rhs_ty,
                 ..
             }) => {
-                let lhs_ty_str = lhs_ty.rewrite(context, shape).map(|lhs| lhs + " =")?;
+                let lhs_ty_str = lhs_ty
+                    .rewrite_result(context, shape)
+                    .map(|lhs| lhs + " =")?;
                 rewrite_assign_rhs(context, lhs_ty_str, &**rhs_ty, &RhsAssignKind::Ty, shape)?
             }
         };
 
-        Some(result)
+        Ok(result)
     }
 }
 
 impl Rewrite for ast::GenericArg {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         match *self {
-            ast::GenericArg::Lifetime(ref lt) => lt.rewrite(context, shape),
-            ast::GenericArg::Type(ref ty) => ty.rewrite(context, shape),
-            ast::GenericArg::Const(ref const_) => const_.rewrite(context, shape),
+            ast::GenericArg::Lifetime(ref lt) => lt.rewrite_result(context, shape),
+            ast::GenericArg::Type(ref ty) => ty.rewrite_result(context, shape),
+            ast::GenericArg::Const(ref const_) => const_.rewrite_result(context, shape),
         }
     }
 }
@@ -483,11 +522,11 @@ fn rewrite_generic_args(
     context: &RewriteContext<'_>,
     shape: Shape,
     span: Span,
-) -> Option<String> {
+) -> RewriteResult {
     match gen_args {
         ast::GenericArgs::AngleBracketed(ref data) => {
             if data.args.is_empty() {
-                Some("".to_owned())
+                Ok("".to_owned())
             } else {
                 let args = data
                     .args
@@ -513,47 +552,63 @@ fn rewrite_generic_args(
             context,
             shape,
         ),
-        ast::GenericArgs::ParenthesizedElided(..) => Some("(..)".to_owned()),
+        ast::GenericArgs::ParenthesizedElided(..) => Ok("(..)".to_owned()),
     }
 }
 
 fn rewrite_bounded_lifetime(
     lt: &ast::Lifetime,
     bounds: &[ast::GenericBound],
+    span: Span,
     context: &RewriteContext<'_>,
     shape: Shape,
-) -> Option<String> {
-    let result = lt.rewrite(context, shape)?;
+) -> RewriteResult {
+    let result = lt.rewrite_result(context, shape)?;
 
     if bounds.is_empty() {
-        Some(result)
+        Ok(result)
     } else {
         let colon = type_bound_colon(context);
         let overhead = last_line_width(&result) + colon.len();
+        let shape = shape
+            .sub_width(overhead)
+            .max_width_error(shape.width, span)?;
         let result = format!(
             "{}{}{}",
             result,
             colon,
-            join_bounds(context, shape.sub_width(overhead)?, bounds, true)?
+            join_bounds(context, shape, bounds, true)?
         );
-        Some(result)
+        Ok(result)
     }
 }
 
 impl Rewrite for ast::AnonConst {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         format_expr(&self.value, ExprType::SubExpression, context, shape)
     }
 }
 
 impl Rewrite for ast::Lifetime {
-    fn rewrite(&self, context: &RewriteContext<'_>, _: Shape) -> Option<String> {
-        Some(context.snippet(self.ident.span).to_owned())
+    fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, _: Shape) -> RewriteResult {
+        Ok(context.snippet(self.ident.span).to_owned())
     }
 }
 
 impl Rewrite for ast::GenericBound {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         match *self {
             ast::GenericBound::Trait(
                 ref poly_trait_ref,
@@ -574,24 +629,30 @@ impl Rewrite for ast::GenericBound {
                     asyncness.push(' ');
                 }
                 let polarity = polarity.as_str();
-                let shape = shape.offset_left(constness.len() + polarity.len())?;
+                let shape = shape
+                    .offset_left(constness.len() + polarity.len())
+                    .max_width_error(shape.width, self.span())?;
                 poly_trait_ref
-                    .rewrite(context, shape)
+                    .rewrite_result(context, shape)
                     .map(|s| format!("{constness}{asyncness}{polarity}{s}"))
                     .map(|s| if has_paren { format!("({})", s) } else { s })
             }
             ast::GenericBound::Use(ref args, span) => {
                 overflow::rewrite_with_angle_brackets(context, "use", args.iter(), shape, span)
             }
-            ast::GenericBound::Outlives(ref lifetime) => lifetime.rewrite(context, shape),
+            ast::GenericBound::Outlives(ref lifetime) => lifetime.rewrite_result(context, shape),
         }
     }
 }
 
 impl Rewrite for ast::GenericBounds {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         if self.is_empty() {
-            return Some(String::new());
+            return Ok(String::new());
         }
 
         join_bounds(context, shape, self, true)
@@ -600,8 +661,15 @@ impl Rewrite for ast::GenericBounds {
 
 impl Rewrite for ast::GenericParam {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         // FIXME: If there are more than one attributes, this will force multiline.
-        let mut result = self.attrs.rewrite(context, shape).unwrap_or(String::new());
+        let mut result = self
+            .attrs
+            .rewrite_result(context, shape)
+            .unwrap_or(String::new());
         let has_attrs = !result.is_empty();
 
         let mut param = String::with_capacity(128);
@@ -615,15 +683,19 @@ impl Rewrite for ast::GenericParam {
             param.push_str("const ");
             param.push_str(rewrite_ident(context, self.ident));
             param.push_str(": ");
-            param.push_str(&ty.rewrite(context, shape)?);
+            param.push_str(&ty.rewrite_result(context, shape)?);
             if let Some(default) = default {
                 let eq_str = match context.config.type_punctuation_density() {
                     TypeDensity::Compressed => "=",
                     TypeDensity::Wide => " = ",
                 };
                 param.push_str(eq_str);
-                let budget = shape.width.checked_sub(param.len())?;
-                let rewrite = default.rewrite(context, Shape::legacy(budget, shape.indent))?;
+                let budget = shape
+                    .width
+                    .checked_sub(param.len())
+                    .max_width_error(shape.width, self.span())?;
+                let rewrite =
+                    default.rewrite_result(context, Shape::legacy(budget, shape.indent))?;
                 param.push_str(&rewrite);
             }
             kw_span.lo()
@@ -634,7 +706,7 @@ impl Rewrite for ast::GenericParam {
 
         if !self.bounds.is_empty() {
             param.push_str(type_bound_colon(context));
-            param.push_str(&self.bounds.rewrite(context, shape)?)
+            param.push_str(&self.bounds.rewrite_result(context, shape)?)
         }
         if let ast::GenericParamKind::Type {
             default: Some(ref def),
@@ -645,9 +717,12 @@ impl Rewrite for ast::GenericParam {
                 TypeDensity::Wide => " = ",
             };
             param.push_str(eq_str);
-            let budget = shape.width.checked_sub(param.len())?;
+            let budget = shape
+                .width
+                .checked_sub(param.len())
+                .max_width_error(shape.width, self.span())?;
             let rewrite =
-                def.rewrite(context, Shape::legacy(budget, shape.indent + param.len()))?;
+                def.rewrite_result(context, Shape::legacy(budget, shape.indent + param.len()))?;
             param.push_str(&rewrite);
         }
 
@@ -673,44 +748,67 @@ impl Rewrite for ast::GenericParam {
             result.push_str(&param);
         }
 
-        Some(result)
+        Ok(result)
     }
 }
 
 impl Rewrite for ast::PolyTraitRef {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         if let Some(lifetime_str) = rewrite_bound_params(context, shape, &self.bound_generic_params)
         {
             // 6 is "for<> ".len()
             let extra_offset = lifetime_str.len() + 6;
-            let path_str = self
-                .trait_ref
-                .rewrite(context, shape.offset_left(extra_offset)?)?;
+            let shape = shape
+                .offset_left(extra_offset)
+                .max_width_error(shape.width, self.span)?;
+            let path_str = self.trait_ref.rewrite_result(context, shape)?;
 
-            Some(format!("for<{lifetime_str}> {path_str}"))
+            Ok(format!("for<{lifetime_str}> {path_str}"))
         } else {
-            self.trait_ref.rewrite(context, shape)
+            self.trait_ref.rewrite_result(context, shape)
         }
     }
 }
 
 impl Rewrite for ast::TraitRef {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         rewrite_path(context, PathContext::Type, &None, &self.path, shape)
     }
 }
 
 impl Rewrite for ast::Ty {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
         match self.kind {
             ast::TyKind::TraitObject(ref bounds, tobj_syntax) => {
                 // we have to consider 'dyn' keyword is used or not!!!
                 let (shape, prefix) = match tobj_syntax {
-                    ast::TraitObjectSyntax::Dyn => (shape.offset_left(4)?, "dyn "),
-                    ast::TraitObjectSyntax::DynStar => (shape.offset_left(5)?, "dyn* "),
+                    ast::TraitObjectSyntax::Dyn => {
+                        let shape = shape
+                            .offset_left(4)
+                            .max_width_error(shape.width, self.span())?;
+                        (shape, "dyn ")
+                    }
+                    ast::TraitObjectSyntax::DynStar => {
+                        let shape = shape
+                            .offset_left(5)
+                            .max_width_error(shape.width, self.span())?;
+                        (shape, "dyn* ")
+                    }
                     ast::TraitObjectSyntax::None => (shape, ""),
                 };
-                let mut res = bounds.rewrite(context, shape)?;
+                let mut res = bounds.rewrite_result(context, shape)?;
                 // We may have falsely removed a trailing `+` inside macro call.
                 if context.inside_macro()
                     && bounds.len() == 1
@@ -719,7 +817,7 @@ impl Rewrite for ast::Ty {
                 {
                     res.push('+');
                 }
-                Some(format!("{prefix}{res}"))
+                Ok(format!("{prefix}{res}"))
             }
             ast::TyKind::Ptr(ref mt) => {
                 let prefix = match mt.mutbl {
@@ -738,8 +836,11 @@ impl Rewrite for ast::Ty {
                 let mut cmnt_lo = ref_hi;
 
                 if let Some(ref lifetime) = *lifetime {
-                    let lt_budget = shape.width.checked_sub(2 + mut_len)?;
-                    let lt_str = lifetime.rewrite(
+                    let lt_budget = shape
+                        .width
+                        .checked_sub(2 + mut_len)
+                        .max_width_error(shape.width, self.span())?;
+                    let lt_str = lifetime.rewrite_result(
                         context,
                         Shape::legacy(lt_budget, shape.indent + 2 + mut_len),
                     )?;
@@ -783,39 +884,46 @@ impl Rewrite for ast::Ty {
                     result = combine_strs_with_missing_comments(
                         context,
                         result.trim_end(),
-                        &mt.ty.rewrite(context, shape)?,
+                        &mt.ty.rewrite_result(context, shape)?,
                         before_ty_span,
                         shape,
                         true,
                     )?;
                 } else {
                     let used_width = last_line_width(&result);
-                    let budget = shape.width.checked_sub(used_width)?;
-                    let ty_str = mt
-                        .ty
-                        .rewrite(context, Shape::legacy(budget, shape.indent + used_width))?;
+                    let budget = shape
+                        .width
+                        .checked_sub(used_width)
+                        .max_width_error(shape.width, self.span())?;
+                    let ty_str = mt.ty.rewrite_result(
+                        context,
+                        Shape::legacy(budget, shape.indent + used_width),
+                    )?;
                     result.push_str(&ty_str);
                 }
 
-                Some(result)
+                Ok(result)
             }
             // FIXME: we drop any comments here, even though it's a silly place to put
             // comments.
             ast::TyKind::Paren(ref ty) => {
-                if context.config.version() == Version::One
+                if context.config.style_edition() <= StyleEdition::Edition2021
                     || context.config.indent_style() == IndentStyle::Visual
                 {
-                    let budget = shape.width.checked_sub(2)?;
+                    let budget = shape
+                        .width
+                        .checked_sub(2)
+                        .max_width_error(shape.width, self.span())?;
                     return ty
-                        .rewrite(context, Shape::legacy(budget, shape.indent + 1))
+                        .rewrite_result(context, Shape::legacy(budget, shape.indent + 1))
                         .map(|ty_str| format!("({})", ty_str));
                 }
 
                 // 2 = ()
                 if let Some(sh) = shape.sub_width(2) {
-                    if let Some(ref s) = ty.rewrite(context, sh) {
+                    if let Ok(ref s) = ty.rewrite_result(context, sh) {
                         if !s.contains('\n') {
-                            return Some(format!("({s})"));
+                            return Ok(format!("({s})"));
                         }
                     }
                 }
@@ -824,8 +932,8 @@ impl Rewrite for ast::Ty {
                 let shape = shape
                     .block_indent(context.config.tab_spaces())
                     .with_max_width(context.config);
-                let rw = ty.rewrite(context, shape)?;
-                Some(format!(
+                let rw = ty.rewrite_result(context, shape)?;
+                Ok(format!(
                     "({}{}{})",
                     shape.to_string_with_newline(context.config),
                     rw,
@@ -833,15 +941,18 @@ impl Rewrite for ast::Ty {
                 ))
             }
             ast::TyKind::Slice(ref ty) => {
-                let budget = shape.width.checked_sub(4)?;
-                ty.rewrite(context, Shape::legacy(budget, shape.indent + 1))
+                let budget = shape
+                    .width
+                    .checked_sub(4)
+                    .max_width_error(shape.width, self.span())?;
+                ty.rewrite_result(context, Shape::legacy(budget, shape.indent + 1))
                     .map(|ty_str| format!("[{}]", ty_str))
             }
             ast::TyKind::Tup(ref items) => {
                 rewrite_tuple(context, items.iter(), self.span, shape, items.len() == 1)
             }
-            ast::TyKind::AnonStruct(..) => Some(context.snippet(self.span).to_owned()),
-            ast::TyKind::AnonUnion(..) => Some(context.snippet(self.span).to_owned()),
+            ast::TyKind::AnonStruct(..) => Ok(context.snippet(self.span).to_owned()),
+            ast::TyKind::AnonUnion(..) => Ok(context.snippet(self.span).to_owned()),
             ast::TyKind::Path(ref q_self, ref path) => {
                 rewrite_path(context, PathContext::Type, q_self, path, shape)
             }
@@ -855,24 +966,27 @@ impl Rewrite for ast::Ty {
             ),
             ast::TyKind::Infer => {
                 if shape.width >= 1 {
-                    Some("_".to_owned())
+                    Ok("_".to_owned())
                 } else {
-                    None
+                    Err(RewriteError::ExceedsMaxWidth {
+                        configured_width: shape.width,
+                        span: self.span(),
+                    })
                 }
             }
             ast::TyKind::BareFn(ref bare_fn) => rewrite_bare_fn(bare_fn, self.span, context, shape),
-            ast::TyKind::Never => Some(String::from("!")),
+            ast::TyKind::Never => Ok(String::from("!")),
             ast::TyKind::MacCall(ref mac) => {
                 rewrite_macro(mac, None, context, shape, MacroPosition::Expression)
             }
-            ast::TyKind::ImplicitSelf => Some(String::from("")),
+            ast::TyKind::ImplicitSelf => Ok(String::from("")),
             ast::TyKind::ImplTrait(_, ref it) => {
                 // Empty trait is not a parser error.
                 if it.is_empty() {
-                    return Some("impl".to_owned());
+                    return Ok("impl".to_owned());
                 }
-                let rw = if context.config.version() == Version::One {
-                    it.rewrite(context, shape)
+                let rw = if context.config.style_edition() <= StyleEdition::Edition2021 {
+                    it.rewrite_result(context, shape)
                 } else {
                     join_bounds(context, shape, it, false)
                 };
@@ -881,8 +995,8 @@ impl Rewrite for ast::Ty {
                     format!("impl{}{}", space, it_str)
                 })
             }
-            ast::TyKind::CVarArgs => Some("...".to_owned()),
-            ast::TyKind::Dummy | ast::TyKind::Err(_) => Some(context.snippet(self.span).to_owned()),
+            ast::TyKind::CVarArgs => Ok("...".to_owned()),
+            ast::TyKind::Dummy | ast::TyKind::Err(_) => Ok(context.snippet(self.span).to_owned()),
             ast::TyKind::Typeof(ref anon_const) => rewrite_call(
                 context,
                 "typeof",
@@ -891,9 +1005,9 @@ impl Rewrite for ast::Ty {
                 shape,
             ),
             ast::TyKind::Pat(ref ty, ref pat) => {
-                let ty = ty.rewrite(context, shape)?;
-                let pat = pat.rewrite(context, shape)?;
-                Some(format!("{ty} is {pat}"))
+                let ty = ty.rewrite_result(context, shape)?;
+                let pat = pat.rewrite_result(context, shape)?;
+                Ok(format!("{ty} is {pat}"))
             }
         }
     }
@@ -904,7 +1018,7 @@ fn rewrite_bare_fn(
     span: Span,
     context: &RewriteContext<'_>,
     shape: Shape,
-) -> Option<String> {
+) -> RewriteResult {
     debug!("rewrite_bare_fn {:#?}", shape);
 
     let mut result = String::with_capacity(128);
@@ -928,9 +1042,14 @@ fn rewrite_bare_fn(
     result.push_str("fn");
 
     let func_ty_shape = if context.use_block_indent() {
-        shape.offset_left(result.len())?
+        shape
+            .offset_left(result.len())
+            .max_width_error(shape.width, span)?
     } else {
-        shape.visual_indent(result.len()).sub_width(result.len())?
+        shape
+            .visual_indent(result.len())
+            .sub_width(result.len())
+            .max_width_error(shape.width, span)?
     };
 
     let rewrite = format_function_type(
@@ -944,7 +1063,7 @@ fn rewrite_bare_fn(
 
     result.push_str(&rewrite);
 
-    Some(result)
+    Ok(result)
 }
 
 fn is_generic_bounds_in_order(generic_bounds: &[ast::GenericBound]) -> bool {
@@ -968,7 +1087,7 @@ fn join_bounds(
     shape: Shape,
     items: &[ast::GenericBound],
     need_indent: bool,
-) -> Option<String> {
+) -> RewriteResult {
     join_bounds_inner(context, shape, items, need_indent, false)
 }
 
@@ -978,7 +1097,7 @@ fn join_bounds_inner(
     items: &[ast::GenericBound],
     need_indent: bool,
     force_newline: bool,
-) -> Option<String> {
+) -> RewriteResult {
     debug_assert!(!items.is_empty());
 
     let generic_bounds_in_order = is_generic_bounds_in_order(items);
@@ -1073,10 +1192,10 @@ fn join_bounds_inner(
             };
 
             let (extendable, trailing_str) = if i == 0 {
-                let bound_str = item.rewrite(context, shape)?;
+                let bound_str = item.rewrite_result(context, shape)?;
                 (is_bound_extendable(&bound_str, item), bound_str)
             } else {
-                let bound_str = &item.rewrite(context, shape)?;
+                let bound_str = &item.rewrite_result(context, shape)?;
                 match leading_span {
                     Some(ls) if has_leading_comment => (
                         is_bound_extendable(bound_str, item),
@@ -1100,7 +1219,7 @@ fn join_bounds_inner(
                     true,
                 )
                 .map(|v| (v, trailing_span, extendable)),
-                _ => Some((strs + &trailing_str, trailing_span, extendable)),
+                _ => Ok((strs + &trailing_str, trailing_span, extendable)),
             }
         },
     )?;
@@ -1110,22 +1229,22 @@ fn join_bounds_inner(
     //   and either there is more than one item;
     //       or the single item is of type `Trait`,
     //          and any of the internal arrays contains more than one item;
-    let retry_with_force_newline = match context.config.version() {
-        Version::One => {
+    let retry_with_force_newline = match context.config.style_edition() {
+        style_edition @ _ if style_edition <= StyleEdition::Edition2021 => {
             !force_newline
                 && items.len() > 1
                 && (result.0.contains('\n') || result.0.len() > shape.width)
         }
-        Version::Two if force_newline => false,
-        Version::Two if (!result.0.contains('\n') && result.0.len() <= shape.width) => false,
-        Version::Two if items.len() > 1 => true,
-        Version::Two => is_item_with_multi_items_array(&items[0]),
+        _ if force_newline => false,
+        _ if (!result.0.contains('\n') && result.0.len() <= shape.width) => false,
+        _ if items.len() > 1 => true,
+        _ => is_item_with_multi_items_array(&items[0]),
     };
 
     if retry_with_force_newline {
         join_bounds_inner(context, shape, items, need_indent, true)
     } else {
-        Some(result.0)
+        Ok(result.0)
     }
 }
 
diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs
index fd59aedadfe..d1cfc6acc49 100644
--- a/src/tools/rustfmt/src/utils.rs
+++ b/src/tools/rustfmt/src/utils.rs
@@ -6,11 +6,11 @@ use rustc_ast::ast::{
 };
 use rustc_ast::ptr;
 use rustc_ast_pretty::pprust;
-use rustc_span::{sym, symbol, BytePos, LocalExpnId, Span, Symbol, SyntaxContext};
+use rustc_span::{BytePos, LocalExpnId, Span, Symbol, SyntaxContext, sym, symbol};
 use unicode_width::UnicodeWidthStr;
 
-use crate::comment::{filter_normal_code, CharClasses, FullCodeCharKind, LineClasses};
-use crate::config::{Config, Version};
+use crate::comment::{CharClasses, FullCodeCharKind, LineClasses, filter_normal_code};
+use crate::config::{Config, StyleEdition};
 use crate::rewrite::RewriteContext;
 use crate::shape::{Indent, Shape};
 
@@ -367,10 +367,10 @@ macro_rules! out_of_file_lines_range {
     };
 }
 
-macro_rules! skip_out_of_file_lines_range {
+macro_rules! skip_out_of_file_lines_range_err {
     ($self:ident, $span:expr) => {
         if out_of_file_lines_range!($self, $span) {
-            return None;
+            return Err(RewriteError::SkipFormatting);
         }
     };
 }
@@ -596,7 +596,7 @@ pub(crate) fn trim_left_preserve_layout(
 
             // just InString{Commented} in order to allow the start of a string to be indented
             let new_veto_trim_value = (kind == FullCodeCharKind::InString
-                || (config.version() == Version::Two
+                || (config.style_edition() >= StyleEdition::Edition2024
                     && kind == FullCodeCharKind::InStringCommented))
                 && !line.ends_with('\\');
             let line = if veto_trim || new_veto_trim_value {
@@ -612,7 +612,7 @@ pub(crate) fn trim_left_preserve_layout(
             // such lines should not be taken into account when computing the minimum.
             match kind {
                 FullCodeCharKind::InStringCommented | FullCodeCharKind::EndStringCommented
-                    if config.version() == Version::Two =>
+                    if config.style_edition() >= StyleEdition::Edition2024 =>
                 {
                     None
                 }
@@ -656,7 +656,7 @@ pub(crate) fn indent_next_line(kind: FullCodeCharKind, line: &str, config: &Conf
         // formatting the code block, therefore the string's indentation needs
         // to be adjusted for the code surrounding the code block.
         config.format_strings() && line.ends_with('\\')
-    } else if config.version() == Version::Two {
+    } else if config.style_edition() >= StyleEdition::Edition2024 {
         !kind.is_commented_string()
     } else {
         true
diff --git a/src/tools/rustfmt/src/vertical.rs b/src/tools/rustfmt/src/vertical.rs
index a06bc995aa5..1ec239c3821 100644
--- a/src/tools/rustfmt/src/vertical.rs
+++ b/src/tools/rustfmt/src/vertical.rs
@@ -11,9 +11,9 @@ use crate::config::lists::*;
 use crate::expr::rewrite_field;
 use crate::items::{rewrite_struct_field, rewrite_struct_field_prefix};
 use crate::lists::{
-    definitive_tactic, itemize_list, write_list, ListFormatting, ListItem, Separator,
+    ListFormatting, ListItem, Separator, definitive_tactic, itemize_list, write_list,
 };
-use crate::rewrite::{Rewrite, RewriteContext};
+use crate::rewrite::{Rewrite, RewriteContext, RewriteResult};
 use crate::shape::{Indent, Shape};
 use crate::source_map::SpanUtils;
 use crate::spanned::Spanned;
@@ -24,13 +24,13 @@ use crate::utils::{
 pub(crate) trait AlignedItem {
     fn skip(&self) -> bool;
     fn get_span(&self) -> Span;
-    fn rewrite_prefix(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String>;
+    fn rewrite_prefix(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult;
     fn rewrite_aligned_item(
         &self,
         context: &RewriteContext<'_>,
         shape: Shape,
         prefix_max_width: usize,
-    ) -> Option<String>;
+    ) -> RewriteResult;
 }
 
 impl AlignedItem for ast::FieldDef {
@@ -42,24 +42,23 @@ impl AlignedItem for ast::FieldDef {
         self.span()
     }
 
-    fn rewrite_prefix(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
-        let attrs_str = self.attrs.rewrite(context, shape)?;
+    fn rewrite_prefix(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
+        let attrs_str = self.attrs.rewrite_result(context, shape)?;
         let missing_span = if self.attrs.is_empty() {
             mk_sp(self.span.lo(), self.span.lo())
         } else {
             mk_sp(self.attrs.last().unwrap().span.hi(), self.span.lo())
         };
         let attrs_extendable = self.ident.is_none() && is_attributes_extendable(&attrs_str);
-        rewrite_struct_field_prefix(context, self).and_then(|field_str| {
-            combine_strs_with_missing_comments(
-                context,
-                &attrs_str,
-                &field_str,
-                missing_span,
-                shape,
-                attrs_extendable,
-            )
-        })
+        let field_str = rewrite_struct_field_prefix(context, self)?;
+        combine_strs_with_missing_comments(
+            context,
+            &attrs_str,
+            &field_str,
+            missing_span,
+            shape,
+            attrs_extendable,
+        )
     }
 
     fn rewrite_aligned_item(
@@ -67,7 +66,7 @@ impl AlignedItem for ast::FieldDef {
         context: &RewriteContext<'_>,
         shape: Shape,
         prefix_max_width: usize,
-    ) -> Option<String> {
+    ) -> RewriteResult {
         rewrite_struct_field(context, self, shape, prefix_max_width)
     }
 }
@@ -81,8 +80,8 @@ impl AlignedItem for ast::ExprField {
         self.span()
     }
 
-    fn rewrite_prefix(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
-        let attrs_str = self.attrs.rewrite(context, shape)?;
+    fn rewrite_prefix(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
+        let attrs_str = self.attrs.rewrite_result(context, shape)?;
         let name = rewrite_ident(context, self.ident);
         let missing_span = if self.attrs.is_empty() {
             mk_sp(self.span.lo(), self.span.lo())
@@ -104,7 +103,7 @@ impl AlignedItem for ast::ExprField {
         context: &RewriteContext<'_>,
         shape: Shape,
         prefix_max_width: usize,
-    ) -> Option<String> {
+    ) -> RewriteResult {
         rewrite_field(context, self, shape, prefix_max_width)
     }
 }
@@ -199,7 +198,7 @@ fn struct_field_prefix_max_min_width<T: AlignedItem>(
                 .rewrite_prefix(context, shape)
                 .map(|field_str| trimmed_last_line_width(&field_str))
         })
-        .fold_options((0, ::std::usize::MAX), |(max_len, min_len), len| {
+        .fold_ok((0, ::std::usize::MAX), |(max_len, min_len), len| {
             (cmp::max(max_len, len), cmp::min(min_len, len))
         })
         .unwrap_or((0, 0))
@@ -246,12 +245,12 @@ fn rewrite_aligned_items_inner<T: AlignedItem>(
     if tactic == DefinitiveListTactic::Horizontal {
         // since the items fits on a line, there is no need to align them
         let do_rewrite =
-            |field: &T| -> Option<String> { field.rewrite_aligned_item(context, item_shape, 0) };
+            |field: &T| -> RewriteResult { field.rewrite_aligned_item(context, item_shape, 0) };
         fields
             .iter()
             .zip(items.iter_mut())
             .for_each(|(field, list_item): (&T, &mut ListItem)| {
-                if list_item.item.is_some() {
+                if list_item.item.is_ok() {
                     list_item.item = do_rewrite(field);
                 }
             });
@@ -267,7 +266,7 @@ fn rewrite_aligned_items_inner<T: AlignedItem>(
         .tactic(tactic)
         .trailing_separator(separator_tactic)
         .preserve_newline(true);
-    write_list(&items, &fmt)
+    write_list(&items, &fmt).ok()
 }
 
 /// Returns the index in `fields` up to which a field belongs to the current group.
diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs
index ac68fc5fecf..8102fe7ad8f 100644
--- a/src/tools/rustfmt/src/visitor.rs
+++ b/src/tools/rustfmt/src/visitor.rs
@@ -3,24 +3,23 @@ use std::rc::Rc;
 
 use rustc_ast::{ast, token::Delimiter, visit};
 use rustc_data_structures::sync::Lrc;
-use rustc_span::{symbol, BytePos, Pos, Span};
+use rustc_span::{BytePos, Pos, Span, symbol};
 use tracing::debug;
 
 use crate::attr::*;
-use crate::comment::{contains_comment, rewrite_comment, CodeCharKind, CommentCodeSlices};
-use crate::config::Version;
-use crate::config::{BraceStyle, Config, MacroSelector};
+use crate::comment::{CodeCharKind, CommentCodeSlices, contains_comment, rewrite_comment};
+use crate::config::{BraceStyle, Config, MacroSelector, StyleEdition};
 use crate::coverage::transform_missing_snippet;
 use crate::items::{
-    format_impl, format_trait, format_trait_alias, is_mod_decl, is_use_item, rewrite_extern_crate,
-    rewrite_type_alias, FnBraceStyle, FnSig, ItemVisitorKind, StaticParts, StructParts,
+    FnBraceStyle, FnSig, ItemVisitorKind, StaticParts, StructParts, format_impl, format_trait,
+    format_trait_alias, is_mod_decl, is_use_item, rewrite_extern_crate, rewrite_type_alias,
 };
-use crate::macros::{macro_style, rewrite_macro, rewrite_macro_def, MacroPosition};
+use crate::macros::{MacroPosition, macro_style, rewrite_macro, rewrite_macro_def};
 use crate::modules::Module;
 use crate::parse::session::ParseSess;
 use crate::rewrite::{Rewrite, RewriteContext};
 use crate::shape::{Indent, Shape};
-use crate::skip::{is_skip_attr, SkipContext};
+use crate::skip::{SkipContext, is_skip_attr};
 use crate::source_map::{LineRangeUtils, SpanUtils};
 use crate::spanned::Spanned;
 use crate::stmt::Stmt;
@@ -291,7 +290,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
 
                     let mut comment_shape =
                         Shape::indented(self.block_indent, config).comment(config);
-                    if self.config.version() == Version::Two && comment_on_same_line {
+                    if self.config.style_edition() >= StyleEdition::Edition2024
+                        && comment_on_same_line
+                    {
                         self.push_str(" ");
                         // put the first line of the comment on the same line as the
                         // block's last line
@@ -312,8 +313,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                                 let comment_str =
                                     rewrite_comment(other_lines, false, comment_shape, config);
                                 match comment_str {
-                                    Some(ref s) => self.push_str(s),
-                                    None => self.push_str(other_lines),
+                                    Ok(ref s) => self.push_str(s),
+                                    Err(_) => self.push_str(other_lines),
                                 }
                             }
                         }
@@ -342,8 +343,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
 
                         let comment_str = rewrite_comment(&sub_slice, false, comment_shape, config);
                         match comment_str {
-                            Some(ref s) => self.push_str(s),
-                            None => self.push_str(&sub_slice),
+                            Ok(ref s) => self.push_str(s),
+                            Err(_) => self.push_str(&sub_slice),
                         }
                     }
                 }
@@ -561,9 +562,11 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                         )
                     } else {
                         let indent = self.block_indent;
-                        let rewrite = self.rewrite_required_fn(
-                            indent, item.ident, sig, &item.vis, generics, item.span,
-                        );
+                        let rewrite = self
+                            .rewrite_required_fn(
+                                indent, item.ident, sig, &item.vis, generics, item.span,
+                            )
+                            .ok();
                         self.push_rewrite(item.span, rewrite);
                     }
                 }
@@ -584,7 +587,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                         item.ident,
                         &item.vis,
                         item.span,
-                    );
+                    )
+                    .ok();
                     self.push_rewrite(item.span, rewrite);
                 }
                 ast::ItemKind::Delegation(..) | ast::ItemKind::DelegationMac(..) => {
@@ -609,7 +613,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
             self.block_indent,
             visitor_kind,
             span,
-        );
+        )
+        .ok();
         self.push_rewrite(span, rewrite);
     }
 
@@ -655,8 +660,9 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
                     );
                 } else {
                     let indent = self.block_indent;
-                    let rewrite =
-                        self.rewrite_required_fn(indent, ai.ident, sig, &ai.vis, generics, ai.span);
+                    let rewrite = self
+                        .rewrite_required_fn(indent, ai.ident, sig, &ai.vis, generics, ai.span)
+                        .ok();
                     self.push_rewrite(ai.span, rewrite);
                 }
             }
@@ -683,7 +689,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> {
 
         // 1 = ;
         let shape = self.shape().saturating_sub_width(1);
-        let rewrite = self.with_context(|ctx| rewrite_macro(mac, ident, ctx, shape, pos));
+        let rewrite = self.with_context(|ctx| rewrite_macro(mac, ident, ctx, shape, pos).ok());
         // As of v638 of the rustc-ap-* crates, the associated span no longer includes
         // the trailing semicolon. This determines the correct span to ensure scenarios
         // with whitespace between the delimiters and trailing semi (i.e. `foo!(abc)     ;`)
diff --git a/src/tools/rustfmt/tests/config/issue-5801-v2.toml b/src/tools/rustfmt/tests/config/issue-5801-v2.toml
index 948f4fb66bf..98e89d37916 100644
--- a/src/tools/rustfmt/tests/config/issue-5801-v2.toml
+++ b/src/tools/rustfmt/tests/config/issue-5801-v2.toml
@@ -1,3 +1,3 @@
 max_width = 120
 version = "Two"
-attr_fn_like_width = 120
\ No newline at end of file
+attr_fn_like_width = 120
diff --git a/src/tools/rustfmt/tests/config/issue-6302.toml b/src/tools/rustfmt/tests/config/issue-6302.toml
new file mode 100644
index 00000000000..8148b37b1f6
--- /dev/null
+++ b/src/tools/rustfmt/tests/config/issue-6302.toml
@@ -0,0 +1 @@
+edition = 2019
diff --git a/src/tools/rustfmt/tests/config/style-edition/just-style-edition/rustfmt.toml b/src/tools/rustfmt/tests/config/style-edition/just-style-edition/rustfmt.toml
new file mode 100644
index 00000000000..3501136812c
--- /dev/null
+++ b/src/tools/rustfmt/tests/config/style-edition/just-style-edition/rustfmt.toml
@@ -0,0 +1 @@
+style_edition = "2024"
diff --git a/src/tools/rustfmt/tests/config/style-edition/just-version/rustfmt.toml b/src/tools/rustfmt/tests/config/style-edition/just-version/rustfmt.toml
new file mode 100644
index 00000000000..1082fd88889
--- /dev/null
+++ b/src/tools/rustfmt/tests/config/style-edition/just-version/rustfmt.toml
@@ -0,0 +1 @@
+version = "Two"
diff --git a/src/tools/rustfmt/tests/config/style-edition/overrides/rustfmt.toml b/src/tools/rustfmt/tests/config/style-edition/overrides/rustfmt.toml
new file mode 100644
index 00000000000..24205692b1f
--- /dev/null
+++ b/src/tools/rustfmt/tests/config/style-edition/overrides/rustfmt.toml
@@ -0,0 +1,2 @@
+style_edition = "2024"
+overflow_delimited_expr = false
diff --git a/src/tools/rustfmt/tests/config/style-edition/style-edition-and-edition/rustfmt.toml b/src/tools/rustfmt/tests/config/style-edition/style-edition-and-edition/rustfmt.toml
new file mode 100644
index 00000000000..92844e03ab6
--- /dev/null
+++ b/src/tools/rustfmt/tests/config/style-edition/style-edition-and-edition/rustfmt.toml
@@ -0,0 +1,2 @@
+style_edition = "2021"
+edition = "2024"
diff --git a/src/tools/rustfmt/tests/config/style-edition/version-edition/rustfmt.toml b/src/tools/rustfmt/tests/config/style-edition/version-edition/rustfmt.toml
new file mode 100644
index 00000000000..16ea9a13f36
--- /dev/null
+++ b/src/tools/rustfmt/tests/config/style-edition/version-edition/rustfmt.toml
@@ -0,0 +1,2 @@
+version = "Two"
+edition = "2018"
diff --git a/src/tools/rustfmt/tests/config/style-edition/version-style-edition-and-edition/rustfmt.toml b/src/tools/rustfmt/tests/config/style-edition/version-style-edition-and-edition/rustfmt.toml
new file mode 100644
index 00000000000..187ba13cfb6
--- /dev/null
+++ b/src/tools/rustfmt/tests/config/style-edition/version-style-edition-and-edition/rustfmt.toml
@@ -0,0 +1,3 @@
+version = "Two"
+edition = "2018"
+style_edition = "2021"
diff --git a/src/tools/rustfmt/tests/config/style-edition/version-style-edition/rustfmt.toml b/src/tools/rustfmt/tests/config/style-edition/version-style-edition/rustfmt.toml
new file mode 100644
index 00000000000..c894bd981bc
--- /dev/null
+++ b/src/tools/rustfmt/tests/config/style-edition/version-style-edition/rustfmt.toml
@@ -0,0 +1,2 @@
+version = "Two"
+style_edition = "2021"
diff --git a/src/tools/rustfmt/tests/rustfmt/main.rs b/src/tools/rustfmt/tests/rustfmt/main.rs
index 58cf0e5e4db..a9f58b9328e 100644
--- a/src/tools/rustfmt/tests/rustfmt/main.rs
+++ b/src/tools/rustfmt/tests/rustfmt/main.rs
@@ -5,7 +5,7 @@ use std::fs::remove_file;
 use std::path::Path;
 use std::process::Command;
 
-use rustfmt_config_proc_macro::rustfmt_only_ci_test;
+use rustfmt_config_proc_macro::{nightly_only_test, rustfmt_only_ci_test};
 
 /// Run the rustfmt executable and return its output.
 fn rustfmt(args: &[&str]) -> (String, String) {
@@ -207,3 +207,28 @@ fn rustfmt_emits_error_when_control_brace_style_is_always_next_line() {
     let (_stdout, stderr) = rustfmt(&args);
     assert!(!stderr.contains("error[internal]: left behind trailing whitespace"))
 }
+
+#[nightly_only_test]
+#[test]
+fn rustfmt_generates_no_error_if_failed_format_code_in_doc_comments() {
+    // See also https://github.com/rust-lang/rustfmt/issues/6109
+
+    let file = "tests/target/issue-6109.rs";
+    let args = ["--config", "format_code_in_doc_comments=true", file];
+    let (stdout, stderr) = rustfmt(&args);
+    assert!(stderr.is_empty());
+    assert!(stdout.is_empty());
+}
+
+#[test]
+fn rustfmt_error_improvement_regarding_invalid_toml() {
+    // See also https://github.com/rust-lang/rustfmt/issues/6302
+    let invalid_toml_config = "tests/config/issue-6302.toml";
+    let args = ["--config-path", invalid_toml_config];
+    let (_stdout, stderr) = rustfmt(&args);
+
+    let toml_path = Path::new(invalid_toml_config).canonicalize().unwrap();
+    let expected_error_message = format!("The file `{}` failed to parse", toml_path.display());
+
+    assert!(stderr.contains(&expected_error_message));
+}
diff --git a/src/tools/rustfmt/tests/source/arrow_in_comments/arrow_in_single_comment.rs b/src/tools/rustfmt/tests/source/arrow_in_comments/arrow_in_single_comment.rs
index fb0576a4822..38e8967e7e6 100644
--- a/src/tools/rustfmt/tests/source/arrow_in_comments/arrow_in_single_comment.rs
+++ b/src/tools/rustfmt/tests/source/arrow_in_comments/arrow_in_single_comment.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 fn main() {
     match a {
         _ =>
diff --git a/src/tools/rustfmt/tests/source/arrow_in_comments/multiple_arrows.rs b/src/tools/rustfmt/tests/source/arrow_in_comments/multiple_arrows.rs
index fc696b309f2..98ef919450f 100644
--- a/src/tools/rustfmt/tests/source/arrow_in_comments/multiple_arrows.rs
+++ b/src/tools/rustfmt/tests/source/arrow_in_comments/multiple_arrows.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 fn main() {
     match a {
         _ => // comment with => 
diff --git a/src/tools/rustfmt/tests/source/configs/indent_style/block_trailing_comma_call/one.rs b/src/tools/rustfmt/tests/source/configs/indent_style/block_trailing_comma_call/one.rs
index 6d48ea742fc..66e2f538415 100644
--- a/src/tools/rustfmt/tests/source/configs/indent_style/block_trailing_comma_call/one.rs
+++ b/src/tools/rustfmt/tests/source/configs/indent_style/block_trailing_comma_call/one.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 // rustfmt-error_on_line_overflow: false
 // rustfmt-indent_style: Block
 
diff --git a/src/tools/rustfmt/tests/source/configs/indent_style/block_trailing_comma_call/two.rs b/src/tools/rustfmt/tests/source/configs/indent_style/block_trailing_comma_call/two.rs
index 7a62d722c6e..51aa6376e23 100644
--- a/src/tools/rustfmt/tests/source/configs/indent_style/block_trailing_comma_call/two.rs
+++ b/src/tools/rustfmt/tests/source/configs/indent_style/block_trailing_comma_call/two.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 // rustfmt-error_on_line_overflow: false
 // rustfmt-indent_style: Block
 
diff --git a/src/tools/rustfmt/tests/source/configs/style_edition/overflow_delim_expr_2015.rs b/src/tools/rustfmt/tests/source/configs/style_edition/overflow_delim_expr_2015.rs
new file mode 100644
index 00000000000..5cb4a870fc1
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/configs/style_edition/overflow_delim_expr_2015.rs
@@ -0,0 +1,155 @@
+// rustfmt-style_edition: 2015
+
+fn combine_blocklike() {
+    do_thing(
+        |param| {
+            action();
+            foo(param)
+        },
+    );
+
+    do_thing(
+        x,
+        |param| {
+            action();
+            foo(param)
+        },
+    );
+
+    do_thing(
+        x,
+
+        // I'll be discussing the `action` with your para(m)legal counsel
+        |param| {
+            action();
+            foo(param)
+        },
+    );
+
+    do_thing(
+        Bar {
+            x: value,
+            y: value2,
+        },
+    );
+
+    do_thing(
+        x,
+        Bar {
+            x: value,
+            y: value2,
+        },
+    );
+
+    do_thing(
+        x,
+
+        // Let me tell you about that one time at the `Bar`
+        Bar {
+            x: value,
+            y: value2,
+        },
+    );
+
+    do_thing(
+        &[
+            value_with_longer_name,
+            value2_with_longer_name,
+            value3_with_longer_name,
+            value4_with_longer_name,
+        ],
+    );
+
+    do_thing(
+        x,
+        &[
+            value_with_longer_name,
+            value2_with_longer_name,
+            value3_with_longer_name,
+            value4_with_longer_name,
+        ],
+    );
+
+    do_thing(
+        x,
+
+        // Just admit it; my list is longer than can be folded on to one line
+        &[
+            value_with_longer_name,
+            value2_with_longer_name,
+            value3_with_longer_name,
+            value4_with_longer_name,
+        ],
+    );
+
+    do_thing(
+        vec![
+            value_with_longer_name,
+            value2_with_longer_name,
+            value3_with_longer_name,
+            value4_with_longer_name,
+        ],
+    );
+
+    do_thing(
+        x,
+        vec![
+            value_with_longer_name,
+            value2_with_longer_name,
+            value3_with_longer_name,
+            value4_with_longer_name,
+        ],
+    );
+
+    do_thing(
+        x,
+
+        // Just admit it; my list is longer than can be folded on to one line
+        vec![
+            value_with_longer_name,
+            value2_with_longer_name,
+            value3_with_longer_name,
+            value4_with_longer_name,
+        ],
+    );
+
+    do_thing(
+        x,
+        (
+            1,
+            2,
+            3,
+            |param| {
+                action();
+                foo(param)
+            },
+        ),
+    );
+}
+
+fn combine_struct_sample() {
+    let identity = verify(
+        &ctx,
+        VerifyLogin {
+            type_: LoginType::Username,
+            username: args.username.clone(),
+            password: Some(args.password.clone()),
+            domain: None,
+        },
+    )?;
+}
+
+fn combine_macro_sample() {
+    rocket::ignite()
+        .mount(
+            "/",
+            routes![
+                http::auth::login,
+                http::auth::logout,
+                http::cors::options,
+                http::action::dance,
+                http::action::sleep,
+            ],
+        )
+        .launch();
+}
diff --git a/src/tools/rustfmt/tests/source/configs/style_edition/overflow_delim_expr_2024.rs b/src/tools/rustfmt/tests/source/configs/style_edition/overflow_delim_expr_2024.rs
new file mode 100644
index 00000000000..66c95e71aa9
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/configs/style_edition/overflow_delim_expr_2024.rs
@@ -0,0 +1,155 @@
+// rustfmt-style_edition: 2024
+
+fn combine_blocklike() {
+    do_thing(
+        |param| {
+            action();
+            foo(param)
+        },
+    );
+
+    do_thing(
+        x,
+        |param| {
+            action();
+            foo(param)
+        },
+    );
+
+    do_thing(
+        x,
+
+        // I'll be discussing the `action` with your para(m)legal counsel
+        |param| {
+            action();
+            foo(param)
+        },
+    );
+
+    do_thing(
+        Bar {
+            x: value,
+            y: value2,
+        },
+    );
+
+    do_thing(
+        x,
+        Bar {
+            x: value,
+            y: value2,
+        },
+    );
+
+    do_thing(
+        x,
+
+        // Let me tell you about that one time at the `Bar`
+        Bar {
+            x: value,
+            y: value2,
+        },
+    );
+
+    do_thing(
+        &[
+            value_with_longer_name,
+            value2_with_longer_name,
+            value3_with_longer_name,
+            value4_with_longer_name,
+        ],
+    );
+
+    do_thing(
+        x,
+        &[
+            value_with_longer_name,
+            value2_with_longer_name,
+            value3_with_longer_name,
+            value4_with_longer_name,
+        ],
+    );
+
+    do_thing(
+        x,
+
+        // Just admit it; my list is longer than can be folded on to one line
+        &[
+            value_with_longer_name,
+            value2_with_longer_name,
+            value3_with_longer_name,
+            value4_with_longer_name,
+        ],
+    );
+
+    do_thing(
+        vec![
+            value_with_longer_name,
+            value2_with_longer_name,
+            value3_with_longer_name,
+            value4_with_longer_name,
+        ],
+    );
+
+    do_thing(
+        x,
+        vec![
+            value_with_longer_name,
+            value2_with_longer_name,
+            value3_with_longer_name,
+            value4_with_longer_name,
+        ],
+    );
+
+    do_thing(
+        x,
+
+        // Just admit it; my list is longer than can be folded on to one line
+        vec![
+            value_with_longer_name,
+            value2_with_longer_name,
+            value3_with_longer_name,
+            value4_with_longer_name,
+        ],
+    );
+
+    do_thing(
+        x,
+        (
+            1,
+            2,
+            3,
+            |param| {
+                action();
+                foo(param)
+            },
+        ),
+    );
+}
+
+fn combine_struct_sample() {
+    let identity = verify(
+        &ctx,
+        VerifyLogin {
+            type_: LoginType::Username,
+            username: args.username.clone(),
+            password: Some(args.password.clone()),
+            domain: None,
+        },
+    )?;
+}
+
+fn combine_macro_sample() {
+    rocket::ignite()
+        .mount(
+            "/",
+            routes![
+                http::auth::login,
+                http::auth::logout,
+                http::cors::options,
+                http::action::dance,
+                http::action::sleep,
+            ],
+        )
+        .launch();
+}
diff --git a/src/tools/rustfmt/tests/source/fn-single-line/version_one.rs b/src/tools/rustfmt/tests/source/fn-single-line/version_one.rs
index 469ab621567..85957e3fdcc 100644
--- a/src/tools/rustfmt/tests/source/fn-single-line/version_one.rs
+++ b/src/tools/rustfmt/tests/source/fn-single-line/version_one.rs
@@ -1,5 +1,5 @@
 // rustfmt-fn_single_line: true
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 // Test single-line functions.
 
 fn foo_expr() {
diff --git a/src/tools/rustfmt/tests/source/fn-single-line/version_two.rs b/src/tools/rustfmt/tests/source/fn-single-line/version_two.rs
index bf381ff1065..f119e581217 100644
--- a/src/tools/rustfmt/tests/source/fn-single-line/version_two.rs
+++ b/src/tools/rustfmt/tests/source/fn-single-line/version_two.rs
@@ -1,5 +1,5 @@
 // rustfmt-fn_single_line: true
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 // Test single-line functions.
 
 fn foo_expr() {
diff --git a/src/tools/rustfmt/tests/source/issue-2179/one.rs b/src/tools/rustfmt/tests/source/issue-2179/one.rs
index d23947931ff..8bbd56f0521 100644
--- a/src/tools/rustfmt/tests/source/issue-2179/one.rs
+++ b/src/tools/rustfmt/tests/source/issue-2179/one.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 // rustfmt-error_on_line_overflow: false
 
 fn issue_2179() {
diff --git a/src/tools/rustfmt/tests/source/issue-2179/two.rs b/src/tools/rustfmt/tests/source/issue-2179/two.rs
index f4cc9cc488b..631b0f3c86e 100644
--- a/src/tools/rustfmt/tests/source/issue-2179/two.rs
+++ b/src/tools/rustfmt/tests/source/issue-2179/two.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 // rustfmt-error_on_line_overflow: false
 
 fn issue_2179() {
diff --git a/src/tools/rustfmt/tests/source/issue-3213/version_one.rs b/src/tools/rustfmt/tests/source/issue-3213/version_one.rs
index f9f4cab55e3..ed7d5145150 100644
--- a/src/tools/rustfmt/tests/source/issue-3213/version_one.rs
+++ b/src/tools/rustfmt/tests/source/issue-3213/version_one.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 
 fn foo() {
     match 0 {
diff --git a/src/tools/rustfmt/tests/source/issue-3213/version_two.rs b/src/tools/rustfmt/tests/source/issue-3213/version_two.rs
index 0f068c19d74..c6d04aced8d 100644
--- a/src/tools/rustfmt/tests/source/issue-3213/version_two.rs
+++ b/src/tools/rustfmt/tests/source/issue-3213/version_two.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 fn foo() {
     match 0 {
diff --git a/src/tools/rustfmt/tests/source/issue-3227/two.rs b/src/tools/rustfmt/tests/source/issue-3227/two.rs
index c1572c00d57..50c0ad47dc1 100644
--- a/src/tools/rustfmt/tests/source/issue-3227/two.rs
+++ b/src/tools/rustfmt/tests/source/issue-3227/two.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 fn main() {
     thread::spawn(|| {
diff --git a/src/tools/rustfmt/tests/source/issue-3270/one.rs b/src/tools/rustfmt/tests/source/issue-3270/one.rs
index 3c2e27e2293..64861176b91 100644
--- a/src/tools/rustfmt/tests/source/issue-3270/one.rs
+++ b/src/tools/rustfmt/tests/source/issue-3270/one.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 
 pub fn main() {
     /*   let s = String::from(
diff --git a/src/tools/rustfmt/tests/source/issue-3270/two.rs b/src/tools/rustfmt/tests/source/issue-3270/two.rs
index 0eb756471e7..1342cf03c39 100644
--- a/src/tools/rustfmt/tests/source/issue-3270/two.rs
+++ b/src/tools/rustfmt/tests/source/issue-3270/two.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 pub fn main() {
  /*   let s = String::from(
diff --git a/src/tools/rustfmt/tests/source/issue-3272/v1.rs b/src/tools/rustfmt/tests/source/issue-3272/v1.rs
index f4c1b7c992b..56dc048bf8a 100644
--- a/src/tools/rustfmt/tests/source/issue-3272/v1.rs
+++ b/src/tools/rustfmt/tests/source/issue-3272/v1.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 
 fn main() {
     assert!(HAYSTACK
diff --git a/src/tools/rustfmt/tests/source/issue-3272/v2.rs b/src/tools/rustfmt/tests/source/issue-3272/v2.rs
index 0148368edc8..f3adbe37c76 100644
--- a/src/tools/rustfmt/tests/source/issue-3272/v2.rs
+++ b/src/tools/rustfmt/tests/source/issue-3272/v2.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 fn main() {
     assert!(HAYSTACK
diff --git a/src/tools/rustfmt/tests/source/issue-3278/version_one.rs b/src/tools/rustfmt/tests/source/issue-3278/version_one.rs
index 580679fbae3..718a32b4c7e 100644
--- a/src/tools/rustfmt/tests/source/issue-3278/version_one.rs
+++ b/src/tools/rustfmt/tests/source/issue-3278/version_one.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 
 pub fn parse_conditional<'a, I: 'a>(
 ) -> impl Parser<Input = I, Output = Expr, PartialState = ()> + 'a
diff --git a/src/tools/rustfmt/tests/source/issue-3278/version_two.rs b/src/tools/rustfmt/tests/source/issue-3278/version_two.rs
index c17b1742d39..eb605e509f9 100644
--- a/src/tools/rustfmt/tests/source/issue-3278/version_two.rs
+++ b/src/tools/rustfmt/tests/source/issue-3278/version_two.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 pub fn parse_conditional<'a, I: 'a>()
 -> impl Parser<Input = I, Output = Expr, PartialState = ()> + 'a
diff --git a/src/tools/rustfmt/tests/source/issue-3295/two.rs b/src/tools/rustfmt/tests/source/issue-3295/two.rs
index 0eaf022249b..ae3d2ec28c0 100644
--- a/src/tools/rustfmt/tests/source/issue-3295/two.rs
+++ b/src/tools/rustfmt/tests/source/issue-3295/two.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 pub enum TestEnum {
     a,
     b,
diff --git a/src/tools/rustfmt/tests/source/issue-3302.rs b/src/tools/rustfmt/tests/source/issue-3302.rs
index c037584fd71..5e0862cb399 100644
--- a/src/tools/rustfmt/tests/source/issue-3302.rs
+++ b/src/tools/rustfmt/tests/source/issue-3302.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 macro_rules! moo1 {
     () => {
diff --git a/src/tools/rustfmt/tests/source/issue-3701/one.rs b/src/tools/rustfmt/tests/source/issue-3701/one.rs
index a7f0bd3aa17..4e8518b6f18 100644
--- a/src/tools/rustfmt/tests/source/issue-3701/one.rs
+++ b/src/tools/rustfmt/tests/source/issue-3701/one.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 
 fn build_sorted_static_get_entry_names(
     mut entries: Vec<(u8, &'static str)>,
diff --git a/src/tools/rustfmt/tests/source/issue-3701/two.rs b/src/tools/rustfmt/tests/source/issue-3701/two.rs
index 8e15c58b8b2..d7cb790a754 100644
--- a/src/tools/rustfmt/tests/source/issue-3701/two.rs
+++ b/src/tools/rustfmt/tests/source/issue-3701/two.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 fn build_sorted_static_get_entry_names(
     mut entries: Vec<(u8, &'static str)>,
diff --git a/src/tools/rustfmt/tests/source/issue-3805.rs b/src/tools/rustfmt/tests/source/issue-3805.rs
index a0289b57974..aadc4a9dddc 100644
--- a/src/tools/rustfmt/tests/source/issue-3805.rs
+++ b/src/tools/rustfmt/tests/source/issue-3805.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 // rustfmt-format_macro_matchers: true
 
 // From original issue example - Line length 101
diff --git a/src/tools/rustfmt/tests/source/issue-3840/version-two_hard-tabs.rs b/src/tools/rustfmt/tests/source/issue-3840/version-two_hard-tabs.rs
index 7b505fda87c..8d009eabdec 100644
--- a/src/tools/rustfmt/tests/source/issue-3840/version-two_hard-tabs.rs
+++ b/src/tools/rustfmt/tests/source/issue-3840/version-two_hard-tabs.rs
@@ -1,5 +1,5 @@
 // rustfmt-hard_tabs: true
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 impl<Target: FromEvent<A> + FromEvent<B>, A: Widget2<Ctx = C>, B: Widget2<Ctx = C>, C: for<'a> CtxFamily<'a>> Widget2 for WidgetEventLifter<Target, A, B>
 {
diff --git a/src/tools/rustfmt/tests/source/issue-3840/version-two_soft-tabs.rs b/src/tools/rustfmt/tests/source/issue-3840/version-two_soft-tabs.rs
index 39c8ef31292..9e283d3be0a 100644
--- a/src/tools/rustfmt/tests/source/issue-3840/version-two_soft-tabs.rs
+++ b/src/tools/rustfmt/tests/source/issue-3840/version-two_soft-tabs.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 impl<Target: FromEvent<A> + FromEvent<B>, A: Widget2<Ctx = C>, B: Widget2<Ctx = C>, C: for<'a> CtxFamily<'a>> Widget2 for WidgetEventLifter<Target, A, B>
 {
diff --git a/src/tools/rustfmt/tests/source/issue-4381/style_edition_2015.rs b/src/tools/rustfmt/tests/source/issue-4381/style_edition_2015.rs
new file mode 100644
index 00000000000..bb4c9feae1d
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/issue-4381/style_edition_2015.rs
@@ -0,0 +1,3 @@
+// rustfmt-style_edition: 2015
+
+use std::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64};
diff --git a/src/tools/rustfmt/tests/source/issue-4530.rs b/src/tools/rustfmt/tests/source/issue-4530.rs
index 9d2882abb3c..6b92122f0c0 100644
--- a/src/tools/rustfmt/tests/source/issue-4530.rs
+++ b/src/tools/rustfmt/tests/source/issue-4530.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 fn main() {
     let [aaaaaaaaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, cccccccccccccccccccccccccc, ddddddddddddddddddddddddd] = panic!();
 }
diff --git a/src/tools/rustfmt/tests/source/issue-4689/one.rs b/src/tools/rustfmt/tests/source/issue-4689/one.rs
index d048eb10fb1..bff090a3525 100644
--- a/src/tools/rustfmt/tests/source/issue-4689/one.rs
+++ b/src/tools/rustfmt/tests/source/issue-4689/one.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 
 // Based on the issue description
 pub trait PrettyPrinter<'tcx>:
diff --git a/src/tools/rustfmt/tests/source/issue-4689/two.rs b/src/tools/rustfmt/tests/source/issue-4689/two.rs
index ea7feda825d..217535c046e 100644
--- a/src/tools/rustfmt/tests/source/issue-4689/two.rs
+++ b/src/tools/rustfmt/tests/source/issue-4689/two.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 // Based on the issue description
 pub trait PrettyPrinter<'tcx>:
diff --git a/src/tools/rustfmt/tests/source/issue-5586.rs b/src/tools/rustfmt/tests/source/issue-5586.rs
index 9cf6c1d58dd..061ad4bdaa4 100644
--- a/src/tools/rustfmt/tests/source/issue-5586.rs
+++ b/src/tools/rustfmt/tests/source/issue-5586.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 fn main() {
     // sample 1
     {
diff --git a/src/tools/rustfmt/tests/source/issue-5655/one.rs b/src/tools/rustfmt/tests/source/issue-5655/one.rs
index 1758ec56f8b..62df2655c29 100644
--- a/src/tools/rustfmt/tests/source/issue-5655/one.rs
+++ b/src/tools/rustfmt/tests/source/issue-5655/one.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 
 fn foo<T>(_: T)
 where
diff --git a/src/tools/rustfmt/tests/source/issue-5655/two.rs b/src/tools/rustfmt/tests/source/issue-5655/two.rs
index e37ebbea8af..bfe1d3813bb 100644
--- a/src/tools/rustfmt/tests/source/issue-5655/two.rs
+++ b/src/tools/rustfmt/tests/source/issue-5655/two.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 fn foo<T>(_: T)
 where
diff --git a/src/tools/rustfmt/tests/source/issue-5801/comment_unexpectedly_wraps_before_max_width.rs b/src/tools/rustfmt/tests/source/issue-5801/comment_unexpectedly_wraps_before_max_width.rs
index 5847afd9560..e61d34604a1 100644
--- a/src/tools/rustfmt/tests/source/issue-5801/comment_unexpectedly_wraps_before_max_width.rs
+++ b/src/tools/rustfmt/tests/source/issue-5801/comment_unexpectedly_wraps_before_max_width.rs
@@ -1,7 +1,7 @@
 // rustfmt-comment_width: 120
 // rustfmt-wrap_comments: true
 // rustfmt-max_width: 120
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 
 /// This function is 120 columns wide and is left alone. This comment is 120 columns wide and the formatter is also fine
 fn my_super_cool_function_name(my_very_cool_argument_name: String, my_other_very_cool_argument_name: String) -> String {
diff --git a/src/tools/rustfmt/tests/source/issue-5987/two.rs b/src/tools/rustfmt/tests/source/issue-5987/two.rs
index e20026b5565..98ed35c4f9a 100644
--- a/src/tools/rustfmt/tests/source/issue-5987/two.rs
+++ b/src/tools/rustfmt/tests/source/issue-5987/two.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 fn main() {
     trace!(
diff --git a/src/tools/rustfmt/tests/source/issue-6147/case_rustfmt_v1.rs b/src/tools/rustfmt/tests/source/issue-6147/case_rustfmt_v1.rs
index 2ac2e0361c3..bcae86aaff2 100644
--- a/src/tools/rustfmt/tests/source/issue-6147/case_rustfmt_v1.rs
+++ b/src/tools/rustfmt/tests/source/issue-6147/case_rustfmt_v1.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 
 pub fn main() {
 let a = Some(12);
diff --git a/src/tools/rustfmt/tests/source/issue-6147/case_rustfmt_v2.rs b/src/tools/rustfmt/tests/source/issue-6147/case_rustfmt_v2.rs
index c1bf1ad4bf8..da612b213fc 100644
--- a/src/tools/rustfmt/tests/source/issue-6147/case_rustfmt_v2.rs
+++ b/src/tools/rustfmt/tests/source/issue-6147/case_rustfmt_v2.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 pub fn main() {
 let a = Some(12);
diff --git a/src/tools/rustfmt/tests/source/issue_5027.rs b/src/tools/rustfmt/tests/source/issue_5027.rs
index 67beeb23b71..a47d6df6f0f 100644
--- a/src/tools/rustfmt/tests/source/issue_5027.rs
+++ b/src/tools/rustfmt/tests/source/issue_5027.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 pub type Iter<'a, D> =                 impl       DoubleEndedIterator<Item = (SomethingSomethingSomethingLongType<D>)>+ ExactSizeIterator+ 'a;
 
diff --git a/src/tools/rustfmt/tests/source/let_else_v2.rs b/src/tools/rustfmt/tests/source/let_else_v2.rs
index a420fbcf95b..23be32d629a 100644
--- a/src/tools/rustfmt/tests/source/let_else_v2.rs
+++ b/src/tools/rustfmt/tests/source/let_else_v2.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 // rustfmt-single_line_let_else_max_width: 100
 
 fn issue5901() {
diff --git a/src/tools/rustfmt/tests/source/long-fn-1/version_one.rs b/src/tools/rustfmt/tests/source/long-fn-1/version_one.rs
index d6832c2af09..60083024810 100644
--- a/src/tools/rustfmt/tests/source/long-fn-1/version_one.rs
+++ b/src/tools/rustfmt/tests/source/long-fn-1/version_one.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 // Tests that a function which is almost short enough, but not quite, gets
 // formatted correctly.
 
diff --git a/src/tools/rustfmt/tests/source/long-fn-1/version_two.rs b/src/tools/rustfmt/tests/source/long-fn-1/version_two.rs
index f402a26e8b6..bce2c551c6a 100644
--- a/src/tools/rustfmt/tests/source/long-fn-1/version_two.rs
+++ b/src/tools/rustfmt/tests/source/long-fn-1/version_two.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 // Tests that a function which is almost short enough, but not quite, gets
 // formatted correctly.
 
diff --git a/src/tools/rustfmt/tests/source/one_line_if_v1.rs b/src/tools/rustfmt/tests/source/one_line_if_v1.rs
index d3dcbe6787a..bf7bc75fb88 100644
--- a/src/tools/rustfmt/tests/source/one_line_if_v1.rs
+++ b/src/tools/rustfmt/tests/source/one_line_if_v1.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 
 fn plain_if(x: bool) -> u8 {
     if x {
diff --git a/src/tools/rustfmt/tests/source/one_line_if_v2.rs b/src/tools/rustfmt/tests/source/one_line_if_v2.rs
index 40c834959f9..f3c974b12db 100644
--- a/src/tools/rustfmt/tests/source/one_line_if_v2.rs
+++ b/src/tools/rustfmt/tests/source/one_line_if_v2.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 fn plain_if(x: bool) -> u8 {
     if x {
diff --git a/src/tools/rustfmt/tests/source/single-line-macro/v1.rs b/src/tools/rustfmt/tests/source/single-line-macro/v1.rs
index a3aa631ed4a..fea146d8d33 100644
--- a/src/tools/rustfmt/tests/source/single-line-macro/v1.rs
+++ b/src/tools/rustfmt/tests/source/single-line-macro/v1.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 
 // #2652
 // Preserve trailing comma inside macro, even if it looks an array.
diff --git a/src/tools/rustfmt/tests/source/single-line-macro/v2.rs b/src/tools/rustfmt/tests/source/single-line-macro/v2.rs
index 51a665f7560..d9fba64ac70 100644
--- a/src/tools/rustfmt/tests/source/single-line-macro/v2.rs
+++ b/src/tools/rustfmt/tests/source/single-line-macro/v2.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 // #2652
 // Preserve trailing comma inside macro, even if it looks an array.
diff --git a/src/tools/rustfmt/tests/source/trailing_comments/hard_tabs.rs b/src/tools/rustfmt/tests/source/trailing_comments/hard_tabs.rs
index 88249aa5fb9..c6d1b3f0ab7 100644
--- a/src/tools/rustfmt/tests/source/trailing_comments/hard_tabs.rs
+++ b/src/tools/rustfmt/tests/source/trailing_comments/hard_tabs.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 // rustfmt-wrap_comments: true
 // rustfmt-hard_tabs: true
 
diff --git a/src/tools/rustfmt/tests/source/trailing_comments/soft_tabs.rs b/src/tools/rustfmt/tests/source/trailing_comments/soft_tabs.rs
index 7845f713b8a..431875989f3 100644
--- a/src/tools/rustfmt/tests/source/trailing_comments/soft_tabs.rs
+++ b/src/tools/rustfmt/tests/source/trailing_comments/soft_tabs.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 // rustfmt-wrap_comments: true
 
 pub const IFF_MULTICAST: ::c_int = 0x0000000800; // Supports multicast
diff --git a/src/tools/rustfmt/tests/source/tuple_v2.rs b/src/tools/rustfmt/tests/source/tuple_v2.rs
index 9223033832b..6dc18e00d7e 100644
--- a/src/tools/rustfmt/tests/source/tuple_v2.rs
+++ b/src/tools/rustfmt/tests/source/tuple_v2.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 fn issue_4355() {
     let _ = ((1,),).0 .0;
diff --git a/src/tools/rustfmt/tests/source/type-alias-where-clauses-with-comments.rs b/src/tools/rustfmt/tests/source/type-alias-where-clauses-with-comments.rs
new file mode 100644
index 00000000000..722ebac47ac
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/type-alias-where-clauses-with-comments.rs
@@ -0,0 +1,31 @@
+type Foo // comment1
+    // interlinear1
+where // comment2
+    // interlinear2
+A: B, // comment3
+C: D, // comment4
+    // interlinear3
+= E; // comment5
+
+type Foo // comment6
+    // interlinear4
+where// comment7
+    // interlinear5
+A: B, // comment8
+C: D, // comment9
+    // interlinear6
+= E // comment10
+    // interlinear7
+where // comment11
+    // interlinear8
+F: G, // comment12
+H: I; // comment13
+
+type Foo // comment14
+    // interlinear9
+= E // comment15
+    // interlinear10
+where // comment16
+    // interlinear11
+F: G,// comment17
+H: I;// comment18
diff --git a/src/tools/rustfmt/tests/source/type-alias-where-clauses.rs b/src/tools/rustfmt/tests/source/type-alias-where-clauses.rs
new file mode 100644
index 00000000000..ad998caf308
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/type-alias-where-clauses.rs
@@ -0,0 +1,20 @@
+    type Foo
+    where
+    A: B,
+    C: D,
+    = E;
+
+    type Foo
+    where
+    A: B,
+    C: D,
+    = E
+    where
+    F: G,
+    H: I;
+
+    type Foo
+    = E
+    where
+    F: G,
+    H: I;
\ No newline at end of file
diff --git a/src/tools/rustfmt/tests/target/arrow_in_comments/arrow_in_single_comment.rs b/src/tools/rustfmt/tests/target/arrow_in_comments/arrow_in_single_comment.rs
index deffdbeeaaf..d638a6b4ef0 100644
--- a/src/tools/rustfmt/tests/target/arrow_in_comments/arrow_in_single_comment.rs
+++ b/src/tools/rustfmt/tests/target/arrow_in_comments/arrow_in_single_comment.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 fn main() {
     match a {
         _ =>
diff --git a/src/tools/rustfmt/tests/target/arrow_in_comments/multiple_arrows.rs b/src/tools/rustfmt/tests/target/arrow_in_comments/multiple_arrows.rs
index b0443411816..f6f4a60eec3 100644
--- a/src/tools/rustfmt/tests/target/arrow_in_comments/multiple_arrows.rs
+++ b/src/tools/rustfmt/tests/target/arrow_in_comments/multiple_arrows.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 fn main() {
     match a {
         _ =>
diff --git a/src/tools/rustfmt/tests/target/configs/indent_style/block_trailing_comma_call/one.rs b/src/tools/rustfmt/tests/target/configs/indent_style/block_trailing_comma_call/one.rs
index 6b9489bef55..204dce6d655 100644
--- a/src/tools/rustfmt/tests/target/configs/indent_style/block_trailing_comma_call/one.rs
+++ b/src/tools/rustfmt/tests/target/configs/indent_style/block_trailing_comma_call/one.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 // rustfmt-error_on_line_overflow: false
 // rustfmt-indent_style: Block
 
diff --git a/src/tools/rustfmt/tests/target/configs/indent_style/block_trailing_comma_call/two.rs b/src/tools/rustfmt/tests/target/configs/indent_style/block_trailing_comma_call/two.rs
index 4f4292e5f48..887e8328ccc 100644
--- a/src/tools/rustfmt/tests/target/configs/indent_style/block_trailing_comma_call/two.rs
+++ b/src/tools/rustfmt/tests/target/configs/indent_style/block_trailing_comma_call/two.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 // rustfmt-error_on_line_overflow: false
 // rustfmt-indent_style: Block
 
diff --git a/src/tools/rustfmt/tests/target/configs/style_edition/overflow_delim_expr_2015.rs b/src/tools/rustfmt/tests/target/configs/style_edition/overflow_delim_expr_2015.rs
new file mode 100644
index 00000000000..05d4b8b6d33
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/configs/style_edition/overflow_delim_expr_2015.rs
@@ -0,0 +1,135 @@
+// rustfmt-style_edition: 2015
+
+fn combine_blocklike() {
+    do_thing(|param| {
+        action();
+        foo(param)
+    });
+
+    do_thing(x, |param| {
+        action();
+        foo(param)
+    });
+
+    do_thing(
+        x,
+        // I'll be discussing the `action` with your para(m)legal counsel
+        |param| {
+            action();
+            foo(param)
+        },
+    );
+
+    do_thing(Bar {
+        x: value,
+        y: value2,
+    });
+
+    do_thing(
+        x,
+        Bar {
+            x: value,
+            y: value2,
+        },
+    );
+
+    do_thing(
+        x,
+        // Let me tell you about that one time at the `Bar`
+        Bar {
+            x: value,
+            y: value2,
+        },
+    );
+
+    do_thing(&[
+        value_with_longer_name,
+        value2_with_longer_name,
+        value3_with_longer_name,
+        value4_with_longer_name,
+    ]);
+
+    do_thing(
+        x,
+        &[
+            value_with_longer_name,
+            value2_with_longer_name,
+            value3_with_longer_name,
+            value4_with_longer_name,
+        ],
+    );
+
+    do_thing(
+        x,
+        // Just admit it; my list is longer than can be folded on to one line
+        &[
+            value_with_longer_name,
+            value2_with_longer_name,
+            value3_with_longer_name,
+            value4_with_longer_name,
+        ],
+    );
+
+    do_thing(vec![
+        value_with_longer_name,
+        value2_with_longer_name,
+        value3_with_longer_name,
+        value4_with_longer_name,
+    ]);
+
+    do_thing(
+        x,
+        vec![
+            value_with_longer_name,
+            value2_with_longer_name,
+            value3_with_longer_name,
+            value4_with_longer_name,
+        ],
+    );
+
+    do_thing(
+        x,
+        // Just admit it; my list is longer than can be folded on to one line
+        vec![
+            value_with_longer_name,
+            value2_with_longer_name,
+            value3_with_longer_name,
+            value4_with_longer_name,
+        ],
+    );
+
+    do_thing(
+        x,
+        (1, 2, 3, |param| {
+            action();
+            foo(param)
+        }),
+    );
+}
+
+fn combine_struct_sample() {
+    let identity = verify(
+        &ctx,
+        VerifyLogin {
+            type_: LoginType::Username,
+            username: args.username.clone(),
+            password: Some(args.password.clone()),
+            domain: None,
+        },
+    )?;
+}
+
+fn combine_macro_sample() {
+    rocket::ignite()
+        .mount(
+            "/",
+            routes![
+                http::auth::login,
+                http::auth::logout,
+                http::cors::options,
+                http::action::dance,
+                http::action::sleep,
+            ],
+        )
+        .launch();
+}
diff --git a/src/tools/rustfmt/tests/target/configs/style_edition/overflow_delim_expr_2024.rs b/src/tools/rustfmt/tests/target/configs/style_edition/overflow_delim_expr_2024.rs
new file mode 100644
index 00000000000..ecd2e8ca797
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/configs/style_edition/overflow_delim_expr_2024.rs
@@ -0,0 +1,120 @@
+// rustfmt-style_edition: 2024
+
+fn combine_blocklike() {
+    do_thing(|param| {
+        action();
+        foo(param)
+    });
+
+    do_thing(x, |param| {
+        action();
+        foo(param)
+    });
+
+    do_thing(
+        x,
+        // I'll be discussing the `action` with your para(m)legal counsel
+        |param| {
+            action();
+            foo(param)
+        },
+    );
+
+    do_thing(Bar {
+        x: value,
+        y: value2,
+    });
+
+    do_thing(x, Bar {
+        x: value,
+        y: value2,
+    });
+
+    do_thing(
+        x,
+        // Let me tell you about that one time at the `Bar`
+        Bar {
+            x: value,
+            y: value2,
+        },
+    );
+
+    do_thing(&[
+        value_with_longer_name,
+        value2_with_longer_name,
+        value3_with_longer_name,
+        value4_with_longer_name,
+    ]);
+
+    do_thing(x, &[
+        value_with_longer_name,
+        value2_with_longer_name,
+        value3_with_longer_name,
+        value4_with_longer_name,
+    ]);
+
+    do_thing(
+        x,
+        // Just admit it; my list is longer than can be folded on to one line
+        &[
+            value_with_longer_name,
+            value2_with_longer_name,
+            value3_with_longer_name,
+            value4_with_longer_name,
+        ],
+    );
+
+    do_thing(vec![
+        value_with_longer_name,
+        value2_with_longer_name,
+        value3_with_longer_name,
+        value4_with_longer_name,
+    ]);
+
+    do_thing(x, vec![
+        value_with_longer_name,
+        value2_with_longer_name,
+        value3_with_longer_name,
+        value4_with_longer_name,
+    ]);
+
+    do_thing(
+        x,
+        // Just admit it; my list is longer than can be folded on to one line
+        vec![
+            value_with_longer_name,
+            value2_with_longer_name,
+            value3_with_longer_name,
+            value4_with_longer_name,
+        ],
+    );
+
+    do_thing(
+        x,
+        (1, 2, 3, |param| {
+            action();
+            foo(param)
+        }),
+    );
+}
+
+fn combine_struct_sample() {
+    let identity = verify(&ctx, VerifyLogin {
+        type_: LoginType::Username,
+        username: args.username.clone(),
+        password: Some(args.password.clone()),
+        domain: None,
+    })?;
+}
+
+fn combine_macro_sample() {
+    rocket::ignite()
+        .mount("/", routes![
+            http::auth::login,
+            http::auth::logout,
+            http::cors::options,
+            http::action::dance,
+            http::action::sleep,
+        ])
+        .launch();
+}
diff --git a/src/tools/rustfmt/tests/target/configs/version/mapped.rs b/src/tools/rustfmt/tests/target/configs/version/mapped.rs
new file mode 100644
index 00000000000..296dc559a93
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/configs/version/mapped.rs
@@ -0,0 +1,9 @@
+// rustfmt-version: Two
+fn main() {
+    let [
+        aaaaaaaaaaaaaaaaaaaaaaaaaa,
+        bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
+        cccccccccccccccccccccccccc,
+        ddddddddddddddddddddddddd,
+    ] = panic!();
+}
diff --git a/src/tools/rustfmt/tests/target/fn-single-line/version_one.rs b/src/tools/rustfmt/tests/target/fn-single-line/version_one.rs
index 013b2cd7216..5b704474d6d 100644
--- a/src/tools/rustfmt/tests/target/fn-single-line/version_one.rs
+++ b/src/tools/rustfmt/tests/target/fn-single-line/version_one.rs
@@ -1,5 +1,5 @@
 // rustfmt-fn_single_line: true
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 // Test single-line functions.
 
 fn foo_expr() { 1 }
diff --git a/src/tools/rustfmt/tests/target/fn-single-line/version_two.rs b/src/tools/rustfmt/tests/target/fn-single-line/version_two.rs
index b8053d4c2f5..aedd1d481b6 100644
--- a/src/tools/rustfmt/tests/target/fn-single-line/version_two.rs
+++ b/src/tools/rustfmt/tests/target/fn-single-line/version_two.rs
@@ -1,5 +1,5 @@
 // rustfmt-fn_single_line: true
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 // Test single-line functions.
 
 fn foo_expr() { 1 }
diff --git a/src/tools/rustfmt/tests/target/issue-2179/one.rs b/src/tools/rustfmt/tests/target/issue-2179/one.rs
index 3f98acc8dcd..6593624e589 100644
--- a/src/tools/rustfmt/tests/target/issue-2179/one.rs
+++ b/src/tools/rustfmt/tests/target/issue-2179/one.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 // rustfmt-error_on_line_overflow: false
 
 fn issue_2179() {
diff --git a/src/tools/rustfmt/tests/target/issue-2179/two.rs b/src/tools/rustfmt/tests/target/issue-2179/two.rs
index 96531509ea2..088518705fe 100644
--- a/src/tools/rustfmt/tests/target/issue-2179/two.rs
+++ b/src/tools/rustfmt/tests/target/issue-2179/two.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 // rustfmt-error_on_line_overflow: false
 
 fn issue_2179() {
diff --git a/src/tools/rustfmt/tests/target/issue-3132.rs b/src/tools/rustfmt/tests/target/issue-3132.rs
index 4dffe0ab836..4d61baa7507 100644
--- a/src/tools/rustfmt/tests/target/issue-3132.rs
+++ b/src/tools/rustfmt/tests/target/issue-3132.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 fn test() {
     /*
diff --git a/src/tools/rustfmt/tests/target/issue-3213/version_one.rs b/src/tools/rustfmt/tests/target/issue-3213/version_one.rs
index 307903b128b..a20915df761 100644
--- a/src/tools/rustfmt/tests/target/issue-3213/version_one.rs
+++ b/src/tools/rustfmt/tests/target/issue-3213/version_one.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 
 fn foo() {
     match 0 {
diff --git a/src/tools/rustfmt/tests/target/issue-3213/version_two.rs b/src/tools/rustfmt/tests/target/issue-3213/version_two.rs
index de93d04ba95..fb609f6a67a 100644
--- a/src/tools/rustfmt/tests/target/issue-3213/version_two.rs
+++ b/src/tools/rustfmt/tests/target/issue-3213/version_two.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 fn foo() {
     match 0 {
diff --git a/src/tools/rustfmt/tests/target/issue-3227/one.rs b/src/tools/rustfmt/tests/target/issue-3227/one.rs
index fcc8331000d..2922bfdfef7 100644
--- a/src/tools/rustfmt/tests/target/issue-3227/one.rs
+++ b/src/tools/rustfmt/tests/target/issue-3227/one.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 
 fn main() {
     thread::spawn(|| {
diff --git a/src/tools/rustfmt/tests/target/issue-3227/two.rs b/src/tools/rustfmt/tests/target/issue-3227/two.rs
index 374ab54305d..ae7eee47194 100644
--- a/src/tools/rustfmt/tests/target/issue-3227/two.rs
+++ b/src/tools/rustfmt/tests/target/issue-3227/two.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 fn main() {
     thread::spawn(|| {
diff --git a/src/tools/rustfmt/tests/target/issue-3270/one.rs b/src/tools/rustfmt/tests/target/issue-3270/one.rs
index 78de9473243..a31a0ff5742 100644
--- a/src/tools/rustfmt/tests/target/issue-3270/one.rs
+++ b/src/tools/rustfmt/tests/target/issue-3270/one.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 
 pub fn main() {
     /*   let s = String::from(
diff --git a/src/tools/rustfmt/tests/target/issue-3270/two.rs b/src/tools/rustfmt/tests/target/issue-3270/two.rs
index e48b5921329..8e26f8ac23d 100644
--- a/src/tools/rustfmt/tests/target/issue-3270/two.rs
+++ b/src/tools/rustfmt/tests/target/issue-3270/two.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 pub fn main() {
     /*   let s = String::from(
diff --git a/src/tools/rustfmt/tests/target/issue-3270/wrap.rs b/src/tools/rustfmt/tests/target/issue-3270/wrap.rs
index 7435c5f0866..967bfb5534c 100644
--- a/src/tools/rustfmt/tests/target/issue-3270/wrap.rs
+++ b/src/tools/rustfmt/tests/target/issue-3270/wrap.rs
@@ -1,5 +1,5 @@
 // rustfmt-wrap_comments: true
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 // check that a line below max_width does not get over the limit when wrapping
 // it in a block comment
diff --git a/src/tools/rustfmt/tests/target/issue-3272/v1.rs b/src/tools/rustfmt/tests/target/issue-3272/v1.rs
index aab201027d5..7cca7ea7896 100644
--- a/src/tools/rustfmt/tests/target/issue-3272/v1.rs
+++ b/src/tools/rustfmt/tests/target/issue-3272/v1.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 
 fn main() {
     assert!(HAYSTACK
diff --git a/src/tools/rustfmt/tests/target/issue-3272/v2.rs b/src/tools/rustfmt/tests/target/issue-3272/v2.rs
index a42a2fccd5b..ca7718c5a61 100644
--- a/src/tools/rustfmt/tests/target/issue-3272/v2.rs
+++ b/src/tools/rustfmt/tests/target/issue-3272/v2.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 fn main() {
     assert!(
diff --git a/src/tools/rustfmt/tests/target/issue-3278/version_one.rs b/src/tools/rustfmt/tests/target/issue-3278/version_one.rs
index 580679fbae3..718a32b4c7e 100644
--- a/src/tools/rustfmt/tests/target/issue-3278/version_one.rs
+++ b/src/tools/rustfmt/tests/target/issue-3278/version_one.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 
 pub fn parse_conditional<'a, I: 'a>(
 ) -> impl Parser<Input = I, Output = Expr, PartialState = ()> + 'a
diff --git a/src/tools/rustfmt/tests/target/issue-3278/version_two.rs b/src/tools/rustfmt/tests/target/issue-3278/version_two.rs
index c17b1742d39..eb605e509f9 100644
--- a/src/tools/rustfmt/tests/target/issue-3278/version_two.rs
+++ b/src/tools/rustfmt/tests/target/issue-3278/version_two.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 pub fn parse_conditional<'a, I: 'a>()
 -> impl Parser<Input = I, Output = Expr, PartialState = ()> + 'a
diff --git a/src/tools/rustfmt/tests/target/issue-3295/two.rs b/src/tools/rustfmt/tests/target/issue-3295/two.rs
index 3e669a0bb75..4f685172cfa 100644
--- a/src/tools/rustfmt/tests/target/issue-3295/two.rs
+++ b/src/tools/rustfmt/tests/target/issue-3295/two.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 pub enum TestEnum {
     a,
     b,
diff --git a/src/tools/rustfmt/tests/target/issue-3302.rs b/src/tools/rustfmt/tests/target/issue-3302.rs
index 146cb983819..504bfd987f5 100644
--- a/src/tools/rustfmt/tests/target/issue-3302.rs
+++ b/src/tools/rustfmt/tests/target/issue-3302.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 macro_rules! moo1 {
     () => {
diff --git a/src/tools/rustfmt/tests/target/issue-3614/version_one.rs b/src/tools/rustfmt/tests/target/issue-3614/version_one.rs
index 8ab28304732..4bd972aa87a 100644
--- a/src/tools/rustfmt/tests/target/issue-3614/version_one.rs
+++ b/src/tools/rustfmt/tests/target/issue-3614/version_one.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 
 fn main() {
     let toto = || {
diff --git a/src/tools/rustfmt/tests/target/issue-3614/version_two.rs b/src/tools/rustfmt/tests/target/issue-3614/version_two.rs
index 5d6f8e7a313..7b9534caa02 100644
--- a/src/tools/rustfmt/tests/target/issue-3614/version_two.rs
+++ b/src/tools/rustfmt/tests/target/issue-3614/version_two.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 fn main() {
     let toto = || {
diff --git a/src/tools/rustfmt/tests/target/issue-3701/one.rs b/src/tools/rustfmt/tests/target/issue-3701/one.rs
index 9d1ef9eed9a..b154724d341 100644
--- a/src/tools/rustfmt/tests/target/issue-3701/one.rs
+++ b/src/tools/rustfmt/tests/target/issue-3701/one.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 
 fn build_sorted_static_get_entry_names(
     mut entries: Vec<(u8, &'static str)>,
diff --git a/src/tools/rustfmt/tests/target/issue-3701/two.rs b/src/tools/rustfmt/tests/target/issue-3701/two.rs
index 62ffc9d823d..995763ef291 100644
--- a/src/tools/rustfmt/tests/target/issue-3701/two.rs
+++ b/src/tools/rustfmt/tests/target/issue-3701/two.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 fn build_sorted_static_get_entry_names(
     mut entries: Vec<(u8, &'static str)>,
diff --git a/src/tools/rustfmt/tests/target/issue-3805.rs b/src/tools/rustfmt/tests/target/issue-3805.rs
index a247a43fe6d..a1eda832d76 100644
--- a/src/tools/rustfmt/tests/target/issue-3805.rs
+++ b/src/tools/rustfmt/tests/target/issue-3805.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 // rustfmt-format_macro_matchers: true
 
 // From original issue example - Line length 101
diff --git a/src/tools/rustfmt/tests/target/issue-3840/version-two_hard-tabs.rs b/src/tools/rustfmt/tests/target/issue-3840/version-two_hard-tabs.rs
index 084db3d1465..78a2f921735 100644
--- a/src/tools/rustfmt/tests/target/issue-3840/version-two_hard-tabs.rs
+++ b/src/tools/rustfmt/tests/target/issue-3840/version-two_hard-tabs.rs
@@ -1,5 +1,5 @@
 // rustfmt-hard_tabs: true
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 impl<
 	Target: FromEvent<A> + FromEvent<B>,
diff --git a/src/tools/rustfmt/tests/target/issue-3840/version-two_soft-tabs.rs b/src/tools/rustfmt/tests/target/issue-3840/version-two_soft-tabs.rs
index bc59b0baa56..c76dd4dafbb 100644
--- a/src/tools/rustfmt/tests/target/issue-3840/version-two_soft-tabs.rs
+++ b/src/tools/rustfmt/tests/target/issue-3840/version-two_soft-tabs.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 impl<
     Target: FromEvent<A> + FromEvent<B>,
diff --git a/src/tools/rustfmt/tests/target/issue-3882.rs b/src/tools/rustfmt/tests/target/issue-3882.rs
index 5eb442af974..8e617635b7c 100644
--- a/src/tools/rustfmt/tests/target/issue-3882.rs
+++ b/src/tools/rustfmt/tests/target/issue-3882.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 fn bar(_t: T, // bar
 ) {
 }
diff --git a/src/tools/rustfmt/tests/target/issue-4381/style_edition_2015.rs b/src/tools/rustfmt/tests/target/issue-4381/style_edition_2015.rs
new file mode 100644
index 00000000000..1fc1613083e
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-4381/style_edition_2015.rs
@@ -0,0 +1,3 @@
+// rustfmt-style_edition: 2015
+
+use std::num::{NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8};
diff --git a/src/tools/rustfmt/tests/target/issue-4381/style_edition_2024.rs b/src/tools/rustfmt/tests/target/issue-4381/style_edition_2024.rs
new file mode 100644
index 00000000000..df85636ad57
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-4381/style_edition_2024.rs
@@ -0,0 +1,3 @@
+// rustfmt-style_edition: 2024
+
+use std::num::{NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64};
diff --git a/src/tools/rustfmt/tests/target/issue-4530.rs b/src/tools/rustfmt/tests/target/issue-4530.rs
index 296dc559a93..9e9fbf95c2d 100644
--- a/src/tools/rustfmt/tests/target/issue-4530.rs
+++ b/src/tools/rustfmt/tests/target/issue-4530.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 fn main() {
     let [
         aaaaaaaaaaaaaaaaaaaaaaaaaa,
diff --git a/src/tools/rustfmt/tests/target/issue-4689/one.rs b/src/tools/rustfmt/tests/target/issue-4689/one.rs
index 7735e34f3b5..fb523f38501 100644
--- a/src/tools/rustfmt/tests/target/issue-4689/one.rs
+++ b/src/tools/rustfmt/tests/target/issue-4689/one.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 
 // Based on the issue description
 pub trait PrettyPrinter<'tcx>:
diff --git a/src/tools/rustfmt/tests/target/issue-4689/two.rs b/src/tools/rustfmt/tests/target/issue-4689/two.rs
index e3b5cd22810..30303490129 100644
--- a/src/tools/rustfmt/tests/target/issue-4689/two.rs
+++ b/src/tools/rustfmt/tests/target/issue-4689/two.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 // Based on the issue description
 pub trait PrettyPrinter<'tcx>:
diff --git a/src/tools/rustfmt/tests/target/issue-5586.rs b/src/tools/rustfmt/tests/target/issue-5586.rs
index 7033ae975b3..afe13d1fb1c 100644
--- a/src/tools/rustfmt/tests/target/issue-5586.rs
+++ b/src/tools/rustfmt/tests/target/issue-5586.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 fn main() {
     // sample 1
     {
diff --git a/src/tools/rustfmt/tests/target/issue-5655/one.rs b/src/tools/rustfmt/tests/target/issue-5655/one.rs
index 1758ec56f8b..62df2655c29 100644
--- a/src/tools/rustfmt/tests/target/issue-5655/one.rs
+++ b/src/tools/rustfmt/tests/target/issue-5655/one.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 
 fn foo<T>(_: T)
 where
diff --git a/src/tools/rustfmt/tests/target/issue-5655/two.rs b/src/tools/rustfmt/tests/target/issue-5655/two.rs
index 14fbc3d1321..4a7eb4f4bc2 100644
--- a/src/tools/rustfmt/tests/target/issue-5655/two.rs
+++ b/src/tools/rustfmt/tests/target/issue-5655/two.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 fn foo<T>(_: T)
 where
diff --git a/src/tools/rustfmt/tests/target/issue-5801/comment_does_not_wrap_within_max_width.rs b/src/tools/rustfmt/tests/target/issue-5801/comment_does_not_wrap_within_max_width.rs
index 9f294751108..461b5873a68 100644
--- a/src/tools/rustfmt/tests/target/issue-5801/comment_does_not_wrap_within_max_width.rs
+++ b/src/tools/rustfmt/tests/target/issue-5801/comment_does_not_wrap_within_max_width.rs
@@ -1,7 +1,7 @@
 // rustfmt-comment_width: 120
 // rustfmt-wrap_comments: true
 // rustfmt-max_width: 120
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 /// This function is 120 columns wide and is left alone. This comment is 120 columns wide and the formatter is also fine
 fn my_super_cool_function_name(my_very_cool_argument_name: String, my_other_very_cool_argument_name: String) -> String {
diff --git a/src/tools/rustfmt/tests/target/issue-5801/comment_unexpectedly_wraps_before_max_width.rs b/src/tools/rustfmt/tests/target/issue-5801/comment_unexpectedly_wraps_before_max_width.rs
index dd839dd4548..58bb8a1c2e3 100644
--- a/src/tools/rustfmt/tests/target/issue-5801/comment_unexpectedly_wraps_before_max_width.rs
+++ b/src/tools/rustfmt/tests/target/issue-5801/comment_unexpectedly_wraps_before_max_width.rs
@@ -1,7 +1,7 @@
 // rustfmt-comment_width: 120
 // rustfmt-wrap_comments: true
 // rustfmt-max_width: 120
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 
 /// This function is 120 columns wide and is left alone. This comment is 120 columns wide and the formatter is also fine
 fn my_super_cool_function_name(my_very_cool_argument_name: String, my_other_very_cool_argument_name: String) -> String {
diff --git a/src/tools/rustfmt/tests/target/issue-5987/one.rs b/src/tools/rustfmt/tests/target/issue-5987/one.rs
index 3c995ed28ba..17327feead5 100644
--- a/src/tools/rustfmt/tests/target/issue-5987/one.rs
+++ b/src/tools/rustfmt/tests/target/issue-5987/one.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 
 fn main() {
     trace!(
diff --git a/src/tools/rustfmt/tests/target/issue-5987/two.rs b/src/tools/rustfmt/tests/target/issue-5987/two.rs
index 8fd92fc179e..41ecb13e3db 100644
--- a/src/tools/rustfmt/tests/target/issue-5987/two.rs
+++ b/src/tools/rustfmt/tests/target/issue-5987/two.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 fn main() {
     trace!(
diff --git a/src/tools/rustfmt/tests/target/issue-6109.rs b/src/tools/rustfmt/tests/target/issue-6109.rs
new file mode 100644
index 00000000000..7d2bbf75691
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/issue-6109.rs
@@ -0,0 +1,7 @@
+/// Some doc comment with code snippet:
+///```
+/// '\u{1F}
+/// ```
+pub struct Code {}
+
+fn main() {}
diff --git a/src/tools/rustfmt/tests/target/issue-6147/case_rustfmt_v1.rs b/src/tools/rustfmt/tests/target/issue-6147/case_rustfmt_v1.rs
index 75800012c63..d8e67655e4c 100644
--- a/src/tools/rustfmt/tests/target/issue-6147/case_rustfmt_v1.rs
+++ b/src/tools/rustfmt/tests/target/issue-6147/case_rustfmt_v1.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 
 pub fn main() {
     let a = Some(12);
diff --git a/src/tools/rustfmt/tests/target/issue-6147/case_rustfmt_v2.rs b/src/tools/rustfmt/tests/target/issue-6147/case_rustfmt_v2.rs
index 5e4220e7306..9d0b12d686b 100644
--- a/src/tools/rustfmt/tests/target/issue-6147/case_rustfmt_v2.rs
+++ b/src/tools/rustfmt/tests/target/issue-6147/case_rustfmt_v2.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 pub fn main() {
     let a = Some(12);
diff --git a/src/tools/rustfmt/tests/target/issue_5027.rs b/src/tools/rustfmt/tests/target/issue_5027.rs
index 26d771720b6..1de3e0d4f15 100644
--- a/src/tools/rustfmt/tests/target/issue_5027.rs
+++ b/src/tools/rustfmt/tests/target/issue_5027.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 pub type Iter<'a, D> = impl DoubleEndedIterator<Item = (SomethingSomethingSomethingLongType<D>)>
     + ExactSizeIterator
diff --git a/src/tools/rustfmt/tests/target/let_else_v2.rs b/src/tools/rustfmt/tests/target/let_else_v2.rs
index b25ac1609d8..6e886299cb0 100644
--- a/src/tools/rustfmt/tests/target/let_else_v2.rs
+++ b/src/tools/rustfmt/tests/target/let_else_v2.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 // rustfmt-single_line_let_else_max_width: 100
 
 fn issue5901() {
diff --git a/src/tools/rustfmt/tests/target/long-fn-1/version_one.rs b/src/tools/rustfmt/tests/target/long-fn-1/version_one.rs
index 05f69953c26..60f672c1837 100644
--- a/src/tools/rustfmt/tests/target/long-fn-1/version_one.rs
+++ b/src/tools/rustfmt/tests/target/long-fn-1/version_one.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 // Tests that a function which is almost short enough, but not quite, gets
 // formatted correctly.
 
diff --git a/src/tools/rustfmt/tests/target/long-fn-1/version_two.rs b/src/tools/rustfmt/tests/target/long-fn-1/version_two.rs
index 32794bccde2..f6007398bcc 100644
--- a/src/tools/rustfmt/tests/target/long-fn-1/version_two.rs
+++ b/src/tools/rustfmt/tests/target/long-fn-1/version_two.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 // Tests that a function which is almost short enough, but not quite, gets
 // formatted correctly.
 
diff --git a/src/tools/rustfmt/tests/target/one_line_if_v1.rs b/src/tools/rustfmt/tests/target/one_line_if_v1.rs
index b3c6c4cbeb2..5160ea0264c 100644
--- a/src/tools/rustfmt/tests/target/one_line_if_v1.rs
+++ b/src/tools/rustfmt/tests/target/one_line_if_v1.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 
 fn plain_if(x: bool) -> u8 {
     if x {
diff --git a/src/tools/rustfmt/tests/target/one_line_if_v2.rs b/src/tools/rustfmt/tests/target/one_line_if_v2.rs
index 81ca4c8b8b4..a9610ec9749 100644
--- a/src/tools/rustfmt/tests/target/one_line_if_v2.rs
+++ b/src/tools/rustfmt/tests/target/one_line_if_v2.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 fn plain_if(x: bool) -> u8 {
     if x { 0 } else { 1 }
diff --git a/src/tools/rustfmt/tests/target/single-line-macro/v1.rs b/src/tools/rustfmt/tests/target/single-line-macro/v1.rs
index a3aa631ed4a..fea146d8d33 100644
--- a/src/tools/rustfmt/tests/target/single-line-macro/v1.rs
+++ b/src/tools/rustfmt/tests/target/single-line-macro/v1.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: One
+// rustfmt-style_edition: 2015
 
 // #2652
 // Preserve trailing comma inside macro, even if it looks an array.
diff --git a/src/tools/rustfmt/tests/target/single-line-macro/v2.rs b/src/tools/rustfmt/tests/target/single-line-macro/v2.rs
index 9c6bcf33ad5..6fcacb70ba3 100644
--- a/src/tools/rustfmt/tests/target/single-line-macro/v2.rs
+++ b/src/tools/rustfmt/tests/target/single-line-macro/v2.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 // #2652
 // Preserve trailing comma inside macro, even if it looks an array.
diff --git a/src/tools/rustfmt/tests/target/style_edition/default.rs b/src/tools/rustfmt/tests/target/style_edition/default.rs
new file mode 100644
index 00000000000..17442df6c49
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/style_edition/default.rs
@@ -0,0 +1,10 @@
+fn build_sorted_static_get_entry_names(
+    mut entries: Vec<(u8, &'static str)>,
+) -> (impl Fn(
+    AlphabeticalTraversal,
+    Box<dyn dirents_sink::Sink<AlphabeticalTraversal>>,
+) -> BoxFuture<'static, Result<Box<dyn dirents_sink::Sealed>, Status>>
+        + Send
+        + Sync
+        + 'static) {
+}
diff --git a/src/tools/rustfmt/tests/target/style_edition/follows_edition.rs b/src/tools/rustfmt/tests/target/style_edition/follows_edition.rs
new file mode 100644
index 00000000000..c36a993d842
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/style_edition/follows_edition.rs
@@ -0,0 +1,14 @@
+// rustfmt-edition: 2024
+
+fn build_sorted_static_get_entry_names(
+    mut entries: Vec<(u8, &'static str)>,
+) -> (
+    impl Fn(
+        AlphabeticalTraversal,
+        Box<dyn dirents_sink::Sink<AlphabeticalTraversal>>,
+    ) -> BoxFuture<'static, Result<Box<dyn dirents_sink::Sealed>, Status>>
+    + Send
+    + Sync
+    + 'static
+) {
+}
diff --git a/src/tools/rustfmt/tests/target/style_edition/overrides_edition_when_set.rs b/src/tools/rustfmt/tests/target/style_edition/overrides_edition_when_set.rs
new file mode 100644
index 00000000000..6d0eaac8970
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/style_edition/overrides_edition_when_set.rs
@@ -0,0 +1,14 @@
+// rustfmt-edition: 2018
+// rustfmt-style_edition: 2024
+fn build_sorted_static_get_entry_names(
+    mut entries: Vec<(u8, &'static str)>,
+) -> (
+    impl Fn(
+        AlphabeticalTraversal,
+        Box<dyn dirents_sink::Sink<AlphabeticalTraversal>>,
+    ) -> BoxFuture<'static, Result<Box<dyn dirents_sink::Sealed>, Status>>
+    + Send
+    + Sync
+    + 'static
+) {
+}
diff --git a/src/tools/rustfmt/tests/target/trailing_comments/hard_tabs.rs b/src/tools/rustfmt/tests/target/trailing_comments/hard_tabs.rs
index 35e72f1affd..e7009ac00c0 100644
--- a/src/tools/rustfmt/tests/target/trailing_comments/hard_tabs.rs
+++ b/src/tools/rustfmt/tests/target/trailing_comments/hard_tabs.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 // rustfmt-wrap_comments: true
 // rustfmt-hard_tabs: true
 
diff --git a/src/tools/rustfmt/tests/target/trailing_comments/soft_tabs.rs b/src/tools/rustfmt/tests/target/trailing_comments/soft_tabs.rs
index eba943042ad..34cfed1a229 100644
--- a/src/tools/rustfmt/tests/target/trailing_comments/soft_tabs.rs
+++ b/src/tools/rustfmt/tests/target/trailing_comments/soft_tabs.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 // rustfmt-wrap_comments: true
 
 pub const IFF_MULTICAST: ::c_int = 0x0000000800; // Supports multicast
diff --git a/src/tools/rustfmt/tests/target/tuple_v2.rs b/src/tools/rustfmt/tests/target/tuple_v2.rs
index ba653291c2f..fa508332be5 100644
--- a/src/tools/rustfmt/tests/target/tuple_v2.rs
+++ b/src/tools/rustfmt/tests/target/tuple_v2.rs
@@ -1,4 +1,4 @@
-// rustfmt-version: Two
+// rustfmt-style_edition: 2024
 
 fn issue_4355() {
     let _ = ((1,),).0.0;
diff --git a/src/tools/rustfmt/tests/target/type-alias-where-clauses-with-comments.rs b/src/tools/rustfmt/tests/target/type-alias-where-clauses-with-comments.rs
new file mode 100644
index 00000000000..25c38916376
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/type-alias-where-clauses-with-comments.rs
@@ -0,0 +1,39 @@
+type Foo
+// comment1
+// interlinear1
+where
+    // comment2
+    // interlinear2
+    A: B, // comment3
+    C: D, // comment4
+// interlinear3
+= E; // comment5
+
+type Foo
+// comment6
+// interlinear4
+where
+    // comment7
+    // interlinear5
+    A: B, // comment8
+    C: D, // comment9
+// interlinear6
+= E
+// comment10
+// interlinear7
+where
+    // comment11
+    // interlinear8
+    F: G, // comment12
+    H: I; // comment13
+
+type Foo // comment14
+    // interlinear9
+    = E
+// comment15
+// interlinear10
+where
+    // comment16
+    // interlinear11
+    F: G, // comment17
+    H: I; // comment18
diff --git a/src/tools/rustfmt/tests/target/type-alias-where-clauses.rs b/src/tools/rustfmt/tests/target/type-alias-where-clauses.rs
new file mode 100644
index 00000000000..96d2d63bbb8
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/type-alias-where-clauses.rs
@@ -0,0 +1,20 @@
+type Foo
+where
+    A: B,
+    C: D,
+= E;
+
+type Foo
+where
+    A: B,
+    C: D,
+= E
+where
+    F: G,
+    H: I;
+
+type Foo
+    = E
+where
+    F: G,
+    H: I;
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index 8197a1bd859..3879f350e94 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -467,7 +467,6 @@ ui/closures/issue-87814-2.rs
 ui/closures/issue-90871.rs
 ui/closures/issue-97607.rs
 ui/closures/issue-99565.rs
-ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs
 ui/codegen/auxiliary/issue-97708-aux.rs
 ui/codegen/issue-101585-128bit-repeat.rs
 ui/codegen/issue-16602-1.rs
@@ -552,7 +551,6 @@ ui/const-generics/infer/issue-77092.rs
 ui/const-generics/issue-102124.rs
 ui/const-generics/issue-105689.rs
 ui/const-generics/issue-106419-struct-with-multiple-const-params.rs
-ui/const-generics/issue-112505-overflow.rs
 ui/const-generics/issue-46511.rs
 ui/const-generics/issue-66451.rs
 ui/const-generics/issue-70408.rs
@@ -1649,7 +1647,6 @@ ui/issues/issue-17068.rs
 ui/issues/issue-17121.rs
 ui/issues/issue-17216.rs
 ui/issues/issue-17252.rs
-ui/issues/issue-17302.rs
 ui/issues/issue-17322.rs
 ui/issues/issue-17336.rs
 ui/issues/issue-17337.rs
@@ -2718,7 +2715,6 @@ ui/limits/issue-15919-32.rs
 ui/limits/issue-15919-64.rs
 ui/limits/issue-17913.rs
 ui/limits/issue-55878.rs
-ui/limits/issue-56762.rs
 ui/limits/issue-69485-var-size-diffs-too-large.rs
 ui/limits/issue-75158-64.rs
 ui/linkage-attr/auxiliary/issue-12133-dylib.rs
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index 3215896091d..1e7eb82b83e 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -82,6 +82,7 @@ pub mod pal;
 pub mod run_make_tests;
 pub mod rustdoc_css_themes;
 pub mod rustdoc_gui_tests;
+pub mod rustdoc_templates;
 pub mod style;
 pub mod target_policy;
 pub mod target_specific_tests;
diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs
index e6d21bfb245..38b3f3f6417 100644
--- a/src/tools/tidy/src/main.rs
+++ b/src/tools/tidy/src/main.rs
@@ -108,6 +108,7 @@ fn main() {
         check!(mir_opt_tests, &tests_path, bless);
         check!(rustdoc_gui_tests, &tests_path);
         check!(rustdoc_css_themes, &librustdoc_path);
+        check!(rustdoc_templates, &librustdoc_path);
         check!(known_bug, &crashes_path);
         check!(unknown_revision, &tests_path);
 
diff --git a/src/tools/tidy/src/rustdoc_templates.rs b/src/tools/tidy/src/rustdoc_templates.rs
new file mode 100644
index 00000000000..6c8530e6366
--- /dev/null
+++ b/src/tools/tidy/src/rustdoc_templates.rs
@@ -0,0 +1,58 @@
+//! Tidy check to ensure that rustdoc templates didn't forget a `{# #}` to strip extra whitespace
+//! characters.
+
+use std::ffi::OsStr;
+use std::path::Path;
+
+use ignore::DirEntry;
+
+use crate::walk::walk;
+
+// Array containing `("beginning of tag", "end of tag")`.
+const TAGS: &[(&str, &str)] = &[("{#", "#}"), ("{%", "%}"), ("{{", "}}")];
+
+pub fn check(librustdoc_path: &Path, bad: &mut bool) {
+    walk(
+        &librustdoc_path.join("html/templates"),
+        |path, is_dir| is_dir || !path.extension().is_some_and(|ext| ext == OsStr::new("html")),
+        &mut |path: &DirEntry, file_content: &str| {
+            let mut lines = file_content.lines().enumerate().peekable();
+
+            while let Some((pos, line)) = lines.next() {
+                let line = line.trim();
+                if TAGS.iter().any(|(_, tag)| line.ends_with(tag)) {
+                    continue;
+                }
+                let Some(next_line) = lines.peek().map(|(_, next_line)| next_line.trim()) else {
+                    continue;
+                };
+                if TAGS.iter().any(|(tag, _)| next_line.starts_with(tag)) {
+                    continue;
+                }
+                // Maybe this is a multi-line tag, let's filter it out then.
+                match TAGS.iter().find_map(|(tag, end_tag)| {
+                    if line.rfind(tag).is_some() { Some(end_tag) } else { None }
+                }) {
+                    None => {
+                        // No it's not, let's error.
+                        tidy_error!(
+                            bad,
+                            "`{}` at line {}: missing `{{# #}}` at the end of the line",
+                            path.path().display(),
+                            pos + 1,
+                        );
+                    }
+                    Some(end_tag) => {
+                        // We skip the tag.
+                        while let Some((_, next_line)) = lines.peek() {
+                            if next_line.contains(end_tag) {
+                                break;
+                            }
+                            lines.next();
+                        }
+                    }
+                }
+            }
+        },
+    );
+}
diff --git a/tests/assembly/cmse.rs b/tests/assembly/cmse.rs
new file mode 100644
index 00000000000..acad77b2513
--- /dev/null
+++ b/tests/assembly/cmse.rs
@@ -0,0 +1,26 @@
+//@ assembly-output: emit-asm
+//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -Copt-level=1
+//@ needs-llvm-components: arm
+#![crate_type = "lib"]
+#![feature(abi_c_cmse_nonsecure_call, cmse_nonsecure_entry, no_core, lang_items)]
+#![no_core]
+#[lang = "sized"]
+pub trait Sized {}
+#[lang = "copy"]
+pub trait Copy {}
+
+// CHECK-LABEL: __acle_se_entry_point
+// CHECK: bxns
+#[no_mangle]
+pub extern "C-cmse-nonsecure-entry" fn entry_point() -> i64 {
+    0
+}
+
+// CHECK-LABEL: call_nonsecure
+// CHECK: blxns
+#[no_mangle]
+pub fn call_nonsecure(
+    f: unsafe extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32) -> u64,
+) -> u64 {
+    unsafe { f(0, 1, 2, 3) }
+}
diff --git a/tests/assembly/simd-bitmask.rs b/tests/assembly/simd-bitmask.rs
index cd22ca06706..9a355cc162f 100644
--- a/tests/assembly/simd-bitmask.rs
+++ b/tests/assembly/simd-bitmask.rs
@@ -9,7 +9,6 @@
 //@ [x86-avx512] needs-llvm-components: x86
 //@ [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu
 //@ [aarch64] needs-llvm-components: aarch64
-//@ [aarch64] min-llvm-version: 18.0
 //@ assembly-output: emit-asm
 //@ compile-flags: --crate-type=lib -O -C panic=abort
 
diff --git a/tests/assembly/simd-intrinsic-gather.rs b/tests/assembly/simd-intrinsic-gather.rs
index 83015f05ab3..2cbb6cfbb50 100644
--- a/tests/assembly/simd-intrinsic-gather.rs
+++ b/tests/assembly/simd-intrinsic-gather.rs
@@ -2,7 +2,6 @@
 //@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
 //@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq
 //@ [x86-avx512] needs-llvm-components: x86
-//@ [x86-avx512] min-llvm-version: 18.0
 //@ assembly-output: emit-asm
 //@ compile-flags: --crate-type=lib -O -C panic=abort
 
diff --git a/tests/assembly/simd-intrinsic-mask-reduce.rs b/tests/assembly/simd-intrinsic-mask-reduce.rs
index dd4dbaeda76..61d7aa59093 100644
--- a/tests/assembly/simd-intrinsic-mask-reduce.rs
+++ b/tests/assembly/simd-intrinsic-mask-reduce.rs
@@ -6,7 +6,6 @@
 //@ [x86] needs-llvm-components: x86
 //@ [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu
 //@ [aarch64] needs-llvm-components: aarch64
-//@ [aarch64] min-llvm-version: 18.0
 //@ assembly-output: emit-asm
 //@ compile-flags: --crate-type=lib -O -C panic=abort
 
diff --git a/tests/assembly/simd-intrinsic-scatter.rs b/tests/assembly/simd-intrinsic-scatter.rs
index 55095e4cb68..679972d9b86 100644
--- a/tests/assembly/simd-intrinsic-scatter.rs
+++ b/tests/assembly/simd-intrinsic-scatter.rs
@@ -2,7 +2,6 @@
 //@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel
 //@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq
 //@ [x86-avx512] needs-llvm-components: x86
-//@ [x86-avx512] min-llvm-version: 18.0
 //@ assembly-output: emit-asm
 //@ compile-flags: --crate-type=lib -O -C panic=abort
 
diff --git a/tests/assembly/simd-intrinsic-select.rs b/tests/assembly/simd-intrinsic-select.rs
index 4dfc2f9ed1f..57fd36fd9e3 100644
--- a/tests/assembly/simd-intrinsic-select.rs
+++ b/tests/assembly/simd-intrinsic-select.rs
@@ -7,7 +7,6 @@
 //@ [x86-avx512] needs-llvm-components: x86
 //@ [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu
 //@ [aarch64] needs-llvm-components: aarch64
-//@ [aarch64] min-llvm-version: 18.0
 //@ assembly-output: emit-asm
 //@ compile-flags: --crate-type=lib -O -C panic=abort
 
diff --git a/tests/assembly/stack-probes.rs b/tests/assembly/stack-probes.rs
index ddabd4b1632..e0931157ce1 100644
--- a/tests/assembly/stack-probes.rs
+++ b/tests/assembly/stack-probes.rs
@@ -6,7 +6,6 @@
 //@[i686] needs-llvm-components: x86
 //@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu
 //@[aarch64] needs-llvm-components: aarch64
-//@[aarch64] min-llvm-version: 18
 
 #![feature(no_core, lang_items)]
 #![crate_type = "lib"]
diff --git a/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs
index 5ed0b6c50a7..57fc601a2e0 100644
--- a/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs
+++ b/tests/assembly/stack-protector/stack-protector-heuristics-effect.rs
@@ -9,7 +9,6 @@
 //@ [basic] compile-flags: -Z stack-protector=basic
 //@ [none] compile-flags: -Z stack-protector=none
 //@ compile-flags: -C opt-level=2 -Z merge-functions=disabled
-//@ min-llvm-version: 17.0.2
 
 // NOTE: the heuristics for stack smash protection inappropriately rely on types in LLVM IR,
 // despite those types having no semantic meaning. This means that the `basic` and `strong`
diff --git a/tests/assembly/targets/targets-macho.rs b/tests/assembly/targets/targets-macho.rs
index 713129b692c..8095ae9029b 100644
--- a/tests/assembly/targets/targets-macho.rs
+++ b/tests/assembly/targets/targets-macho.rs
@@ -18,6 +18,9 @@
 //@ revisions: aarch64_apple_tvos_sim
 //@ [aarch64_apple_tvos_sim] compile-flags: --target aarch64-apple-tvos-sim
 //@ [aarch64_apple_tvos_sim] needs-llvm-components: aarch64
+//@ revisions: arm64e_apple_tvos
+//@ [arm64e_apple_tvos] compile-flags: --target arm64e-apple-tvos
+//@ [arm64e_apple_tvos] needs-llvm-components: aarch64
 //@ revisions: aarch64_apple_watchos
 //@ [aarch64_apple_watchos] compile-flags: --target aarch64-apple-watchos
 //@ [aarch64_apple_watchos] needs-llvm-components: aarch64
@@ -28,11 +31,9 @@
 //@ [arm64_32_apple_watchos] compile-flags: --target arm64_32-apple-watchos
 //@ [arm64_32_apple_watchos] needs-llvm-components: aarch64
 //@ revisions: aarch64_apple_visionos
-//@ [aarch64_apple_visionos] min-llvm-version: 18
 //@ [aarch64_apple_visionos] compile-flags: --target aarch64-apple-visionos
 //@ [aarch64_apple_visionos] needs-llvm-components: aarch64
 //@ revisions: aarch64_apple_visionos_sim
-//@ [aarch64_apple_visionos_sim] min-llvm-version: 18
 //@ [aarch64_apple_visionos_sim] compile-flags: --target aarch64-apple-visionos-sim
 //@ [aarch64_apple_visionos_sim] needs-llvm-components: aarch64
 //@ revisions: arm64e_apple_darwin
diff --git a/tests/codegen/align-byval.rs b/tests/codegen/align-byval.rs
index 223696229cb..b057147ab13 100644
--- a/tests/codegen/align-byval.rs
+++ b/tests/codegen/align-byval.rs
@@ -1,10 +1,8 @@
 // ignore-tidy-linelength
-//@ revisions:m68k wasm x86_64-linux x86_64-windows i686-linux i686-windows
+//@ revisions:m68k x86_64-linux x86_64-windows i686-linux i686-windows
 
 //@[m68k] compile-flags: --target m68k-unknown-linux-gnu
 //@[m68k] needs-llvm-components: m68k
-//@[wasm] compile-flags: --target wasm32-unknown-emscripten
-//@[wasm] needs-llvm-components: webassembly
 //@[x86_64-linux] compile-flags: --target x86_64-unknown-linux-gnu
 //@[x86_64-linux] needs-llvm-components: x86
 //@[x86_64-windows] compile-flags: --target x86_64-pc-windows-msvc
@@ -15,7 +13,7 @@
 //@[i686-windows] needs-llvm-components: x86
 
 // Tests that `byval` alignment is properly specified (#80127).
-// The only targets that use `byval` are m68k, wasm, x86-64, and x86.
+// The only targets that use `byval` are m68k, x86-64, and x86.
 // Note also that Windows mandates a by-ref ABI here, so it does not use byval.
 
 #![feature(no_core, lang_items)]
@@ -112,9 +110,6 @@ pub unsafe fn call_na1(x: NaturalAlign1) {
     // m68k: [[ALLOCA:%[a-z0-9+]]] = alloca [2 x i8], align 1
     // m68k: call void @natural_align_1({{.*}}byval([2 x i8]) align 1{{.*}} [[ALLOCA]])
 
-    // wasm: [[ALLOCA:%[a-z0-9+]]] = alloca [2 x i8], align 1
-    // 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
@@ -133,7 +128,6 @@ pub unsafe fn call_na2(x: NaturalAlign2) {
     // CHECK: start:
 
     // m68k-NEXT: call void @natural_align_2
-    // wasm-NEXT: call void @natural_align_2
     // x86_64-linux-NEXT: call void @natural_align_2
     // x86_64-windows-NEXT: call void @natural_align_2
 
@@ -204,8 +198,6 @@ pub unsafe fn call_fa16(x: ForceAlign16) {
 extern "C" {
     // m68k: declare void @natural_align_1({{.*}}byval([2 x i8]) 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)
@@ -217,8 +209,6 @@ extern "C" {
 
     // m68k: declare void @natural_align_2({{.*}}byval([34 x i8]) align 2{{.*}})
 
-    // wasm: declare void @natural_align_2({{.*}}byval([34 x i8]) align 2{{.*}})
-
     // x86_64-linux: declare void @natural_align_2({{.*}}byval([34 x i8]) align 2{{.*}})
 
     // x86_64-windows: declare void @natural_align_2(
@@ -232,8 +222,6 @@ extern "C" {
 
     // m68k: declare void @force_align_4({{.*}}byval([20 x i8]) align 4{{.*}})
 
-    // wasm: declare void @force_align_4({{.*}}byval([20 x i8]) align 4{{.*}})
-
     // x86_64-linux: declare void @force_align_4({{.*}}byval([20 x i8]) align 4{{.*}})
 
     // x86_64-windows: declare void @force_align_4(
@@ -247,8 +235,6 @@ extern "C" {
 
     // m68k: declare void @natural_align_8({{.*}}byval([24 x i8]) align 4{{.*}})
 
-    // wasm: declare void @natural_align_8({{.*}}byval([24 x i8]) align 8{{.*}})
-
     // x86_64-linux: declare void @natural_align_8({{.*}}byval([24 x i8]) align 8{{.*}})
 
     // x86_64-windows: declare void @natural_align_8(
@@ -262,8 +248,6 @@ extern "C" {
 
     // m68k: declare void @force_align_8({{.*}}byval([24 x i8]) align 8{{.*}})
 
-    // wasm: declare void @force_align_8({{.*}}byval([24 x i8]) align 8{{.*}})
-
     // x86_64-linux: declare void @force_align_8({{.*}}byval([24 x i8]) align 8{{.*}})
 
     // x86_64-windows: declare void @force_align_8(
@@ -279,8 +263,6 @@ extern "C" {
 
     // m68k: declare void @lower_fa8({{.*}}byval([24 x i8]) align 4{{.*}})
 
-    // wasm: declare void @lower_fa8({{.*}}byval([24 x i8]) align 8{{.*}})
-
     // x86_64-linux: declare void @lower_fa8({{.*}}byval([24 x i8]) align 8{{.*}})
 
     // x86_64-windows: declare void @lower_fa8(
@@ -294,8 +276,6 @@ extern "C" {
 
     // m68k: declare void @wrapped_fa8({{.*}}byval([24 x i8]) align 8{{.*}})
 
-    // wasm: declare void @wrapped_fa8({{.*}}byval([24 x i8]) align 8{{.*}})
-
     // x86_64-linux: declare void @wrapped_fa8({{.*}}byval([24 x i8]) align 8{{.*}})
 
     // x86_64-windows: declare void @wrapped_fa8(
@@ -311,8 +291,6 @@ extern "C" {
 
     // m68k: declare void @transparent_fa8({{.*}}byval([24 x i8]) align 8{{.*}})
 
-    // wasm: declare void @transparent_fa8({{.*}}byval([24 x i8]) align 8{{.*}})
-
     // x86_64-linux: declare void @transparent_fa8({{.*}}byval([24 x i8]) align 8{{.*}})
 
     // x86_64-windows: declare void @transparent_fa8(
@@ -328,8 +306,6 @@ extern "C" {
 
     // m68k: declare void @force_align_16({{.*}}byval([80 x i8]) align 16{{.*}})
 
-    // wasm: declare void @force_align_16({{.*}}byval([80 x i8]) align 16{{.*}})
-
     // x86_64-linux: declare void @force_align_16({{.*}}byval([80 x i8]) align 16{{.*}})
 
     // x86_64-windows: declare void @force_align_16(
diff --git a/tests/codegen/constant-branch.rs b/tests/codegen/constant-branch.rs
index a2710cc4b25..8fc8fb4f57a 100644
--- a/tests/codegen/constant-branch.rs
+++ b/tests/codegen/constant-branch.rs
@@ -7,18 +7,19 @@
 // CHECK-LABEL: @if_bool
 #[no_mangle]
 pub fn if_bool() {
-    // CHECK: br label %{{.+}}
+    // CHECK-NOT: br i1
+    // CHECK-NOT: switch
     _ = if true { 0 } else { 1 };
 
-    // CHECK: br label %{{.+}}
     _ = if false { 0 } else { 1 };
 }
 
 // CHECK-LABEL: @if_constant_int_eq
 #[no_mangle]
 pub fn if_constant_int_eq() {
+    // CHECK-NOT: br i1
+    // CHECK-NOT: switch
     let val = 0;
-    // CHECK: br label %{{.+}}
     _ = if val == 0 { 0 } else { 1 };
 
     // CHECK: br label %{{.+}}
@@ -28,23 +29,20 @@ pub fn if_constant_int_eq() {
 // CHECK-LABEL: @if_constant_match
 #[no_mangle]
 pub fn if_constant_match() {
-    // CHECK: br label %{{.+}}
+    // CHECK-NOT: br i1
+    // CHECK-NOT: switch
     _ = match 1 {
         1 => 2,
         2 => 3,
         _ => 4,
     };
 
-    // CHECK: br label %{{.+}}
     _ = match 1 {
         2 => 3,
         _ => 4,
     };
 
-    // CHECK: br label %[[MINUS1:.+]]
     _ = match -1 {
-        // CHECK: [[MINUS1]]:
-        // CHECK: store i32 1
         -1 => 1,
         _ => 0,
     }
diff --git a/tests/codegen/enum/enum-early-otherwise-branch.rs b/tests/codegen/enum/enum-early-otherwise-branch.rs
index 6c7548912da..07c8aed2624 100644
--- a/tests/codegen/enum/enum-early-otherwise-branch.rs
+++ b/tests/codegen/enum/enum-early-otherwise-branch.rs
@@ -1,5 +1,4 @@
 //@ compile-flags: -O
-//@ min-llvm-version: 18
 
 #![crate_type = "lib"]
 
diff --git a/tests/codegen/issue-97217.rs b/tests/codegen/issue-97217.rs
index ecf1fa1ddb3..ef9acc5fc93 100644
--- a/tests/codegen/issue-97217.rs
+++ b/tests/codegen/issue-97217.rs
@@ -1,5 +1,4 @@
 //@ compile-flags: -C opt-level=3
-//@ min-llvm-version: 17.0.2
 #![crate_type = "lib"]
 
 // Regression test for issue 97217 (the following should result in no allocations)
diff --git a/tests/codegen/issues/issue-110797-enum-jump-same.rs b/tests/codegen/issues/issue-110797-enum-jump-same.rs
index f34b191ac70..f114e0e260e 100644
--- a/tests/codegen/issues/issue-110797-enum-jump-same.rs
+++ b/tests/codegen/issues/issue-110797-enum-jump-same.rs
@@ -1,5 +1,4 @@
 //@ compile-flags: -O
-//@ min-llvm-version: 18
 
 #![crate_type = "lib"]
 
diff --git a/tests/codegen/issues/issue-118392.rs b/tests/codegen/issues/issue-118392.rs
index 2cbb1f8b204..ce2332b4c3c 100644
--- a/tests/codegen/issues/issue-118392.rs
+++ b/tests/codegen/issues/issue-118392.rs
@@ -1,5 +1,4 @@
 //@ compile-flags: -O
-//@ min-llvm-version: 18
 #![crate_type = "lib"]
 
 // CHECK-LABEL: @div2
diff --git a/tests/codegen/issues/issue-44056-macos-tls-align.rs b/tests/codegen/issues/issue-44056-macos-tls-align.rs
deleted file mode 100644
index 972b8490d18..00000000000
--- a/tests/codegen/issues/issue-44056-macos-tls-align.rs
+++ /dev/null
@@ -1,27 +0,0 @@
-//
-//@ only-apple
-//@ compile-flags: -O
-
-#![crate_type = "rlib"]
-#![feature(thread_local)]
-
-// local_unnamed_addr does not appear when std is built with debug assertions.
-// CHECK: @STATIC_VAR_1 = thread_local {{(local_unnamed_addr )?}}global <{ [32 x i8] }> zeroinitializer, section "__DATA,__thread_bss", align 4
-#[no_mangle]
-#[thread_local]
-static mut STATIC_VAR_1: [u32; 8] = [0; 8];
-
-// CHECK: @STATIC_VAR_2 = thread_local {{(local_unnamed_addr )?}}global <{ [32 x i8] }> <{{[^>]*}}>, section "__DATA,__thread_data", align 4
-#[no_mangle]
-#[thread_local]
-static mut STATIC_VAR_2: [u32; 8] = [4; 8];
-
-#[no_mangle]
-pub unsafe fn f(x: &mut [u32; 8]) {
-    std::mem::swap(x, &mut STATIC_VAR_1)
-}
-
-#[no_mangle]
-pub unsafe fn g(x: &mut [u32; 8]) {
-    std::mem::swap(x, &mut STATIC_VAR_2)
-}
diff --git a/tests/codegen/maybeuninit-rvo.rs b/tests/codegen/maybeuninit-rvo.rs
index cc5da39a9ca..db2e33c34bd 100644
--- a/tests/codegen/maybeuninit-rvo.rs
+++ b/tests/codegen/maybeuninit-rvo.rs
@@ -1,6 +1,5 @@
 //@ compile-flags: -O
 //@ needs-unwind
-//@ min-llvm-version: 18
 #![feature(c_unwind)]
 #![crate_type = "lib"]
 
diff --git a/tests/codegen/no-alloca-inside-if-false.rs b/tests/codegen/no-alloca-inside-if-false.rs
new file mode 100644
index 00000000000..a231c7e808a
--- /dev/null
+++ b/tests/codegen/no-alloca-inside-if-false.rs
@@ -0,0 +1,27 @@
+//@ compile-flags: -Cno-prepopulate-passes -Copt-level=0 -Cpanic=abort
+// Check that there's an alloca for the reference and the vector, but nothing else.
+// We use panic=abort because unwinding panics give hint::black_box a cleanup block, which has
+// another alloca.
+
+#![crate_type = "lib"]
+
+#[inline(never)]
+fn test<const SIZE: usize>() {
+    // CHECK-LABEL: no_alloca_inside_if_false::test
+    // CHECK: start:
+    // CHECK-NEXT: alloca [{{12|24}} x i8]
+    // CHECK-NOT: alloca
+    if const { SIZE < 4096 } {
+        let arr = [0u8; SIZE];
+        std::hint::black_box(&arr);
+    } else {
+        let vec = vec![0u8; SIZE];
+        std::hint::black_box(&vec);
+    }
+}
+
+// CHECK-LABEL: @main
+#[no_mangle]
+pub fn main() {
+    test::<8192>();
+}
diff --git a/tests/codegen/option-niche-eq.rs b/tests/codegen/option-niche-eq.rs
index 4d3a7ce3764..caef0598b4b 100644
--- a/tests/codegen/option-niche-eq.rs
+++ b/tests/codegen/option-niche-eq.rs
@@ -1,5 +1,4 @@
 //@ compile-flags: -O -Zmerge-functions=disabled
-//@ min-llvm-version: 18
 #![crate_type = "lib"]
 
 extern crate core;
diff --git a/tests/codegen/repr/transparent-byval-struct-ptr.rs b/tests/codegen/repr/transparent-byval-struct-ptr.rs
index 35b52bee8d9..92ef937d734 100644
--- a/tests/codegen/repr/transparent-byval-struct-ptr.rs
+++ b/tests/codegen/repr/transparent-byval-struct-ptr.rs
@@ -1,4 +1,4 @@
-//@ revisions: i686-linux i686-freebsd x64-linux x64-apple wasm32
+//@ revisions: i686-linux i686-freebsd x64-linux x64-apple
 //@ compile-flags: -O -C no-prepopulate-passes
 
 //@[i686-linux] compile-flags: --target i686-unknown-linux-gnu
@@ -9,8 +9,6 @@
 //@[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
diff --git a/tests/codegen/repr/transparent-opaque-ptr.rs b/tests/codegen/repr/transparent-opaque-ptr.rs
index a84e95627c4..4e7b38bca39 100644
--- a/tests/codegen/repr/transparent-opaque-ptr.rs
+++ b/tests/codegen/repr/transparent-opaque-ptr.rs
@@ -1,10 +1,12 @@
-//@ revisions: aarch64-linux aarch64-darwin
+//@ revisions: aarch64-linux aarch64-darwin wasm32-wasi
 //@ compile-flags: -O -C no-prepopulate-passes
 
 //@[aarch64-linux] compile-flags: --target aarch64-unknown-linux-gnu
 //@[aarch64-linux] needs-llvm-components: aarch64
 //@[aarch64-darwin] compile-flags: --target aarch64-apple-darwin
 //@[aarch64-darwin] needs-llvm-components: aarch64
+//@[wasm32-wasi] compile-flags: --target wasm32-wasi
+//@[wasm32-wasi] needs-llvm-components: webassembly
 
 // See ./transparent.rs
 // Some platforms pass large aggregates using immediate arrays in LLVMIR
diff --git a/tests/codegen/slice-pointer-nonnull-unwrap.rs b/tests/codegen/slice-pointer-nonnull-unwrap.rs
index 2c4a959685f..202edb98c73 100644
--- a/tests/codegen/slice-pointer-nonnull-unwrap.rs
+++ b/tests/codegen/slice-pointer-nonnull-unwrap.rs
@@ -1,5 +1,4 @@
 //@ compile-flags: -O
-//@ min-llvm-version: 18
 #![crate_type = "lib"]
 
 use std::ptr::NonNull;
diff --git a/tests/codegen/unwind-landingpad-cold.rs b/tests/codegen/unwind-landingpad-cold.rs
index fa200bc300c..fb095e04650 100644
--- a/tests/codegen/unwind-landingpad-cold.rs
+++ b/tests/codegen/unwind-landingpad-cold.rs
@@ -1,6 +1,5 @@
 //@ compile-flags: -Cno-prepopulate-passes
 //@ needs-unwind
-//@ min-llvm-version: 17.0.2
 #![crate_type = "lib"]
 
 // This test checks that drop calls in unwind landing pads
diff --git a/tests/codegen/unwind-landingpad-inline.rs b/tests/codegen/unwind-landingpad-inline.rs
index 77ef8d2a5fe..920774b3402 100644
--- a/tests/codegen/unwind-landingpad-inline.rs
+++ b/tests/codegen/unwind-landingpad-inline.rs
@@ -1,4 +1,3 @@
-//@ min-llvm-version: 17.0.2
 //@ compile-flags: -Copt-level=3
 #![crate_type = "lib"]
 
diff --git a/tests/coverage/mcdc/condition-limit.cov-map b/tests/coverage/mcdc/condition-limit.cov-map
index b565353572a..b4447a33691 100644
--- a/tests/coverage/mcdc/condition-limit.cov-map
+++ b/tests/coverage/mcdc/condition-limit.cov-map
@@ -1,5 +1,5 @@
 Function name: condition_limit::bad
-Raw bytes (204): 0x[01, 01, 2c, 01, 05, 05, 1d, 05, 1d, 7a, 19, 05, 1d, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 21, 9b, 01, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 11, 01, 15, 01, 03, 09, 20, 05, 02, 03, 08, 00, 09, 05, 00, 0d, 00, 0e, 20, 7a, 1d, 00, 0d, 00, 0e, 7a, 00, 12, 00, 13, 20, 76, 19, 00, 12, 00, 13, 76, 00, 17, 00, 18, 20, 72, 15, 00, 17, 00, 18, 72, 00, 1c, 00, 1d, 20, 6e, 11, 00, 1c, 00, 1d, 6e, 00, 21, 00, 22, 20, 6a, 0d, 00, 21, 00, 22, 6a, 00, 26, 00, 27, 20, 21, 09, 00, 26, 00, 27, 21, 00, 28, 02, 06, 9b, 01, 02, 06, 00, 07, 97, 01, 01, 01, 00, 02]
+Raw bytes (204): 0x[01, 01, 2c, 01, 05, 05, 1d, 05, 1d, 7a, 19, 05, 1d, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 6e, 0d, 72, 11, 76, 15, 7a, 19, 05, 1d, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 21, 9b, 01, 9f, 01, 02, a3, 01, 1d, a7, 01, 19, ab, 01, 15, af, 01, 11, 09, 0d, 11, 01, 14, 01, 03, 09, 20, 05, 02, 03, 08, 00, 09, 05, 00, 0d, 00, 0e, 20, 7a, 1d, 00, 0d, 00, 0e, 7a, 00, 12, 00, 13, 20, 76, 19, 00, 12, 00, 13, 76, 00, 17, 00, 18, 20, 72, 15, 00, 17, 00, 18, 72, 00, 1c, 00, 1d, 20, 6e, 11, 00, 1c, 00, 1d, 6e, 00, 21, 00, 22, 20, 6a, 0d, 00, 21, 00, 22, 6a, 00, 26, 00, 27, 20, 21, 09, 00, 26, 00, 27, 21, 00, 28, 02, 06, 9b, 01, 02, 06, 00, 07, 97, 01, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 44
@@ -48,7 +48,7 @@ Number of expressions: 44
 - expression 42 operands: lhs = Expression(43, Add), rhs = Counter(4)
 - expression 43 operands: lhs = Counter(2), rhs = Counter(3)
 Number of file 0 mappings: 17
-- Code(Counter(0)) at (prev + 21, 1) to (start + 3, 9)
+- Code(Counter(0)) at (prev + 20, 1) to (start + 3, 9)
 - Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 3, 8) to (start + 0, 9)
     true  = c1
     false = (c0 - c1)
@@ -88,7 +88,7 @@ Number of file 0 mappings: 17
     = (c8 + ((((((c2 + c3) + c4) + c5) + c6) + c7) + (c0 - c1)))
 
 Function name: condition_limit::good
-Raw bytes (180): 0x[01, 01, 20, 01, 05, 05, 19, 05, 19, 52, 15, 05, 19, 52, 15, 05, 19, 4e, 11, 52, 15, 05, 19, 4e, 11, 52, 15, 05, 19, 4a, 0d, 4e, 11, 52, 15, 05, 19, 4a, 0d, 4e, 11, 52, 15, 05, 19, 73, 02, 77, 19, 7b, 15, 7f, 11, 09, 0d, 1d, 6f, 73, 02, 77, 19, 7b, 15, 7f, 11, 09, 0d, 10, 01, 0d, 01, 03, 09, 28, 00, 06, 03, 08, 00, 22, 30, 05, 02, 01, 06, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 52, 19, 06, 05, 00, 00, 0d, 00, 0e, 52, 00, 12, 00, 13, 30, 4e, 15, 05, 04, 00, 00, 12, 00, 13, 4e, 00, 17, 00, 18, 30, 4a, 11, 04, 03, 00, 00, 17, 00, 18, 4a, 00, 1c, 00, 1d, 30, 46, 0d, 03, 02, 00, 00, 1c, 00, 1d, 46, 00, 21, 00, 22, 30, 1d, 09, 02, 00, 00, 00, 21, 00, 22, 1d, 00, 23, 02, 06, 6f, 02, 06, 00, 07, 6b, 01, 01, 00, 02]
+Raw bytes (180): 0x[01, 01, 20, 01, 05, 05, 19, 05, 19, 52, 15, 05, 19, 52, 15, 05, 19, 4e, 11, 52, 15, 05, 19, 4e, 11, 52, 15, 05, 19, 4a, 0d, 4e, 11, 52, 15, 05, 19, 4a, 0d, 4e, 11, 52, 15, 05, 19, 73, 02, 77, 19, 7b, 15, 7f, 11, 09, 0d, 1d, 6f, 73, 02, 77, 19, 7b, 15, 7f, 11, 09, 0d, 10, 01, 0c, 01, 03, 09, 28, 00, 06, 03, 08, 00, 22, 30, 05, 02, 01, 06, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 52, 19, 06, 05, 00, 00, 0d, 00, 0e, 52, 00, 12, 00, 13, 30, 4e, 15, 05, 04, 00, 00, 12, 00, 13, 4e, 00, 17, 00, 18, 30, 4a, 11, 04, 03, 00, 00, 17, 00, 18, 4a, 00, 1c, 00, 1d, 30, 46, 0d, 03, 02, 00, 00, 1c, 00, 1d, 46, 00, 21, 00, 22, 30, 1d, 09, 02, 00, 00, 00, 21, 00, 22, 1d, 00, 23, 02, 06, 6f, 02, 06, 00, 07, 6b, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 32
@@ -125,7 +125,7 @@ Number of expressions: 32
 - expression 30 operands: lhs = Expression(31, Add), rhs = Counter(4)
 - expression 31 operands: lhs = Counter(2), rhs = Counter(3)
 Number of file 0 mappings: 16
-- Code(Counter(0)) at (prev + 13, 1) to (start + 3, 9)
+- Code(Counter(0)) at (prev + 12, 1) to (start + 3, 9)
 - MCDCDecision { bitmap_idx: 0, conditions_num: 6 } at (prev + 3, 8) to (start + 0, 34)
 - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 6, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
     true  = c1
diff --git a/tests/coverage/mcdc/condition-limit.coverage b/tests/coverage/mcdc/condition-limit.coverage
index 81e832d6a49..ae8596bb961 100644
--- a/tests/coverage/mcdc/condition-limit.coverage
+++ b/tests/coverage/mcdc/condition-limit.coverage
@@ -1,6 +1,5 @@
    LL|       |#![feature(coverage_attribute)]
    LL|       |//@ edition: 2021
-   LL|       |//@ min-llvm-version: 18
    LL|       |//@ ignore-llvm-version: 19 - 99
    LL|       |//@ compile-flags: -Zcoverage-options=mcdc
    LL|       |//@ llvm-cov-flags: --show-branches=count --show-mcdc
diff --git a/tests/coverage/mcdc/condition-limit.rs b/tests/coverage/mcdc/condition-limit.rs
index 2ff46b11a16..0d8546b01cd 100644
--- a/tests/coverage/mcdc/condition-limit.rs
+++ b/tests/coverage/mcdc/condition-limit.rs
@@ -1,6 +1,5 @@
 #![feature(coverage_attribute)]
 //@ edition: 2021
-//@ min-llvm-version: 18
 //@ ignore-llvm-version: 19 - 99
 //@ compile-flags: -Zcoverage-options=mcdc
 //@ llvm-cov-flags: --show-branches=count --show-mcdc
diff --git a/tests/coverage/mcdc/if.cov-map b/tests/coverage/mcdc/if.cov-map
index ea8dedb0ac3..9a7d15f700d 100644
--- a/tests/coverage/mcdc/if.cov-map
+++ b/tests/coverage/mcdc/if.cov-map
@@ -1,5 +1,5 @@
 Function name: if::mcdc_check_a
-Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 10, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
+Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 0f, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 4
@@ -8,7 +8,7 @@ Number of expressions: 4
 - expression 2 operands: lhs = Counter(3), rhs = Expression(3, Add)
 - expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
 Number of file 0 mappings: 8
-- Code(Counter(0)) at (prev + 16, 1) to (start + 1, 9)
+- Code(Counter(0)) at (prev + 15, 1) to (start + 1, 9)
 - MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
 - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
     true  = c1
@@ -24,7 +24,7 @@ Number of file 0 mappings: 8
     = (c3 + (c2 + (c0 - c1)))
 
 Function name: if::mcdc_check_b
-Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 18, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
+Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 17, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 4
@@ -33,7 +33,7 @@ Number of expressions: 4
 - expression 2 operands: lhs = Counter(3), rhs = Expression(3, Add)
 - expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
 Number of file 0 mappings: 8
-- Code(Counter(0)) at (prev + 24, 1) to (start + 1, 9)
+- Code(Counter(0)) at (prev + 23, 1) to (start + 1, 9)
 - MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
 - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
     true  = c1
@@ -49,7 +49,7 @@ Number of file 0 mappings: 8
     = (c3 + (c2 + (c0 - c1)))
 
 Function name: if::mcdc_check_both
-Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 20, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
+Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 1f, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 4
@@ -58,7 +58,7 @@ Number of expressions: 4
 - expression 2 operands: lhs = Counter(3), rhs = Expression(3, Add)
 - expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
 Number of file 0 mappings: 8
-- Code(Counter(0)) at (prev + 32, 1) to (start + 1, 9)
+- Code(Counter(0)) at (prev + 31, 1) to (start + 1, 9)
 - MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
 - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
     true  = c1
@@ -74,7 +74,7 @@ Number of file 0 mappings: 8
     = (c3 + (c2 + (c0 - c1)))
 
 Function name: if::mcdc_check_neither
-Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 08, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
+Raw bytes (64): 0x[01, 01, 04, 01, 05, 09, 02, 0d, 0f, 09, 02, 08, 01, 07, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0d, 00, 0e, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 0e, 0d, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 4
@@ -83,7 +83,7 @@ Number of expressions: 4
 - expression 2 operands: lhs = Counter(3), rhs = Expression(3, Add)
 - expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
 Number of file 0 mappings: 8
-- Code(Counter(0)) at (prev + 8, 1) to (start + 1, 9)
+- Code(Counter(0)) at (prev + 7, 1) to (start + 1, 9)
 - MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
 - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
     true  = c1
@@ -99,7 +99,7 @@ Number of file 0 mappings: 8
     = (c3 + (c2 + (c0 - c1)))
 
 Function name: if::mcdc_check_not_tree_decision
-Raw bytes (87): 0x[01, 01, 08, 01, 05, 02, 09, 05, 09, 0d, 1e, 02, 09, 11, 1b, 0d, 1e, 02, 09, 0a, 01, 32, 01, 03, 0a, 28, 00, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 03, 00, 09, 00, 0a, 02, 00, 0e, 00, 0f, 30, 09, 1e, 03, 02, 00, 00, 0e, 00, 0f, 0b, 00, 14, 00, 15, 30, 11, 0d, 02, 00, 00, 00, 14, 00, 15, 11, 00, 16, 02, 06, 1b, 02, 0c, 02, 06, 17, 03, 01, 00, 02]
+Raw bytes (87): 0x[01, 01, 08, 01, 05, 02, 09, 05, 09, 0d, 1e, 02, 09, 11, 1b, 0d, 1e, 02, 09, 0a, 01, 31, 01, 03, 0a, 28, 00, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 03, 00, 09, 00, 0a, 02, 00, 0e, 00, 0f, 30, 09, 1e, 03, 02, 00, 00, 0e, 00, 0f, 0b, 00, 14, 00, 15, 30, 11, 0d, 02, 00, 00, 00, 14, 00, 15, 11, 00, 16, 02, 06, 1b, 02, 0c, 02, 06, 17, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 8
@@ -112,7 +112,7 @@ Number of expressions: 8
 - expression 6 operands: lhs = Counter(3), rhs = Expression(7, Sub)
 - expression 7 operands: lhs = Expression(0, Sub), rhs = Counter(2)
 Number of file 0 mappings: 10
-- Code(Counter(0)) at (prev + 50, 1) to (start + 3, 10)
+- Code(Counter(0)) at (prev + 49, 1) to (start + 3, 10)
 - MCDCDecision { bitmap_idx: 0, conditions_num: 3 } at (prev + 3, 8) to (start + 0, 21)
 - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 3 } at (prev + 0, 9) to (start + 0, 10)
     true  = c1
@@ -134,7 +134,7 @@ Number of file 0 mappings: 10
     = (c4 + (c3 + ((c0 - c1) - c2)))
 
 Function name: if::mcdc_check_tree_decision
-Raw bytes (87): 0x[01, 01, 08, 01, 05, 05, 0d, 05, 0d, 0d, 11, 09, 02, 1b, 1f, 0d, 11, 09, 02, 0a, 01, 28, 01, 03, 09, 28, 00, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0e, 00, 0f, 30, 0d, 0a, 02, 00, 03, 00, 0e, 00, 0f, 0a, 00, 13, 00, 14, 30, 11, 09, 03, 00, 00, 00, 13, 00, 14, 1b, 00, 16, 02, 06, 1f, 02, 0c, 02, 06, 17, 03, 01, 00, 02]
+Raw bytes (87): 0x[01, 01, 08, 01, 05, 05, 0d, 05, 0d, 0d, 11, 09, 02, 1b, 1f, 0d, 11, 09, 02, 0a, 01, 27, 01, 03, 09, 28, 00, 03, 03, 08, 00, 15, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 05, 00, 0e, 00, 0f, 30, 0d, 0a, 02, 00, 03, 00, 0e, 00, 0f, 0a, 00, 13, 00, 14, 30, 11, 09, 03, 00, 00, 00, 13, 00, 14, 1b, 00, 16, 02, 06, 1f, 02, 0c, 02, 06, 17, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 8
@@ -147,7 +147,7 @@ Number of expressions: 8
 - expression 6 operands: lhs = Counter(3), rhs = Counter(4)
 - expression 7 operands: lhs = Counter(2), rhs = Expression(0, Sub)
 Number of file 0 mappings: 10
-- Code(Counter(0)) at (prev + 40, 1) to (start + 3, 9)
+- Code(Counter(0)) at (prev + 39, 1) to (start + 3, 9)
 - MCDCDecision { bitmap_idx: 0, conditions_num: 3 } at (prev + 3, 8) to (start + 0, 21)
 - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
     true  = c1
@@ -169,7 +169,7 @@ Number of file 0 mappings: 10
     = ((c3 + c4) + (c2 + (c0 - c1)))
 
 Function name: if::mcdc_nested_if
-Raw bytes (124): 0x[01, 01, 0d, 01, 05, 02, 09, 05, 09, 1b, 15, 05, 09, 1b, 15, 05, 09, 11, 15, 02, 09, 2b, 32, 0d, 2f, 11, 15, 02, 09, 0e, 01, 3c, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 00, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 30, 09, 32, 02, 00, 00, 00, 0d, 00, 0e, 1b, 01, 09, 01, 0d, 28, 01, 02, 01, 0c, 00, 12, 30, 16, 15, 01, 02, 00, 00, 0c, 00, 0d, 16, 00, 11, 00, 12, 30, 0d, 11, 02, 00, 00, 00, 11, 00, 12, 0d, 00, 13, 02, 0a, 2f, 02, 0a, 00, 0b, 32, 01, 0c, 02, 06, 27, 03, 01, 00, 02]
+Raw bytes (124): 0x[01, 01, 0d, 01, 05, 02, 09, 05, 09, 1b, 15, 05, 09, 1b, 15, 05, 09, 11, 15, 02, 09, 2b, 32, 0d, 2f, 11, 15, 02, 09, 0e, 01, 3b, 01, 01, 09, 28, 00, 02, 01, 08, 00, 0e, 30, 05, 02, 01, 00, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 30, 09, 32, 02, 00, 00, 00, 0d, 00, 0e, 1b, 01, 09, 01, 0d, 28, 01, 02, 01, 0c, 00, 12, 30, 16, 15, 01, 02, 00, 00, 0c, 00, 0d, 16, 00, 11, 00, 12, 30, 0d, 11, 02, 00, 00, 00, 11, 00, 12, 0d, 00, 13, 02, 0a, 2f, 02, 0a, 00, 0b, 32, 01, 0c, 02, 06, 27, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 13
@@ -187,7 +187,7 @@ Number of expressions: 13
 - expression 11 operands: lhs = Counter(4), rhs = Counter(5)
 - expression 12 operands: lhs = Expression(0, Sub), rhs = Counter(2)
 Number of file 0 mappings: 14
-- Code(Counter(0)) at (prev + 60, 1) to (start + 1, 9)
+- Code(Counter(0)) at (prev + 59, 1) to (start + 1, 9)
 - MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 14)
 - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 8) to (start + 0, 9)
     true  = c1
diff --git a/tests/coverage/mcdc/if.coverage b/tests/coverage/mcdc/if.coverage
index dc93319950b..d71de28c6f6 100644
--- a/tests/coverage/mcdc/if.coverage
+++ b/tests/coverage/mcdc/if.coverage
@@ -1,6 +1,5 @@
    LL|       |#![feature(coverage_attribute)]
    LL|       |//@ edition: 2021
-   LL|       |//@ min-llvm-version: 18
    LL|       |//@ ignore-llvm-version: 19 - 99
    LL|       |//@ compile-flags: -Zcoverage-options=mcdc
    LL|       |//@ llvm-cov-flags: --show-branches=count --show-mcdc
diff --git a/tests/coverage/mcdc/if.rs b/tests/coverage/mcdc/if.rs
index 6f589659a3d..17247f5e0c1 100644
--- a/tests/coverage/mcdc/if.rs
+++ b/tests/coverage/mcdc/if.rs
@@ -1,6 +1,5 @@
 #![feature(coverage_attribute)]
 //@ edition: 2021
-//@ min-llvm-version: 18
 //@ ignore-llvm-version: 19 - 99
 //@ compile-flags: -Zcoverage-options=mcdc
 //@ llvm-cov-flags: --show-branches=count --show-mcdc
diff --git a/tests/coverage/mcdc/inlined_expressions.cov-map b/tests/coverage/mcdc/inlined_expressions.cov-map
index 8bb488c0dc0..09b7291c964 100644
--- a/tests/coverage/mcdc/inlined_expressions.cov-map
+++ b/tests/coverage/mcdc/inlined_expressions.cov-map
@@ -1,5 +1,5 @@
 Function name: inlined_expressions::inlined_instance
-Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 09, 01, 01, 06, 28, 00, 02, 01, 05, 00, 0b, 30, 05, 02, 01, 02, 00, 00, 05, 00, 06, 05, 00, 0a, 00, 0b, 30, 09, 0d, 02, 00, 00, 00, 0a, 00, 0b, 07, 01, 01, 00, 02]
+Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 08, 01, 01, 06, 28, 00, 02, 01, 05, 00, 0b, 30, 05, 02, 01, 02, 00, 00, 05, 00, 06, 05, 00, 0a, 00, 0b, 30, 09, 0d, 02, 00, 00, 00, 0a, 00, 0b, 07, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 3
@@ -7,7 +7,7 @@ Number of expressions: 3
 - expression 1 operands: lhs = Expression(2, Add), rhs = Expression(0, Sub)
 - expression 2 operands: lhs = Counter(2), rhs = Counter(3)
 Number of file 0 mappings: 6
-- Code(Counter(0)) at (prev + 9, 1) to (start + 1, 6)
+- Code(Counter(0)) at (prev + 8, 1) to (start + 1, 6)
 - MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 5) to (start + 0, 11)
 - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 5) to (start + 0, 6)
     true  = c1
diff --git a/tests/coverage/mcdc/inlined_expressions.coverage b/tests/coverage/mcdc/inlined_expressions.coverage
index 4e4800310c9..af0b78477d4 100644
--- a/tests/coverage/mcdc/inlined_expressions.coverage
+++ b/tests/coverage/mcdc/inlined_expressions.coverage
@@ -1,6 +1,5 @@
    LL|       |#![feature(coverage_attribute)]
    LL|       |//@ edition: 2021
-   LL|       |//@ min-llvm-version: 18
    LL|       |//@ ignore-llvm-version: 19 - 99
    LL|       |//@ compile-flags: -Zcoverage-options=mcdc -Copt-level=z -Cllvm-args=--inline-threshold=0
    LL|       |//@ llvm-cov-flags: --show-branches=count --show-mcdc
diff --git a/tests/coverage/mcdc/inlined_expressions.rs b/tests/coverage/mcdc/inlined_expressions.rs
index fc1e4dae37c..5c1fde6681a 100644
--- a/tests/coverage/mcdc/inlined_expressions.rs
+++ b/tests/coverage/mcdc/inlined_expressions.rs
@@ -1,6 +1,5 @@
 #![feature(coverage_attribute)]
 //@ edition: 2021
-//@ min-llvm-version: 18
 //@ ignore-llvm-version: 19 - 99
 //@ compile-flags: -Zcoverage-options=mcdc -Copt-level=z -Cllvm-args=--inline-threshold=0
 //@ llvm-cov-flags: --show-branches=count --show-mcdc
diff --git a/tests/coverage/mcdc/nested_if.cov-map b/tests/coverage/mcdc/nested_if.cov-map
index 0bd2aef814c..adeb6cbc1fb 100644
--- a/tests/coverage/mcdc/nested_if.cov-map
+++ b/tests/coverage/mcdc/nested_if.cov-map
@@ -1,5 +1,5 @@
 Function name: nested_if::doubly_nested_if_in_condition
-Raw bytes (168): 0x[01, 01, 0e, 01, 05, 05, 11, 05, 11, 26, 19, 05, 11, 19, 1d, 19, 1d, 1d, 22, 26, 19, 05, 11, 11, 15, 09, 02, 0d, 37, 09, 02, 14, 01, 10, 01, 01, 09, 28, 02, 02, 01, 08, 00, 4e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4e, 05, 00, 10, 00, 11, 28, 01, 02, 00, 10, 00, 36, 30, 11, 26, 01, 00, 02, 00, 10, 00, 11, 30, 15, 21, 02, 00, 00, 00, 15, 00, 36, 26, 00, 18, 00, 19, 28, 00, 02, 00, 18, 00, 1e, 30, 19, 22, 01, 02, 00, 00, 18, 00, 19, 19, 00, 1d, 00, 1e, 30, 1a, 1d, 02, 00, 00, 00, 1d, 00, 1e, 1a, 00, 21, 00, 25, 1f, 00, 2f, 00, 34, 2b, 00, 39, 00, 3e, 21, 00, 48, 00, 4c, 0d, 00, 4f, 02, 06, 37, 02, 0c, 02, 06, 33, 03, 01, 00, 02]
+Raw bytes (168): 0x[01, 01, 0e, 01, 05, 05, 11, 05, 11, 26, 19, 05, 11, 19, 1d, 19, 1d, 1d, 22, 26, 19, 05, 11, 11, 15, 09, 02, 0d, 37, 09, 02, 14, 01, 0f, 01, 01, 09, 28, 02, 02, 01, 08, 00, 4e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4e, 05, 00, 10, 00, 11, 28, 01, 02, 00, 10, 00, 36, 30, 11, 26, 01, 00, 02, 00, 10, 00, 11, 30, 15, 21, 02, 00, 00, 00, 15, 00, 36, 26, 00, 18, 00, 19, 28, 00, 02, 00, 18, 00, 1e, 30, 19, 22, 01, 02, 00, 00, 18, 00, 19, 19, 00, 1d, 00, 1e, 30, 1a, 1d, 02, 00, 00, 00, 1d, 00, 1e, 1a, 00, 21, 00, 25, 1f, 00, 2f, 00, 34, 2b, 00, 39, 00, 3e, 21, 00, 48, 00, 4c, 0d, 00, 4f, 02, 06, 37, 02, 0c, 02, 06, 33, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 14
@@ -18,7 +18,7 @@ Number of expressions: 14
 - expression 12 operands: lhs = Counter(3), rhs = Expression(13, Add)
 - expression 13 operands: lhs = Counter(2), rhs = Expression(0, Sub)
 Number of file 0 mappings: 20
-- Code(Counter(0)) at (prev + 16, 1) to (start + 1, 9)
+- Code(Counter(0)) at (prev + 15, 1) to (start + 1, 9)
 - MCDCDecision { bitmap_idx: 2, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 78)
 - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
     true  = c1
@@ -58,7 +58,7 @@ Number of file 0 mappings: 20
     = (c3 + (c2 + (c0 - c1)))
 
 Function name: nested_if::nested_if_in_condition
-Raw bytes (120): 0x[01, 01, 0b, 01, 05, 05, 11, 05, 11, 1e, 15, 05, 11, 11, 15, 1e, 15, 05, 11, 09, 02, 0d, 2b, 09, 02, 0e, 01, 08, 01, 01, 09, 28, 01, 02, 01, 08, 00, 2e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 2e, 05, 00, 10, 00, 11, 28, 00, 02, 00, 10, 00, 16, 30, 11, 1e, 01, 00, 02, 00, 10, 00, 11, 1e, 00, 15, 00, 16, 30, 15, 1a, 02, 00, 00, 00, 15, 00, 16, 17, 00, 19, 00, 1d, 1a, 00, 27, 00, 2c, 0d, 00, 2f, 02, 06, 2b, 02, 0c, 02, 06, 27, 03, 01, 00, 02]
+Raw bytes (120): 0x[01, 01, 0b, 01, 05, 05, 11, 05, 11, 1e, 15, 05, 11, 11, 15, 1e, 15, 05, 11, 09, 02, 0d, 2b, 09, 02, 0e, 01, 07, 01, 01, 09, 28, 01, 02, 01, 08, 00, 2e, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 2e, 05, 00, 10, 00, 11, 28, 00, 02, 00, 10, 00, 16, 30, 11, 1e, 01, 00, 02, 00, 10, 00, 11, 1e, 00, 15, 00, 16, 30, 15, 1a, 02, 00, 00, 00, 15, 00, 16, 17, 00, 19, 00, 1d, 1a, 00, 27, 00, 2c, 0d, 00, 2f, 02, 06, 2b, 02, 0c, 02, 06, 27, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 11
@@ -74,7 +74,7 @@ Number of expressions: 11
 - expression 9 operands: lhs = Counter(3), rhs = Expression(10, Add)
 - expression 10 operands: lhs = Counter(2), rhs = Expression(0, Sub)
 Number of file 0 mappings: 14
-- Code(Counter(0)) at (prev + 8, 1) to (start + 1, 9)
+- Code(Counter(0)) at (prev + 7, 1) to (start + 1, 9)
 - MCDCDecision { bitmap_idx: 1, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 46)
 - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
     true  = c1
@@ -103,7 +103,7 @@ Number of file 0 mappings: 14
     = (c3 + (c2 + (c0 - c1)))
 
 Function name: nested_if::nested_in_then_block_in_condition
-Raw bytes (176): 0x[01, 01, 12, 01, 05, 05, 11, 05, 11, 3a, 15, 05, 11, 11, 15, 33, 19, 11, 15, 19, 1d, 19, 1d, 1d, 2e, 33, 19, 11, 15, 3a, 15, 05, 11, 09, 02, 0d, 47, 09, 02, 14, 01, 23, 01, 01, 09, 28, 02, 02, 01, 08, 00, 4b, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4b, 05, 00, 10, 00, 11, 28, 00, 02, 00, 10, 00, 16, 30, 11, 3a, 01, 00, 02, 00, 10, 00, 11, 3a, 00, 15, 00, 16, 30, 15, 36, 02, 00, 00, 00, 15, 00, 16, 33, 00, 1c, 00, 1d, 28, 01, 02, 00, 1c, 00, 22, 30, 19, 2e, 01, 02, 00, 00, 1c, 00, 1d, 19, 00, 21, 00, 22, 30, 26, 1d, 02, 00, 00, 00, 21, 00, 22, 26, 00, 25, 00, 29, 2b, 00, 33, 00, 38, 36, 00, 44, 00, 49, 0d, 00, 4c, 02, 06, 47, 02, 0c, 02, 06, 43, 03, 01, 00, 02]
+Raw bytes (176): 0x[01, 01, 12, 01, 05, 05, 11, 05, 11, 3a, 15, 05, 11, 11, 15, 33, 19, 11, 15, 19, 1d, 19, 1d, 1d, 2e, 33, 19, 11, 15, 3a, 15, 05, 11, 09, 02, 0d, 47, 09, 02, 14, 01, 22, 01, 01, 09, 28, 02, 02, 01, 08, 00, 4b, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 4b, 05, 00, 10, 00, 11, 28, 00, 02, 00, 10, 00, 16, 30, 11, 3a, 01, 00, 02, 00, 10, 00, 11, 3a, 00, 15, 00, 16, 30, 15, 36, 02, 00, 00, 00, 15, 00, 16, 33, 00, 1c, 00, 1d, 28, 01, 02, 00, 1c, 00, 22, 30, 19, 2e, 01, 02, 00, 00, 1c, 00, 1d, 19, 00, 21, 00, 22, 30, 26, 1d, 02, 00, 00, 00, 21, 00, 22, 26, 00, 25, 00, 29, 2b, 00, 33, 00, 38, 36, 00, 44, 00, 49, 0d, 00, 4c, 02, 06, 47, 02, 0c, 02, 06, 43, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 18
@@ -126,7 +126,7 @@ Number of expressions: 18
 - expression 16 operands: lhs = Counter(3), rhs = Expression(17, Add)
 - expression 17 operands: lhs = Counter(2), rhs = Expression(0, Sub)
 Number of file 0 mappings: 20
-- Code(Counter(0)) at (prev + 35, 1) to (start + 1, 9)
+- Code(Counter(0)) at (prev + 34, 1) to (start + 1, 9)
 - MCDCDecision { bitmap_idx: 2, conditions_num: 2 } at (prev + 1, 8) to (start + 0, 75)
 - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
     true  = c1
@@ -167,7 +167,7 @@ Number of file 0 mappings: 20
     = (c3 + (c2 + (c0 - c1)))
 
 Function name: nested_if::nested_single_condition_decision
-Raw bytes (85): 0x[01, 01, 06, 01, 05, 05, 11, 05, 11, 09, 02, 0d, 17, 09, 02, 0b, 01, 18, 01, 04, 09, 28, 00, 02, 04, 08, 00, 29, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 29, 05, 00, 10, 00, 11, 20, 11, 0a, 00, 10, 00, 11, 11, 00, 14, 00, 19, 0a, 00, 23, 00, 27, 0d, 00, 2a, 02, 06, 17, 02, 0c, 02, 06, 13, 03, 01, 00, 02]
+Raw bytes (85): 0x[01, 01, 06, 01, 05, 05, 11, 05, 11, 09, 02, 0d, 17, 09, 02, 0b, 01, 17, 01, 04, 09, 28, 00, 02, 04, 08, 00, 29, 30, 05, 02, 01, 02, 00, 00, 08, 00, 09, 30, 0d, 09, 02, 00, 00, 00, 0d, 00, 29, 05, 00, 10, 00, 11, 20, 11, 0a, 00, 10, 00, 11, 11, 00, 14, 00, 19, 0a, 00, 23, 00, 27, 0d, 00, 2a, 02, 06, 17, 02, 0c, 02, 06, 13, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 6
@@ -178,7 +178,7 @@ Number of expressions: 6
 - expression 4 operands: lhs = Counter(3), rhs = Expression(5, Add)
 - expression 5 operands: lhs = Counter(2), rhs = Expression(0, Sub)
 Number of file 0 mappings: 11
-- Code(Counter(0)) at (prev + 24, 1) to (start + 4, 9)
+- Code(Counter(0)) at (prev + 23, 1) to (start + 4, 9)
 - MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 4, 8) to (start + 0, 41)
 - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 8) to (start + 0, 9)
     true  = c1
diff --git a/tests/coverage/mcdc/nested_if.coverage b/tests/coverage/mcdc/nested_if.coverage
index 916bb94745d..37aa33d5c57 100644
--- a/tests/coverage/mcdc/nested_if.coverage
+++ b/tests/coverage/mcdc/nested_if.coverage
@@ -1,6 +1,5 @@
    LL|       |#![feature(coverage_attribute)]
    LL|       |//@ edition: 2021
-   LL|       |//@ min-llvm-version: 18
    LL|       |//@ ignore-llvm-version: 19 - 99
    LL|       |//@ compile-flags: -Zcoverage-options=mcdc
    LL|       |//@ llvm-cov-flags: --show-branches=count --show-mcdc
diff --git a/tests/coverage/mcdc/nested_if.rs b/tests/coverage/mcdc/nested_if.rs
index f9ce7a0bc25..1443ccc23ab 100644
--- a/tests/coverage/mcdc/nested_if.rs
+++ b/tests/coverage/mcdc/nested_if.rs
@@ -1,6 +1,5 @@
 #![feature(coverage_attribute)]
 //@ edition: 2021
-//@ min-llvm-version: 18
 //@ ignore-llvm-version: 19 - 99
 //@ compile-flags: -Zcoverage-options=mcdc
 //@ llvm-cov-flags: --show-branches=count --show-mcdc
diff --git a/tests/coverage/mcdc/non_control_flow.cov-map b/tests/coverage/mcdc/non_control_flow.cov-map
index 0c6928b684d..f8576831e75 100644
--- a/tests/coverage/mcdc/non_control_flow.cov-map
+++ b/tests/coverage/mcdc/non_control_flow.cov-map
@@ -1,5 +1,5 @@
 Function name: non_control_flow::assign_3
-Raw bytes (89): 0x[01, 01, 09, 05, 07, 0b, 11, 09, 0d, 01, 05, 01, 05, 22, 11, 01, 05, 22, 11, 01, 05, 0a, 01, 17, 01, 00, 28, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 03, 00, 0d, 00, 18, 30, 05, 22, 01, 00, 02, 00, 0d, 00, 0e, 22, 00, 12, 00, 13, 30, 1e, 11, 02, 03, 00, 00, 12, 00, 13, 1e, 00, 17, 00, 18, 30, 09, 0d, 03, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02]
+Raw bytes (89): 0x[01, 01, 09, 05, 07, 0b, 11, 09, 0d, 01, 05, 01, 05, 22, 11, 01, 05, 22, 11, 01, 05, 0a, 01, 16, 01, 00, 28, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 03, 00, 0d, 00, 18, 30, 05, 22, 01, 00, 02, 00, 0d, 00, 0e, 22, 00, 12, 00, 13, 30, 1e, 11, 02, 03, 00, 00, 12, 00, 13, 1e, 00, 17, 00, 18, 30, 09, 0d, 03, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 9
@@ -13,7 +13,7 @@ Number of expressions: 9
 - expression 7 operands: lhs = Expression(8, Sub), rhs = Counter(4)
 - expression 8 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 10
-- Code(Counter(0)) at (prev + 23, 1) to (start + 0, 40)
+- Code(Counter(0)) at (prev + 22, 1) to (start + 0, 40)
 - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
     = (c1 + ((c2 + c3) + c4))
 - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
@@ -35,7 +35,7 @@ Number of file 0 mappings: 10
     = (c1 + ((c2 + c3) + c4))
 
 Function name: non_control_flow::assign_3_bis
-Raw bytes (85): 0x[01, 01, 07, 07, 11, 09, 0d, 01, 05, 05, 09, 16, 1a, 05, 09, 01, 05, 0a, 01, 1c, 01, 00, 2c, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 03, 00, 0d, 00, 18, 30, 05, 1a, 01, 03, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 16, 03, 00, 02, 00, 12, 00, 13, 13, 00, 17, 00, 18, 30, 0d, 11, 02, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02]
+Raw bytes (85): 0x[01, 01, 07, 07, 11, 09, 0d, 01, 05, 05, 09, 16, 1a, 05, 09, 01, 05, 0a, 01, 1b, 01, 00, 2c, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 03, 00, 0d, 00, 18, 30, 05, 1a, 01, 03, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 16, 03, 00, 02, 00, 12, 00, 13, 13, 00, 17, 00, 18, 30, 0d, 11, 02, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 7
@@ -47,7 +47,7 @@ Number of expressions: 7
 - expression 5 operands: lhs = Counter(1), rhs = Counter(2)
 - expression 6 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 10
-- Code(Counter(0)) at (prev + 28, 1) to (start + 0, 44)
+- Code(Counter(0)) at (prev + 27, 1) to (start + 0, 44)
 - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
     = ((c2 + c3) + c4)
 - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
@@ -68,7 +68,7 @@ Number of file 0 mappings: 10
     = ((c2 + c3) + c4)
 
 Function name: non_control_flow::assign_and
-Raw bytes (64): 0x[01, 01, 04, 07, 0e, 09, 0d, 01, 05, 01, 05, 08, 01, 0d, 01, 00, 21, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02]
+Raw bytes (64): 0x[01, 01, 04, 07, 0e, 09, 0d, 01, 05, 01, 05, 08, 01, 0c, 01, 00, 21, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 4
@@ -77,7 +77,7 @@ Number of expressions: 4
 - expression 2 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 3 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 8
-- Code(Counter(0)) at (prev + 13, 1) to (start + 0, 33)
+- Code(Counter(0)) at (prev + 12, 1) to (start + 0, 33)
 - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
     = ((c2 + c3) + (c0 - c1))
 - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
@@ -93,7 +93,7 @@ Number of file 0 mappings: 8
     = ((c2 + c3) + (c0 - c1))
 
 Function name: non_control_flow::assign_or
-Raw bytes (64): 0x[01, 01, 04, 07, 0d, 05, 09, 01, 05, 01, 05, 08, 01, 12, 01, 00, 20, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 00, 02, 00, 0d, 00, 0e, 0e, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02]
+Raw bytes (64): 0x[01, 01, 04, 07, 0d, 05, 09, 01, 05, 01, 05, 08, 01, 11, 01, 00, 20, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 00, 02, 00, 0d, 00, 0e, 0e, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 4
@@ -102,7 +102,7 @@ Number of expressions: 4
 - expression 2 operands: lhs = Counter(0), rhs = Counter(1)
 - expression 3 operands: lhs = Counter(0), rhs = Counter(1)
 Number of file 0 mappings: 8
-- Code(Counter(0)) at (prev + 18, 1) to (start + 0, 32)
+- Code(Counter(0)) at (prev + 17, 1) to (start + 0, 32)
 - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
     = ((c1 + c2) + c3)
 - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
@@ -119,15 +119,15 @@ Number of file 0 mappings: 8
     = ((c1 + c2) + c3)
 
 Function name: non_control_flow::foo
-Raw bytes (9): 0x[01, 01, 00, 01, 01, 26, 01, 02, 02]
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 25, 01, 02, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 0
 Number of file 0 mappings: 1
-- Code(Counter(0)) at (prev + 38, 1) to (start + 2, 2)
+- Code(Counter(0)) at (prev + 37, 1) to (start + 2, 2)
 
 Function name: non_control_flow::func_call
-Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 2a, 01, 01, 0a, 28, 00, 02, 01, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 0d, 02, 00, 00, 00, 0e, 00, 0f, 07, 01, 01, 00, 02]
+Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 29, 01, 01, 0a, 28, 00, 02, 01, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 0d, 02, 00, 00, 00, 0e, 00, 0f, 07, 01, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 3
@@ -135,7 +135,7 @@ Number of expressions: 3
 - expression 1 operands: lhs = Expression(2, Add), rhs = Expression(0, Sub)
 - expression 2 operands: lhs = Counter(2), rhs = Counter(3)
 Number of file 0 mappings: 6
-- Code(Counter(0)) at (prev + 42, 1) to (start + 1, 10)
+- Code(Counter(0)) at (prev + 41, 1) to (start + 1, 10)
 - MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 9) to (start + 0, 15)
 - MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 9) to (start + 0, 10)
     true  = c1
@@ -148,7 +148,7 @@ Number of file 0 mappings: 6
     = ((c2 + c3) + (c0 - c1))
 
 Function name: non_control_flow::right_comb_tree
-Raw bytes (139): 0x[01, 01, 13, 07, 1a, 0b, 19, 0f, 15, 13, 11, 09, 0d, 01, 05, 01, 05, 05, 19, 05, 19, 4a, 15, 05, 19, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 0e, 01, 21, 01, 00, 41, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 05, 00, 0d, 00, 2a, 30, 05, 1a, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 13, 00, 14, 30, 4a, 19, 02, 03, 00, 00, 13, 00, 14, 4a, 00, 19, 00, 1a, 30, 46, 15, 03, 04, 00, 00, 19, 00, 1a, 46, 00, 1f, 00, 20, 30, 42, 11, 04, 05, 00, 00, 1f, 00, 20, 42, 00, 24, 00, 27, 30, 09, 0d, 05, 00, 00, 00, 24, 00, 27, 03, 01, 05, 01, 02]
+Raw bytes (139): 0x[01, 01, 13, 07, 1a, 0b, 19, 0f, 15, 13, 11, 09, 0d, 01, 05, 01, 05, 05, 19, 05, 19, 4a, 15, 05, 19, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 0e, 01, 20, 01, 00, 41, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 05, 00, 0d, 00, 2a, 30, 05, 1a, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 13, 00, 14, 30, 4a, 19, 02, 03, 00, 00, 13, 00, 14, 4a, 00, 19, 00, 1a, 30, 46, 15, 03, 04, 00, 00, 19, 00, 1a, 46, 00, 1f, 00, 20, 30, 42, 11, 04, 05, 00, 00, 1f, 00, 20, 42, 00, 24, 00, 27, 30, 09, 0d, 05, 00, 00, 00, 24, 00, 27, 03, 01, 05, 01, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 19
@@ -172,7 +172,7 @@ Number of expressions: 19
 - expression 17 operands: lhs = Expression(18, Sub), rhs = Counter(5)
 - expression 18 operands: lhs = Counter(1), rhs = Counter(6)
 Number of file 0 mappings: 14
-- Code(Counter(0)) at (prev + 33, 1) to (start + 0, 65)
+- Code(Counter(0)) at (prev + 32, 1) to (start + 0, 65)
 - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10)
     = (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1))
 - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14)
diff --git a/tests/coverage/mcdc/non_control_flow.coverage b/tests/coverage/mcdc/non_control_flow.coverage
index c64f61a153c..74c19cf12df 100644
--- a/tests/coverage/mcdc/non_control_flow.coverage
+++ b/tests/coverage/mcdc/non_control_flow.coverage
@@ -1,6 +1,5 @@
    LL|       |#![feature(coverage_attribute)]
    LL|       |//@ edition: 2021
-   LL|       |//@ min-llvm-version: 18
    LL|       |//@ ignore-llvm-version: 19 - 99
    LL|       |//@ compile-flags: -Zcoverage-options=mcdc
    LL|       |//@ llvm-cov-flags: --show-branches=count --show-mcdc
diff --git a/tests/coverage/mcdc/non_control_flow.rs b/tests/coverage/mcdc/non_control_flow.rs
index 633d381a1aa..e0145ed8268 100644
--- a/tests/coverage/mcdc/non_control_flow.rs
+++ b/tests/coverage/mcdc/non_control_flow.rs
@@ -1,6 +1,5 @@
 #![feature(coverage_attribute)]
 //@ edition: 2021
-//@ min-llvm-version: 18
 //@ ignore-llvm-version: 19 - 99
 //@ compile-flags: -Zcoverage-options=mcdc
 //@ llvm-cov-flags: --show-branches=count --show-mcdc
diff --git a/tests/crashes/125476.rs b/tests/crashes/125476.rs
index aa9a081388d..ad739639b72 100644
--- a/tests/crashes/125476.rs
+++ b/tests/crashes/125476.rs
@@ -1,4 +1,4 @@
 //@ known-bug: rust-lang/rust#125476
 //@ only-x86_64
-pub struct Data([u8; usize::MAX >> 16]);
+pub struct Data([u8; usize::MAX >> 2]);
 const _: &'static [Data] = &[];
diff --git a/tests/crashes/130310.rs b/tests/crashes/130310.rs
deleted file mode 100644
index d59dd39983c..00000000000
--- a/tests/crashes/130310.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-//@ known-bug: rust-lang/rust#130310
-
-use std::marker::PhantomData;
-
-#[repr(C)]
-struct A<T> {
-    a: *const A<A<T>>,
-    p: PhantomData<T>,
-}
-
-extern "C" {
-    fn f(a: *const A<()>);
-}
-
-fn main() {}
diff --git a/tests/run-make/compiler-builtins/rmake.rs b/tests/run-make/compiler-builtins/rmake.rs
index 42ed07d9daf..3b05fe2055c 100644
--- a/tests/run-make/compiler-builtins/rmake.rs
+++ b/tests/run-make/compiler-builtins/rmake.rs
@@ -33,8 +33,8 @@ fn main() {
 
     let path = env_var("PATH");
     let rustc = env_var("RUSTC");
-    let bootstrap_cargo = env_var("BOOTSTRAP_CARGO");
-    let mut cmd = cmd(bootstrap_cargo);
+    let cargo = env_var("CARGO");
+    let mut cmd = cmd(cargo);
     cmd.args(&[
         "build",
         "--manifest-path",
diff --git a/tests/run-make/embed-source-dwarf/rmake.rs b/tests/run-make/embed-source-dwarf/rmake.rs
index 06d550121b0..c7106967a85 100644
--- a/tests/run-make/embed-source-dwarf/rmake.rs
+++ b/tests/run-make/embed-source-dwarf/rmake.rs
@@ -1,11 +1,6 @@
 //@ ignore-windows
 //@ ignore-apple
 
-// LLVM 17's embed-source implementation requires that source code is attached
-// for all files in the output DWARF debug info. This restriction was lifted in
-// LLVM 18 (87e22bdd2bd6d77d782f9d64b3e3ae5bdcd5080d).
-//@ min-llvm-version: 18
-
 // This test should be replaced with one in tests/debuginfo once we can easily
 // tell via GDB or LLDB if debuginfo contains source code. Cheap tricks in LLDB
 // like setting an invalid source map path don't appear to work, maybe this'll
diff --git a/tests/run-make/thumb-none-cortex-m/rmake.rs b/tests/run-make/thumb-none-cortex-m/rmake.rs
index 0ddb91d378f..9112646290f 100644
--- a/tests/run-make/thumb-none-cortex-m/rmake.rs
+++ b/tests/run-make/thumb-none-cortex-m/rmake.rs
@@ -36,10 +36,10 @@ fn main() {
 
     let path = env_var("PATH");
     let rustc = env_var("RUSTC");
-    let bootstrap_cargo = env_var("BOOTSTRAP_CARGO");
-    // FIXME: extract bootstrap cargo invocations to a proper command
+    let cargo = env_var("CARGO");
+    // FIXME: extract cargo invocations to a proper command
     // https://github.com/rust-lang/rust/issues/128734
-    let mut cmd = cmd(bootstrap_cargo);
+    let mut cmd = cmd(cargo);
     cmd.args(&[
         "build",
         "--manifest-path",
diff --git a/tests/rustdoc-gui/docblock-code-block-line-number.goml b/tests/rustdoc-gui/docblock-code-block-line-number.goml
index 03f8f80b10d..53f756dfcd6 100644
--- a/tests/rustdoc-gui/docblock-code-block-line-number.goml
+++ b/tests/rustdoc-gui/docblock-code-block-line-number.goml
@@ -39,7 +39,10 @@ define-function: (
             {
                 "color": |color|,
                 "margin": "0px",
-                "padding": "14px 8px",
+                "padding-top": "14px",
+                "padding-bottom": "14px",
+                "padding-left": "8px",
+                "padding-right": "2px",
                 "text-align": "right",
                 // There should not be a radius on the right of the line numbers.
                 "border-top-left-radius": "6px",
@@ -84,7 +87,7 @@ assert-css: ("#settings", {"display": "block"})
 
 // Then, click the toggle button.
 click: "input#line-numbers"
-wait-for: 100 // wait-for-false does not exist
+wait-for: 100 // FIXME: `wait-for-false` does not exist
 assert-false: "pre.example-line-numbers"
 assert-local-storage: {"rustdoc-line-numbers": "false" }
 
@@ -104,6 +107,8 @@ assert-css: (
 click: "input#line-numbers"
 wait-for: "pre.example-line-numbers"
 assert-local-storage: {"rustdoc-line-numbers": "true" }
+wait-for: 100 // FIXME: `wait-for-false` does not exist
+assert: "pre.example-line-numbers"
 
 // Same check with scraped examples line numbers.
 go-to: "file://" + |DOC_PATH| + "/scrape_examples/fn.test_many.html"
@@ -141,3 +146,112 @@ assert-css: (
     },
     ALL,
 )
+
+define-function: (
+    "check-padding",
+    [path, padding_bottom],
+    block {
+        assert-css: (|path| + " .src-line-numbers", {
+            "padding-top": "0px",
+            "padding-bottom": "0px",
+            "padding-left": "0px",
+            "padding-right": "0px",
+        }, ALL)
+        assert-css: (|path| + " .src-line-numbers > pre", {
+            "padding-top": "14px",
+            "padding-bottom": |padding_bottom|,
+            "padding-left": "0px",
+            "padding-right": "0px",
+        }, ALL)
+        assert-css: (|path| + " .src-line-numbers > pre > span", {
+            "padding-top": "0px",
+            "padding-bottom": "0px",
+            "padding-left": "8px",
+            "padding-right": "8px",
+        }, ALL)
+    },
+)
+
+call-function: ("check-padding", {
+    "path": ".scraped-example .example-wrap",
+    "padding_bottom": "0px",
+})
+
+move-cursor-to: ".scraped-example .example-wrap .rust"
+wait-for: ".scraped-example .example-wrap .button-holder .expand"
+click: ".scraped-example .example-wrap .button-holder .expand"
+wait-for: ".scraped-example.expanded"
+
+call-function: ("check-padding", {
+    "path": ".scraped-example.expanded .example-wrap",
+    "padding_bottom": "14px",
+})
+
+define-function: ("check-line-numbers-existence", [], block {
+    assert-local-storage: {"rustdoc-line-numbers": "true" }
+    assert-false: ".example-line-numbers"
+    click: "#settings-menu"
+    wait-for: "#settings"
+
+    // Then, click the toggle button.
+    click: "input#line-numbers"
+    wait-for: 100 // FIXME: `wait-for-false` does not exist
+    assert-local-storage-false: {"rustdoc-line-numbers": "true" }
+    assert-false: ".example-line-numbers"
+    // Line numbers should still be there.
+    assert: ".src-line-numbers"
+    // Now disabling the setting.
+    click: "input#line-numbers"
+    wait-for: 100 // FIXME: `wait-for-false` does not exist
+    assert-local-storage: {"rustdoc-line-numbers": "true" }
+    assert-false: ".example-line-numbers"
+    // Line numbers should still be there.
+    assert: ".src-line-numbers"
+    // Closing settings menu.
+    click: "#settings-menu"
+    wait-for-css: ("#settings", {"display": "none"})
+})
+
+// Checking that turning off the line numbers setting won't remove line numbers from scraped
+// examples.
+call-function: ("check-line-numbers-existence", {})
+
+// Now checking the line numbers in the source code page.
+click: ".src"
+assert-css: (".src-line-numbers", {
+    "padding-top": "20px",
+    "padding-bottom": "20px",
+    "padding-left": "4px",
+    "padding-right": "0px",
+})
+assert-css: (".src-line-numbers > a", {
+    "padding-top": "0px",
+    "padding-bottom": "0px",
+    "padding-left": "8px",
+    "padding-right": "8px",
+})
+// Checking that turning off the line numbers setting won't remove line numbers.
+call-function: ("check-line-numbers-existence", {})
+
+// Now checking that even non-rust code blocks have line numbers generated.
+go-to: "file://" + |DOC_PATH| + "/lib2/sub_mod/struct.Foo.html"
+assert-local-storage: {"rustdoc-line-numbers": "true" }
+assert: ".example-wrap > pre.language-txt"
+assert: ".example-wrap > pre.rust"
+assert-count: (".example-wrap", 2)
+assert-count: (".example-wrap > pre.example-line-numbers", 2)
+
+click: "#settings-menu"
+wait-for: "#settings"
+
+// Then, click the toggle button.
+click: "input#line-numbers"
+wait-for: 100 // FIXME: `wait-for-false` does not exist
+assert-local-storage-false: {"rustdoc-line-numbers": "true" }
+assert-count: (".example-wrap > pre.example-line-numbers", 0)
+
+// Now turning off the setting.
+click: "input#line-numbers"
+wait-for: 100 // FIXME: `wait-for-false` does not exist
+assert-local-storage: {"rustdoc-line-numbers": "true" }
+assert-count: (".example-wrap > pre.example-line-numbers", 2)
diff --git a/tests/rustdoc-gui/scrape-examples-layout.goml b/tests/rustdoc-gui/scrape-examples-layout.goml
index 6bea352bce4..be14e202b37 100644
--- a/tests/rustdoc-gui/scrape-examples-layout.goml
+++ b/tests/rustdoc-gui/scrape-examples-layout.goml
@@ -37,6 +37,7 @@ assert-property: (
 
 // The "title" should be located at the right bottom corner of the code example.
 store-position: (".scraped-example .example-wrap", {"x": x, "y": y})
+assert-size: (".scraped-example .example-wrap", {"height": 130})
 store-size: (".scraped-example .example-wrap", {"width": width, "height": height})
 store-size: (".scraped-example .scraped-example-title", {
     "width": title_width,
@@ -47,6 +48,13 @@ assert-position: (".scraped-example .scraped-example-title", {
     "y": |y| + |height| - |title_height| - 8,
 })
 
+store-size: (".more-scraped-examples .scraped-example .example-wrap", {"height": more_height})
+assert: |more_height| > |height|
+assert-size: (".more-scraped-examples .scraped-example .example-wrap", {
+    "height": 250,
+    "width": |width|,
+})
+
 // Check that the expand button works and also that line number aligns with code.
 move-cursor-to: ".scraped-example .rust"
 click: ".scraped-example .button-holder .expand"
diff --git a/tests/rustdoc-ui/doctest/doctest-output-include-fail.md b/tests/rustdoc-ui/doctest/doctest-output-include-fail.md
new file mode 100644
index 00000000000..a8e61238f31
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doctest-output-include-fail.md
@@ -0,0 +1,7 @@
+With a code sample, that has an error:
+
+```rust
+fn main() {
+    let x = 234 // no semicolon here! oh no!
+}
+```
diff --git a/tests/rustdoc-ui/doctest/doctest-output-include-fail.rs b/tests/rustdoc-ui/doctest/doctest-output-include-fail.rs
new file mode 100644
index 00000000000..4fc0674a0c9
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doctest-output-include-fail.rs
@@ -0,0 +1,7 @@
+//@ compile-flags:--test --test-args=--test-threads=1
+//@ normalize-stdout-test: "tests/rustdoc-ui/doctest" -> "$$DIR"
+//@ normalize-stdout-test: "finished in \d+\.\d+s" -> "finished in $$TIME"
+//@ failure-status: 101
+
+// https://github.com/rust-lang/rust/issues/130470
+#![doc = include_str!("doctest-output-include-fail.md")]
diff --git a/tests/rustdoc-ui/doctest/doctest-output-include-fail.stdout b/tests/rustdoc-ui/doctest/doctest-output-include-fail.stdout
new file mode 100644
index 00000000000..22d15f8743c
--- /dev/null
+++ b/tests/rustdoc-ui/doctest/doctest-output-include-fail.stdout
@@ -0,0 +1,24 @@
+
+running 1 test
+test $DIR/doctest-output-include-fail.md - (line 3) ... FAILED
+
+failures:
+
+---- $DIR/doctest-output-include-fail.md - (line 3) stdout ----
+error: expected `;`, found `}`
+  --> $DIR/doctest-output-include-fail.md:5:16
+   |
+LL |     let x = 234 // no semicolon here! oh no!
+   |                ^ help: add `;` here
+LL | }
+   | - unexpected token
+
+error: aborting due to 1 previous error
+
+Couldn't compile the test.
+
+failures:
+    $DIR/doctest-output-include-fail.md - (line 3)
+
+test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
+
diff --git a/tests/rustdoc-ui/doctest/doctest-output.stdout b/tests/rustdoc-ui/doctest/doctest-output.stdout
index 35b0e366fb5..c3b1570c43e 100644
--- a/tests/rustdoc-ui/doctest/doctest-output.stdout
+++ b/tests/rustdoc-ui/doctest/doctest-output.stdout
@@ -1,7 +1,7 @@
 
 running 3 tests
 test $DIR/doctest-output.rs - (line 8) ... ok
-test $DIR/doctest-output.rs - ExpandedStruct (line 24) ... ok
+test $DIR/doctest-output.rs - ExpandedStruct (line 25) ... ok
 test $DIR/doctest-output.rs - foo::bar (line 18) ... ok
 
 test result: ok. 3 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME
diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs
index 9600c8dff67..b439a4bcf86 100644
--- a/tests/ui/abi/compatibility.rs
+++ b/tests/ui/abi/compatibility.rs
@@ -39,7 +39,6 @@
 //@ revisions: loongarch64
 //@[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu
 //@[loongarch64] needs-llvm-components: loongarch
-//@[loongarch64] min-llvm-version: 18
 //FIXME: wasm is disabled due to <https://github.com/rust-lang/rust/issues/115666>.
 //FIXME @ revisions: wasm
 //FIXME @[wasm] compile-flags: --target wasm32-unknown-unknown
diff --git a/tests/ui/abi/stack-probes-lto.rs b/tests/ui/abi/stack-probes-lto.rs
index 70343b0599a..e6c26c5c4de 100644
--- a/tests/ui/abi/stack-probes-lto.rs
+++ b/tests/ui/abi/stack-probes-lto.rs
@@ -1,7 +1,6 @@
 //@ revisions: aarch64 x32 x64
 //@ run-pass
 //@[aarch64] only-aarch64
-//@[aarch64] min-llvm-version: 18
 //@[x32] only-x86
 //@[x64] only-x86_64
 //@ ignore-sgx no processes
diff --git a/tests/ui/abi/stack-probes.rs b/tests/ui/abi/stack-probes.rs
index 22304257593..1c0e50250d7 100644
--- a/tests/ui/abi/stack-probes.rs
+++ b/tests/ui/abi/stack-probes.rs
@@ -1,7 +1,6 @@
 //@ revisions: aarch64 x32 x64
 //@ run-pass
 //@[aarch64] only-aarch64
-//@[aarch64] min-llvm-version: 18
 //@[x32] only-x86
 //@[x64] only-x86_64
 //@ ignore-emscripten no processes
diff --git a/tests/ui/abi/statics/static-mut-foreign.rs b/tests/ui/abi/statics/static-mut-foreign.rs
index 167b7a4e36e..40cd57637e6 100644
--- a/tests/ui/abi/statics/static-mut-foreign.rs
+++ b/tests/ui/abi/statics/static-mut-foreign.rs
@@ -3,6 +3,9 @@
 // statics cannot. This ensures that there's some form of error if this is
 // attempted.
 
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
 use std::ffi::c_int;
 
 #[link(name = "rust_test_helpers", kind = "static")]
@@ -29,9 +32,7 @@ unsafe fn run() {
     rust_dbg_static_mut = -3;
     assert_eq!(rust_dbg_static_mut, -3);
     static_bound(&rust_dbg_static_mut);
-    //~^ WARN shared reference to mutable static is discouraged [static_mut_refs]
     static_bound_set(&mut rust_dbg_static_mut);
-    //~^ WARN mutable reference to mutable static is discouraged [static_mut_refs]
 }
 
 pub fn main() {
diff --git a/tests/ui/abi/statics/static-mut-foreign.stderr b/tests/ui/abi/statics/static-mut-foreign.stderr
deleted file mode 100644
index 0c4bd5382a1..00000000000
--- a/tests/ui/abi/statics/static-mut-foreign.stderr
+++ /dev/null
@@ -1,31 +0,0 @@
-warning: creating a shared reference to mutable static is discouraged
-  --> $DIR/static-mut-foreign.rs:31:18
-   |
-LL |     static_bound(&rust_dbg_static_mut);
-   |                  ^^^^^^^^^^^^^^^^^^^^ shared 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 shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
-   = note: `#[warn(static_mut_refs)]` on by default
-help: use `addr_of!` instead to create a raw pointer
-   |
-LL |     static_bound(addr_of!(rust_dbg_static_mut));
-   |                  ~~~~~~~~~                   +
-
-warning: creating a mutable reference to mutable static is discouraged
-  --> $DIR/static-mut-foreign.rs:33:22
-   |
-LL |     static_bound_set(&mut rust_dbg_static_mut);
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^ 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 |     static_bound_set(addr_of_mut!(rust_dbg_static_mut));
-   |                      ~~~~~~~~~~~~~                   +
-
-warning: 2 warnings emitted
-
diff --git a/tests/ui/array-slice-vec/slice-panic-1.rs b/tests/ui/array-slice-vec/slice-panic-1.rs
index 4436b633856..d4f584c1632 100644
--- a/tests/ui/array-slice-vec/slice-panic-1.rs
+++ b/tests/ui/array-slice-vec/slice-panic-1.rs
@@ -5,6 +5,8 @@
 
 // Test that if a slicing expr[..] fails, the correct cleanups happen.
 
+// FIXME(static_mut_refs): this could use an atomic
+#![allow(static_mut_refs)]
 
 use std::thread;
 
diff --git a/tests/ui/array-slice-vec/slice-panic-2.rs b/tests/ui/array-slice-vec/slice-panic-2.rs
index 4bd13988424..b3d1dc45573 100644
--- a/tests/ui/array-slice-vec/slice-panic-2.rs
+++ b/tests/ui/array-slice-vec/slice-panic-2.rs
@@ -5,6 +5,8 @@
 
 // Test that if a slicing expr[..] fails, the correct cleanups happen.
 
+// FIXME(static_mut_refs): this could use an atomic
+#![allow(static_mut_refs)]
 
 use std::thread;
 
diff --git a/tests/ui/array-slice-vec/slice.rs b/tests/ui/array-slice-vec/slice.rs
index 2adcd96f598..ad5db7a2102 100644
--- a/tests/ui/array-slice-vec/slice.rs
+++ b/tests/ui/array-slice-vec/slice.rs
@@ -3,6 +3,9 @@
 
 // Test slicing sugar.
 
+// FIXME(static_mut_refs): this could use an atomic
+#![allow(static_mut_refs)]
+
 extern crate core;
 use core::ops::{Index, IndexMut, Range, RangeTo, RangeFrom, RangeFull};
 
diff --git a/tests/ui/asm/inline-syntax.arm.stderr b/tests/ui/asm/inline-syntax.arm.stderr
index 4a50ec8d0d5..61e5078d6d9 100644
--- a/tests/ui/asm/inline-syntax.arm.stderr
+++ b/tests/ui/asm/inline-syntax.arm.stderr
@@ -1,9 +1,11 @@
 error: unknown directive
-.intel_syntax noprefix
-^
-error: unknown directive
-.intel_syntax noprefix
-^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:1
+   |
+LL | .intel_syntax noprefix
+   | ^
+
 error: unknown directive
    |
 note: instantiated into assembly here
@@ -13,7 +15,7 @@ LL | .intel_syntax noprefix
    | ^
 
 error: unknown directive
-  --> $DIR/inline-syntax.rs:35:15
+  --> $DIR/inline-syntax.rs:29:15
    |
 LL |         asm!(".intel_syntax noprefix", "nop");
    |               ^
@@ -25,7 +27,7 @@ LL |     .intel_syntax noprefix
    |     ^
 
 error: unknown directive
-  --> $DIR/inline-syntax.rs:39:15
+  --> $DIR/inline-syntax.rs:32:15
    |
 LL |         asm!(".intel_syntax aaa noprefix", "nop");
    |               ^
@@ -37,7 +39,7 @@ LL |     .intel_syntax aaa noprefix
    |     ^
 
 error: unknown directive
-  --> $DIR/inline-syntax.rs:43:15
+  --> $DIR/inline-syntax.rs:35:15
    |
 LL |         asm!(".att_syntax noprefix", "nop");
    |               ^
@@ -49,7 +51,7 @@ LL |     .att_syntax noprefix
    |     ^
 
 error: unknown directive
-  --> $DIR/inline-syntax.rs:47:15
+  --> $DIR/inline-syntax.rs:38:15
    |
 LL |         asm!(".att_syntax bbb noprefix", "nop");
    |               ^
@@ -61,7 +63,7 @@ LL |     .att_syntax bbb noprefix
    |     ^
 
 error: unknown directive
-  --> $DIR/inline-syntax.rs:51:15
+  --> $DIR/inline-syntax.rs:41:15
    |
 LL |         asm!(".intel_syntax noprefix; nop");
    |               ^
@@ -73,7 +75,7 @@ LL |     .intel_syntax noprefix; nop
    |     ^
 
 error: unknown directive
-  --> $DIR/inline-syntax.rs:58:13
+  --> $DIR/inline-syntax.rs:47:13
    |
 LL |             .intel_syntax noprefix
    |             ^
@@ -84,5 +86,5 @@ note: instantiated into assembly here
 LL |             .intel_syntax noprefix
    |             ^
 
-error: aborting due to 7 previous errors
+error: aborting due to 8 previous errors
 
diff --git a/tests/ui/asm/inline-syntax.arm_llvm_18.stderr b/tests/ui/asm/inline-syntax.arm_llvm_18.stderr
deleted file mode 100644
index ada3f4891d3..00000000000
--- a/tests/ui/asm/inline-syntax.arm_llvm_18.stderr
+++ /dev/null
@@ -1,90 +0,0 @@
-error: unknown directive
-   |
-note: instantiated into assembly here
-  --> <inline asm>:1:1
-   |
-LL | .intel_syntax noprefix
-   | ^
-
-error: unknown directive
-   |
-note: instantiated into assembly here
-  --> <inline asm>:1:1
-   |
-LL | .intel_syntax noprefix
-   | ^
-
-error: unknown directive
-  --> $DIR/inline-syntax.rs:35:15
-   |
-LL |         asm!(".intel_syntax noprefix", "nop");
-   |               ^
-   |
-note: instantiated into assembly here
-  --> <inline asm>:1:2
-   |
-LL |     .intel_syntax noprefix
-   |     ^
-
-error: unknown directive
-  --> $DIR/inline-syntax.rs:39:15
-   |
-LL |         asm!(".intel_syntax aaa noprefix", "nop");
-   |               ^
-   |
-note: instantiated into assembly here
-  --> <inline asm>:1:2
-   |
-LL |     .intel_syntax aaa noprefix
-   |     ^
-
-error: unknown directive
-  --> $DIR/inline-syntax.rs:43:15
-   |
-LL |         asm!(".att_syntax noprefix", "nop");
-   |               ^
-   |
-note: instantiated into assembly here
-  --> <inline asm>:1:2
-   |
-LL |     .att_syntax noprefix
-   |     ^
-
-error: unknown directive
-  --> $DIR/inline-syntax.rs:47:15
-   |
-LL |         asm!(".att_syntax bbb noprefix", "nop");
-   |               ^
-   |
-note: instantiated into assembly here
-  --> <inline asm>:1:2
-   |
-LL |     .att_syntax bbb noprefix
-   |     ^
-
-error: unknown directive
-  --> $DIR/inline-syntax.rs:51:15
-   |
-LL |         asm!(".intel_syntax noprefix; nop");
-   |               ^
-   |
-note: instantiated into assembly here
-  --> <inline asm>:1:2
-   |
-LL |     .intel_syntax noprefix; nop
-   |     ^
-
-error: unknown directive
-  --> $DIR/inline-syntax.rs:58:13
-   |
-LL |             .intel_syntax noprefix
-   |             ^
-   |
-note: instantiated into assembly here
-  --> <inline asm>:2:13
-   |
-LL |             .intel_syntax noprefix
-   |             ^
-
-error: aborting due to 8 previous errors
-
diff --git a/tests/ui/asm/inline-syntax.rs b/tests/ui/asm/inline-syntax.rs
index 4a98d37aca0..b8486527e6f 100644
--- a/tests/ui/asm/inline-syntax.rs
+++ b/tests/ui/asm/inline-syntax.rs
@@ -1,16 +1,10 @@
-//@ revisions: x86_64 arm arm_llvm_18
+//@ revisions: x86_64 arm
 //@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu
 //@[x86_64] check-pass
 //@[x86_64] needs-llvm-components: x86
 //@[arm] compile-flags: --target armv7-unknown-linux-gnueabihf
 //@[arm] build-fail
 //@[arm] needs-llvm-components: arm
-//@[arm] ignore-llvm-version: 18 - 99
-//Newer LLVM produces extra error notes.
-//@[arm_llvm_18] compile-flags: --target armv7-unknown-linux-gnueabihf
-//@[arm_llvm_18] build-fail
-//@[arm_llvm_18] needs-llvm-components: arm
-//@[arm_llvm_18] min-llvm-version: 18
 //@ needs-asm-support
 
 #![feature(no_core, lang_items, rustc_attrs)]
@@ -35,23 +29,18 @@ pub fn main() {
         asm!(".intel_syntax noprefix", "nop");
         //[x86_64]~^ WARN avoid using `.intel_syntax`
         //[arm]~^^ ERROR unknown directive
-        //[arm_llvm_18]~^^^ ERROR unknown directive
         asm!(".intel_syntax aaa noprefix", "nop");
         //[x86_64]~^ WARN avoid using `.intel_syntax`
         //[arm]~^^ ERROR unknown directive
-        //[arm_llvm_18]~^^^ ERROR unknown directive
         asm!(".att_syntax noprefix", "nop");
         //[x86_64]~^ WARN avoid using `.att_syntax`
         //[arm]~^^ ERROR unknown directive
-        //[arm_llvm_18]~^^^ ERROR unknown directive
         asm!(".att_syntax bbb noprefix", "nop");
         //[x86_64]~^ WARN avoid using `.att_syntax`
         //[arm]~^^ ERROR unknown directive
-        //[arm_llvm_18]~^^^ ERROR unknown directive
         asm!(".intel_syntax noprefix; nop");
         //[x86_64]~^ WARN avoid using `.intel_syntax`
         //[arm]~^^ ERROR unknown directive
-        //[arm_llvm_18]~^^^ ERROR unknown directive
 
         asm!(
             r"
@@ -60,7 +49,6 @@ pub fn main() {
         );
         //[x86_64]~^^^ WARN avoid using `.intel_syntax`
         //[arm]~^^^^ ERROR unknown directive
-        //[arm_llvm_18]~^^^^^ ERROR unknown directive
     }
 }
 
diff --git a/tests/ui/asm/inline-syntax.x86_64.stderr b/tests/ui/asm/inline-syntax.x86_64.stderr
index 66dc37f3089..59c95194322 100644
--- a/tests/ui/asm/inline-syntax.x86_64.stderr
+++ b/tests/ui/asm/inline-syntax.x86_64.stderr
@@ -1,5 +1,5 @@
 warning: avoid using `.intel_syntax`, Intel syntax is the default
-  --> $DIR/inline-syntax.rs:67:14
+  --> $DIR/inline-syntax.rs:55:14
    |
 LL | global_asm!(".intel_syntax noprefix", "nop");
    |              ^^^^^^^^^^^^^^^^^^^^^^
@@ -7,37 +7,37 @@ LL | global_asm!(".intel_syntax noprefix", "nop");
    = note: `#[warn(bad_asm_style)]` on by default
 
 warning: avoid using `.intel_syntax`, Intel syntax is the default
-  --> $DIR/inline-syntax.rs:35:15
+  --> $DIR/inline-syntax.rs:29:15
    |
 LL |         asm!(".intel_syntax noprefix", "nop");
    |               ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: avoid using `.intel_syntax`, Intel syntax is the default
-  --> $DIR/inline-syntax.rs:39:15
+  --> $DIR/inline-syntax.rs:32:15
    |
 LL |         asm!(".intel_syntax aaa noprefix", "nop");
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead
-  --> $DIR/inline-syntax.rs:43:15
+  --> $DIR/inline-syntax.rs:35:15
    |
 LL |         asm!(".att_syntax noprefix", "nop");
    |               ^^^^^^^^^^^^^^^^^^^^
 
 warning: avoid using `.att_syntax`, prefer using `options(att_syntax)` instead
-  --> $DIR/inline-syntax.rs:47:15
+  --> $DIR/inline-syntax.rs:38:15
    |
 LL |         asm!(".att_syntax bbb noprefix", "nop");
    |               ^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: avoid using `.intel_syntax`, Intel syntax is the default
-  --> $DIR/inline-syntax.rs:51:15
+  --> $DIR/inline-syntax.rs:41:15
    |
 LL |         asm!(".intel_syntax noprefix; nop");
    |               ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: avoid using `.intel_syntax`, Intel syntax is the default
-  --> $DIR/inline-syntax.rs:58:13
+  --> $DIR/inline-syntax.rs:47:13
    |
 LL |             .intel_syntax noprefix
    |             ^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs
index a8c8a85c5aa..af64901ace0 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs
+++ b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs
@@ -16,4 +16,22 @@ fn bar<T: Trait<method() -> (): Send>>() {}
 fn baz<T: Trait<method(): Send>>() {}
 //~^ ERROR return type notation arguments must be elided with `..`
 
+fn foo_path<T: Trait>() where T::method(i32): Send {}
+//~^ ERROR argument types not allowed with return type notation
+
+fn bar_path<T: Trait>() where T::method() -> (): Send {}
+//~^ ERROR return type not allowed with return type notation
+
+fn baz_path<T: Trait>() where T::method(): Send {}
+//~^ ERROR return type notation arguments must be elided with `..`
+
+fn foo_qualified<T: Trait>() where <T as Trait>::method(i32): Send {}
+//~^ ERROR expected associated type
+
+fn bar_qualified<T: Trait>() where <T as Trait>::method() -> (): Send {}
+//~^ ERROR expected associated type
+
+fn baz_qualified<T: Trait>() where <T as Trait>::method(): Send {}
+//~^ ERROR expected associated type
+
 fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr
index 7e1695984f1..68081470087 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr
+++ b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr
@@ -1,3 +1,21 @@
+error[E0575]: expected associated type, found associated function `Trait::method`
+  --> $DIR/bad-inputs-and-output.rs:28:36
+   |
+LL | fn foo_qualified<T: Trait>() where <T as Trait>::method(i32): Send {}
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^ not a associated type
+
+error[E0575]: expected associated type, found associated function `Trait::method`
+  --> $DIR/bad-inputs-and-output.rs:31:36
+   |
+LL | fn bar_qualified<T: Trait>() where <T as Trait>::method() -> (): Send {}
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a associated type
+
+error[E0575]: expected associated type, found associated function `Trait::method`
+  --> $DIR/bad-inputs-and-output.rs:34:36
+   |
+LL | fn baz_qualified<T: Trait>() where <T as Trait>::method(): Send {}
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^ not a associated type
+
 warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/bad-inputs-and-output.rs:3:12
    |
@@ -25,5 +43,24 @@ error: return type notation arguments must be elided with `..`
 LL | fn baz<T: Trait<method(): Send>>() {}
    |                       ^^ help: add `..`: `(..)`
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: argument types not allowed with return type notation
+  --> $DIR/bad-inputs-and-output.rs:19:40
+   |
+LL | fn foo_path<T: Trait>() where T::method(i32): Send {}
+   |                                        ^^^^^ help: remove the input types: `()`
+
+error: return type not allowed with return type notation
+  --> $DIR/bad-inputs-and-output.rs:22:42
+   |
+LL | fn bar_path<T: Trait>() where T::method() -> (): Send {}
+   |                                          ^^^^^^ help: remove the return type
+
+error: return type notation arguments must be elided with `..`
+  --> $DIR/bad-inputs-and-output.rs:25:40
+   |
+LL | fn baz_path<T: Trait>() where T::method(): Send {}
+   |                                        ^^ help: add `..`: `(..)`
+
+error: aborting due to 9 previous errors; 1 warning emitted
 
+For more information about this error, try `rustc --explain E0575`.
diff --git a/tests/ui/associated-type-bounds/return-type-notation/bare-path.rs b/tests/ui/associated-type-bounds/return-type-notation/bare-path.rs
index f507d82afec..185c0523633 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/bare-path.rs
+++ b/tests/ui/associated-type-bounds/return-type-notation/bare-path.rs
@@ -10,17 +10,12 @@ trait Tr {
 fn foo<T: Tr>()
 where
     T::method(..): Send,
-    //~^ ERROR return type notation not allowed in this position yet
-    //~| ERROR expected type, found function
     <T as Tr>::method(..): Send,
-    //~^ ERROR return type notation not allowed in this position yet
-    //~| ERROR expected associated type, found associated function `Tr::method`
 {
     let _ = T::CONST::(..);
     //~^ ERROR return type notation not allowed in this position yet
     let _: T::method(..);
     //~^ ERROR return type notation not allowed in this position yet
-    //~| ERROR expected type, found function
 }
 
 fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/bare-path.stderr b/tests/ui/associated-type-bounds/return-type-notation/bare-path.stderr
index cb45de59c7e..dca2bdeab0a 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/bare-path.stderr
+++ b/tests/ui/associated-type-bounds/return-type-notation/bare-path.stderr
@@ -1,9 +1,3 @@
-error[E0575]: expected associated type, found associated function `Tr::method`
-  --> $DIR/bare-path.rs:15:5
-   |
-LL |     <T as Tr>::method(..): Send,
-   |     ^^^^^^^^^^^^^^^^^^^^^ not a associated type
-
 warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/bare-path.rs:1:12
    |
@@ -14,53 +8,16 @@ LL | #![feature(return_type_notation)]
    = note: `#[warn(incomplete_features)]` on by default
 
 error: return type notation not allowed in this position yet
-  --> $DIR/bare-path.rs:19:23
+  --> $DIR/bare-path.rs:15:23
    |
 LL |     let _ = T::CONST::(..);
    |                       ^^^^
 
 error: return type notation not allowed in this position yet
-  --> $DIR/bare-path.rs:21:21
+  --> $DIR/bare-path.rs:17:12
    |
 LL |     let _: T::method(..);
-   |                     ^^^^
-
-error: return type notation not allowed in this position yet
-  --> $DIR/bare-path.rs:12:14
-   |
-LL |     T::method(..): Send,
-   |              ^^^^
-
-error: return type notation not allowed in this position yet
-  --> $DIR/bare-path.rs:15:22
-   |
-LL |     <T as Tr>::method(..): Send,
-   |                      ^^^^
-
-error: expected type, found function
-  --> $DIR/bare-path.rs:12:8
-   |
-LL |     T::method(..): Send,
-   |        ^^^^^^ unexpected function
-   |
-note: the associated function is defined here
-  --> $DIR/bare-path.rs:7:5
-   |
-LL |     fn method() -> impl Sized;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: expected type, found function
-  --> $DIR/bare-path.rs:21:15
-   |
-LL |     let _: T::method(..);
-   |               ^^^^^^ unexpected function
-   |
-note: the associated function is defined here
-  --> $DIR/bare-path.rs:7:5
-   |
-LL |     fn method() -> impl Sized;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |            ^^^^^^^^^^^^^
 
-error: aborting due to 7 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors; 1 warning emitted
 
-For more information about this error, try `rustc --explain E0575`.
diff --git a/tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.rs b/tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.rs
new file mode 100644
index 00000000000..d4f21f47c6c
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.rs
@@ -0,0 +1,52 @@
+//@ check-pass
+
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait Trait<'a> {
+    fn late<'b>(&'b self, _: &'a ()) -> impl Sized;
+    fn early<'b: 'b>(&'b self, _: &'a ()) -> impl Sized;
+}
+
+#[allow(refining_impl_trait_internal)]
+impl<'a> Trait<'a> for () {
+    fn late<'b>(&'b self, _: &'a ()) -> i32 { 1 }
+    fn early<'b: 'b>(&'b self, _: &'a ()) -> i32 { 1 }
+}
+
+trait Other<'c> {}
+impl Other<'_> for i32 {}
+
+fn test<T>(t: &T)
+where
+    T: for<'a, 'c> Trait<'a, late(..): Other<'c>>,
+    // which is basically:
+    // for<'a, 'c> Trait<'a, for<'b> method<'b>: Other<'c>>,
+    T: for<'a, 'c> Trait<'a, early(..): Other<'c>>,
+    // which is basically:
+    // for<'a, 'c> Trait<'a, for<'b> method<'b>: Other<'c>>,
+{
+    is_other_impl(t.late(&()));
+    is_other_impl(t.early(&()));
+}
+
+fn test_path<T>(t: &T)
+where
+T: for<'a> Trait<'a>,
+    for<'a, 'c> <T as Trait<'a>>::late(..): Other<'c>,
+    // which is basically:
+    // for<'a, 'b, 'c> <T as Trait<'a>>::method::<'b>: Other<'c>
+    for<'a, 'c> <T as Trait<'a>>::early(..): Other<'c>,
+    // which is basically:
+    // for<'a, 'b, 'c> <T as Trait<'a>>::method::<'b>: Other<'c>
+{
+    is_other_impl(t.late(&()));
+    is_other_impl(t.early(&()));
+}
+
+fn is_other_impl(_: impl for<'c> Other<'c>) {}
+
+fn main() {
+    test(&());
+    test(&());
+}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.stderr b/tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.stderr
new file mode 100644
index 00000000000..c67231c07f7
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/higher-ranked-bound-works.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/higher-ranked-bound-works.rs:3:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/associated-type-bounds/return-type-notation/namespace-conflict.rs b/tests/ui/associated-type-bounds/return-type-notation/namespace-conflict.rs
new file mode 100644
index 00000000000..9bdc2d00233
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/namespace-conflict.rs
@@ -0,0 +1,42 @@
+//@ check-pass
+
+#![allow(non_camel_case_types)]
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait Foo {
+    type test;
+
+    fn test() -> impl Bar;
+}
+
+fn call_path<T: Foo>()
+where
+    T::test(..): Bar,
+{
+}
+
+fn call_bound<T: Foo<test(..): Bar>>() {}
+
+trait Bar {}
+struct NotBar;
+struct YesBar;
+impl Bar for YesBar {}
+
+impl Foo for () {
+    type test = NotBar;
+
+    // Use refinement here so we can observe `YesBar: Bar`.
+    #[allow(refining_impl_trait_internal)]
+    fn test() -> YesBar {
+        YesBar
+    }
+}
+
+fn main() {
+    // If `T::test(..)` resolved to the GAT (erroneously), then this would be
+    // an error since `<() as Foo>::bar` -- the associated type -- does not
+    // implement `Bar`, but the return type of the method does.
+    call_path::<()>();
+    call_bound::<()>();
+}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/namespace-conflict.stderr b/tests/ui/associated-type-bounds/return-type-notation/namespace-conflict.stderr
new file mode 100644
index 00000000000..f4ece074b28
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/namespace-conflict.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/namespace-conflict.rs:4:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.rs b/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.rs
index d283c6eab37..35d6dd799c7 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.rs
+++ b/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.rs
@@ -5,7 +5,10 @@ trait Trait {
     fn method() {}
 }
 
-fn test<T: Trait<method(..): Send>>() {}
-//~^ ERROR  return type notation used on function that is not `async` and does not return `impl Trait`
+fn bound<T: Trait<method(..): Send>>() {}
+//~^ ERROR return type notation used on function that is not `async` and does not return `impl Trait`
+
+fn path<T>() where T: Trait, T::method(..): Send {}
+//~^ ERROR return type notation used on function that is not `async` and does not return `impl Trait`
 
 fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.stderr b/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.stderr
index 79ced3c96ed..e308c927bf0 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.stderr
+++ b/tests/ui/associated-type-bounds/return-type-notation/non-rpitit.stderr
@@ -8,15 +8,26 @@ LL | #![feature(return_type_notation)]
    = note: `#[warn(incomplete_features)]` on by default
 
 error: return type notation used on function that is not `async` and does not return `impl Trait`
-  --> $DIR/non-rpitit.rs:8:18
+  --> $DIR/non-rpitit.rs:8:19
    |
 LL |     fn method() {}
    |     ----------- this function must be `async` or return `impl Trait`
 ...
-LL | fn test<T: Trait<method(..): Send>>() {}
-   |                  ^^^^^^^^^^^^^^^^
+LL | fn bound<T: Trait<method(..): Send>>() {}
+   |                   ^^^^^^^^^^^^^^^^
    |
    = note: function returns `()`, which is not compatible with associated type return bounds
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: return type notation used on function that is not `async` and does not return `impl Trait`
+  --> $DIR/non-rpitit.rs:11:30
+   |
+LL |     fn method() {}
+   |     ----------- this function must be `async` or return `impl Trait`
+...
+LL | fn path<T>() where T: Trait, T::method(..): Send {}
+   |                              ^^^^^^^^^^^^^
+   |
+   = note: function returns `()`, which is not compatible with associated type return bounds
+
+error: aborting due to 2 previous errors; 1 warning emitted
 
diff --git a/tests/ui/associated-type-bounds/return-type-notation/not-a-method.rs b/tests/ui/associated-type-bounds/return-type-notation/not-a-method.rs
new file mode 100644
index 00000000000..d94ec6b74d9
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/not-a-method.rs
@@ -0,0 +1,42 @@
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+fn function() {}
+
+fn not_a_method()
+where
+    function(..): Send,
+    //~^ ERROR expected function, found function `function`
+    //~| ERROR return type notation not allowed in this position yet
+{
+}
+
+fn not_a_method_and_typoed()
+where
+    function(): Send,
+    //~^ ERROR expected type, found function `function`
+{
+}
+
+trait Tr {
+    fn method();
+}
+
+// Forgot the `T::`
+fn maybe_method_overlaps<T: Tr>()
+where
+    method(..): Send,
+    //~^ ERROR cannot find function `method` in this scope
+    //~| ERROR return type notation not allowed in this position yet
+{
+}
+
+// Forgot the `T::`, AND typoed `(..)` to `()`
+fn maybe_method_overlaps_and_typoed<T: Tr>()
+where
+    method(): Send,
+    //~^ ERROR cannot find type `method` in this scope
+{
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/not-a-method.stderr b/tests/ui/associated-type-bounds/return-type-notation/not-a-method.stderr
new file mode 100644
index 00000000000..8add2d46296
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/not-a-method.stderr
@@ -0,0 +1,49 @@
+error[E0575]: expected function, found function `function`
+  --> $DIR/not-a-method.rs:8:5
+   |
+LL |     function(..): Send,
+   |     ^^^^^^^^^^^^ not a function
+
+error[E0573]: expected type, found function `function`
+  --> $DIR/not-a-method.rs:16:5
+   |
+LL |     function(): Send,
+   |     ^^^^^^^^^^ not a type
+
+error[E0576]: cannot find function `method` in this scope
+  --> $DIR/not-a-method.rs:28:5
+   |
+LL |     method(..): Send,
+   |     ^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `method` in this scope
+  --> $DIR/not-a-method.rs:37:5
+   |
+LL |     method(): Send,
+   |     ^^^^^^ not found in this scope
+
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/not-a-method.rs:1:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: return type notation not allowed in this position yet
+  --> $DIR/not-a-method.rs:8:5
+   |
+LL |     function(..): Send,
+   |     ^^^^^^^^^^^^
+
+error: return type notation not allowed in this position yet
+  --> $DIR/not-a-method.rs:28:5
+   |
+LL |     method(..): Send,
+   |     ^^^^^^^^^^
+
+error: aborting due to 6 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0412, E0573, E0575, E0576.
+For more information about an error, try `rustc --explain E0412`.
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-ambiguous.rs b/tests/ui/associated-type-bounds/return-type-notation/path-ambiguous.rs
new file mode 100644
index 00000000000..cb42c33e364
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-ambiguous.rs
@@ -0,0 +1,27 @@
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait A {
+    fn method() -> impl Sized;
+}
+trait B {
+    fn method() -> impl Sized;
+}
+
+fn ambiguous<T: A + B>()
+where
+    T::method(..): Send,
+    //~^ ERROR ambiguous associated function `method` in bounds of `T`
+{
+}
+
+trait Sub: A + B {}
+
+fn ambiguous_via_supertrait<T: Sub>()
+where
+    T::method(..): Send,
+    //~^ ERROR ambiguous associated function `method` in bounds of `T`
+{
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-ambiguous.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-ambiguous.stderr
new file mode 100644
index 00000000000..e841049ac66
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-ambiguous.stderr
@@ -0,0 +1,54 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/path-ambiguous.rs:1:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0221]: ambiguous associated function `method` in bounds of `T`
+  --> $DIR/path-ambiguous.rs:13:5
+   |
+LL |     fn method() -> impl Sized;
+   |     -------------------------- ambiguous `method` from `A`
+...
+LL |     fn method() -> impl Sized;
+   |     -------------------------- ambiguous `method` from `B`
+...
+LL |     T::method(..): Send,
+   |     ^^^^^^^^^^^^^ ambiguous associated function `method`
+   |
+help: use fully-qualified syntax to disambiguate
+   |
+LL |     <T as B>::method(..): Send,
+   |     ~~~~~~~~~~
+help: use fully-qualified syntax to disambiguate
+   |
+LL |     <T as A>::method(..): Send,
+   |     ~~~~~~~~~~
+
+error[E0221]: ambiguous associated function `method` in bounds of `T`
+  --> $DIR/path-ambiguous.rs:22:5
+   |
+LL |     fn method() -> impl Sized;
+   |     -------------------------- ambiguous `method` from `A`
+...
+LL |     fn method() -> impl Sized;
+   |     -------------------------- ambiguous `method` from `B`
+...
+LL |     T::method(..): Send,
+   |     ^^^^^^^^^^^^^ ambiguous associated function `method`
+   |
+help: use fully-qualified syntax to disambiguate
+   |
+LL |     <T as B>::method(..): Send,
+   |     ~~~~~~~~~~
+help: use fully-qualified syntax to disambiguate
+   |
+LL |     <T as A>::method(..): Send,
+   |     ~~~~~~~~~~
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0221`.
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.rs b/tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.rs
new file mode 100644
index 00000000000..56abd167fb6
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.rs
@@ -0,0 +1,24 @@
+//@ check-pass
+
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait Trait {
+    fn method() -> impl Sized;
+}
+
+fn is_send(_: impl Send) {}
+
+struct W<T>(T);
+
+impl<T> W<T> {
+    fn test()
+    where
+        T: Trait,
+        T::method(..): Send,
+    {
+        is_send(T::method());
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.stderr
new file mode 100644
index 00000000000..3db033d8cf5
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-constrained-in-method.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/path-constrained-in-method.rs:3:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-higher-ranked.rs b/tests/ui/associated-type-bounds/return-type-notation/path-higher-ranked.rs
new file mode 100644
index 00000000000..a4d8f005371
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-higher-ranked.rs
@@ -0,0 +1,25 @@
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait A<'a> {
+    fn method() -> impl Sized;
+}
+trait B: for<'a> A<'a> {}
+
+fn higher_ranked<T>()
+where
+    T: for<'a> A<'a>,
+    T::method(..): Send,
+    //~^ ERROR cannot use the associated function of a trait with uninferred generic parameters
+{
+}
+
+fn higher_ranked_via_supertrait<T>()
+where
+    T: B,
+    T::method(..): Send,
+    //~^ ERROR cannot use the associated function of a trait with uninferred generic parameters
+{
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-higher-ranked.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-higher-ranked.stderr
new file mode 100644
index 00000000000..22de6165503
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-higher-ranked.stderr
@@ -0,0 +1,34 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/path-higher-ranked.rs:1:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0212]: cannot use the associated function of a trait with uninferred generic parameters
+  --> $DIR/path-higher-ranked.rs:12:5
+   |
+LL |     T::method(..): Send,
+   |     ^^^^^^^^^^^^^
+   |
+help: use a fully qualified path with inferred lifetimes
+   |
+LL |     <T as A<'_>>::method(..): Send,
+   |     ~~~~~~~~~~~~~~
+
+error[E0212]: cannot use the associated function of a trait with uninferred generic parameters
+  --> $DIR/path-higher-ranked.rs:20:5
+   |
+LL |     T::method(..): Send,
+   |     ^^^^^^^^^^^^^
+   |
+help: use a fully qualified path with inferred lifetimes
+   |
+LL |     <T as A<'_>>::method(..): Send,
+   |     ~~~~~~~~~~~~~~
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0212`.
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-missing.rs b/tests/ui/associated-type-bounds/return-type-notation/path-missing.rs
new file mode 100644
index 00000000000..c1a7b95ca2d
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-missing.rs
@@ -0,0 +1,25 @@
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait A {
+    #[allow(non_camel_case_types)]
+    type bad;
+}
+
+fn fully_qualified<T: A>()
+where
+    <T as A>::method(..): Send,
+    //~^ ERROR cannot find method or associated constant `method` in trait `A`
+    <T as A>::bad(..): Send,
+    //~^ ERROR expected method or associated constant, found associated type `A::bad`
+{
+}
+
+fn type_dependent<T: A>()
+where
+    T::method(..): Send,
+    //~^ associated function `method` not found for `T`
+{
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-missing.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-missing.stderr
new file mode 100644
index 00000000000..0130c3bc614
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-missing.stderr
@@ -0,0 +1,33 @@
+error[E0576]: cannot find method or associated constant `method` in trait `A`
+  --> $DIR/path-missing.rs:11:15
+   |
+LL |     <T as A>::method(..): Send,
+   |               ^^^^^^ not found in `A`
+
+error[E0575]: expected method or associated constant, found associated type `A::bad`
+  --> $DIR/path-missing.rs:13:5
+   |
+LL |     <T as A>::bad(..): Send,
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = note: can't use a type alias as a constructor
+
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/path-missing.rs:1:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0220]: associated function `method` not found for `T`
+  --> $DIR/path-missing.rs:20:8
+   |
+LL |     T::method(..): Send,
+   |        ^^^^^^ associated function `method` not found
+
+error: aborting due to 3 previous errors; 1 warning emitted
+
+Some errors have detailed explanations: E0220, E0575, E0576.
+For more information about an error, try `rustc --explain E0220`.
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-no-qself.rs b/tests/ui/associated-type-bounds/return-type-notation/path-no-qself.rs
new file mode 100644
index 00000000000..d2636789c10
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-no-qself.rs
@@ -0,0 +1,15 @@
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait Trait {
+    fn method() -> impl Sized;
+}
+
+fn test()
+where
+    Trait::method(..): Send,
+    //~^ ERROR ambiguous associated type
+{
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-no-qself.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-no-qself.stderr
new file mode 100644
index 00000000000..d66b0a109fc
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-no-qself.stderr
@@ -0,0 +1,23 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/path-no-qself.rs:1:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0223]: ambiguous associated type
+  --> $DIR/path-no-qself.rs:10:5
+   |
+LL |     Trait::method(..): Send,
+   |     ^^^^^^^^^^^^^^^^^
+   |
+help: if there were a type named `Example` that implemented `Trait`, you could use the fully-qualified path
+   |
+LL |     <Example as Trait>::method: Send,
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0223`.
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-non-param-qself.rs b/tests/ui/associated-type-bounds/return-type-notation/path-non-param-qself.rs
new file mode 100644
index 00000000000..b0e6ea852b0
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-non-param-qself.rs
@@ -0,0 +1,21 @@
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait Trait {
+    fn method() -> impl Sized;
+}
+
+struct Adt;
+
+fn non_param_qself()
+where
+    <()>::method(..): Send,
+    //~^ ERROR ambiguous associated function
+    i32::method(..): Send,
+    //~^ ERROR ambiguous associated function
+    Adt::method(..): Send,
+    //~^ ERROR ambiguous associated function
+{
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-non-param-qself.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-non-param-qself.stderr
new file mode 100644
index 00000000000..cd1aa9813e3
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-non-param-qself.stderr
@@ -0,0 +1,30 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/path-non-param-qself.rs:1:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0223]: ambiguous associated function
+  --> $DIR/path-non-param-qself.rs:12:5
+   |
+LL |     <()>::method(..): Send,
+   |     ^^^^^^^^^^^^^^^^
+
+error[E0223]: ambiguous associated function
+  --> $DIR/path-non-param-qself.rs:14:5
+   |
+LL |     i32::method(..): Send,
+   |     ^^^^^^^^^^^^^^^
+
+error[E0223]: ambiguous associated function
+  --> $DIR/path-non-param-qself.rs:16:5
+   |
+LL |     Adt::method(..): Send,
+   |     ^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0223`.
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-self-qself.rs b/tests/ui/associated-type-bounds/return-type-notation/path-self-qself.rs
new file mode 100644
index 00000000000..0cf84457ba7
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-self-qself.rs
@@ -0,0 +1,27 @@
+//@ check-pass
+
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait Foo {
+    fn method() -> impl Sized;
+}
+
+trait Bar: Foo {
+    fn other()
+    where
+        Self::method(..): Send;
+}
+
+fn is_send(_: impl Send) {}
+
+impl<T: Foo> Bar for T {
+    fn other()
+    where
+        Self::method(..): Send,
+    {
+        is_send(Self::method());
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-self-qself.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-self-qself.stderr
new file mode 100644
index 00000000000..ab33647583c
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-self-qself.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/path-self-qself.rs:3:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-type-param.rs b/tests/ui/associated-type-bounds/return-type-notation/path-type-param.rs
new file mode 100644
index 00000000000..693a300eb1d
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-type-param.rs
@@ -0,0 +1,22 @@
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait Foo {
+    fn method<T>() -> impl Sized;
+}
+
+fn test<T: Foo>()
+where
+    <T as Foo>::method(..): Send,
+    //~^ ERROR return type notation is not allowed for functions that have type parameters
+{
+}
+
+fn test_type_dependent<T: Foo>()
+where
+    <T as Foo>::method(..): Send,
+    //~^ ERROR return type notation is not allowed for functions that have type parameters
+{
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-type-param.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-type-param.stderr
new file mode 100644
index 00000000000..0d33d4f97d7
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-type-param.stderr
@@ -0,0 +1,29 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/path-type-param.rs:1:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: return type notation is not allowed for functions that have type parameters
+  --> $DIR/path-type-param.rs:10:5
+   |
+LL |     fn method<T>() -> impl Sized;
+   |               - type parameter declared here
+...
+LL |     <T as Foo>::method(..): Send,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: return type notation is not allowed for functions that have type parameters
+  --> $DIR/path-type-param.rs:17:5
+   |
+LL |     fn method<T>() -> impl Sized;
+   |               - type parameter declared here
+...
+LL |     <T as Foo>::method(..): Send,
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.rs b/tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.rs
new file mode 100644
index 00000000000..a5b0b0e4e25
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.rs
@@ -0,0 +1,25 @@
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait Trait {
+    fn method() -> impl Sized;
+}
+
+struct DoesntWork;
+impl Trait for DoesntWork {
+    fn method() -> impl Sized {
+        std::ptr::null_mut::<()>()
+        // This isn't `Send`.
+    }
+}
+
+fn test<T: Trait>()
+where
+    T::method(..): Send,
+{
+}
+
+fn main() {
+    test::<DoesntWork>();
+    //~^ ERROR `*mut ()` cannot be sent between threads safely
+}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.stderr
new file mode 100644
index 00000000000..7d32a428555
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-unsatisfied.stderr
@@ -0,0 +1,36 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/path-unsatisfied.rs:1:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0277]: `*mut ()` cannot be sent between threads safely
+  --> $DIR/path-unsatisfied.rs:23:12
+   |
+LL |     fn method() -> impl Sized {
+   |                    ---------- within this `impl Sized`
+...
+LL |     test::<DoesntWork>();
+   |            ^^^^^^^^^^ `*mut ()` cannot be sent between threads safely
+   |
+   = help: within `impl Sized`, the trait `Send` is not implemented for `*mut ()`, which is required by `impl Sized: Send`
+note: required because it appears within the type `impl Sized`
+  --> $DIR/path-unsatisfied.rs:10:20
+   |
+LL |     fn method() -> impl Sized {
+   |                    ^^^^^^^^^^
+note: required by a bound in `test`
+  --> $DIR/path-unsatisfied.rs:18:20
+   |
+LL | fn test<T: Trait>()
+   |    ---- required by a bound in this function
+LL | where
+LL |     T::method(..): Send,
+   |                    ^^^^ required by this bound in `test`
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-works.rs b/tests/ui/associated-type-bounds/return-type-notation/path-works.rs
new file mode 100644
index 00000000000..027bc89f13e
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-works.rs
@@ -0,0 +1,23 @@
+//@ check-pass
+
+#![feature(return_type_notation)]
+//~^ WARN the feature `return_type_notation` is incomplete
+
+trait Trait {
+    fn method() -> impl Sized;
+}
+
+struct Works;
+impl Trait for Works {
+    fn method() -> impl Sized {}
+}
+
+fn test<T: Trait>()
+where
+    T::method(..): Send,
+{
+}
+
+fn main() {
+    test::<Works>();
+}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/path-works.stderr b/tests/ui/associated-type-bounds/return-type-notation/path-works.stderr
new file mode 100644
index 00000000000..b1ec8069ba0
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/path-works.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/path-works.rs:3:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/async-await/issues/issue-67611-static-mut-refs.rs b/tests/ui/async-await/issues/issue-67611-static-mut-refs.rs
index 51e85931dbf..547c7414526 100644
--- a/tests/ui/async-await/issues/issue-67611-static-mut-refs.rs
+++ b/tests/ui/async-await/issues/issue-67611-static-mut-refs.rs
@@ -2,6 +2,8 @@
 //@ edition:2018
 
 #![feature(if_let_guard)]
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
 
 static mut A: [i32; 5] = [1, 2, 3, 4, 5];
 
diff --git a/tests/ui/async-await/pin-reborrow-arg.rs b/tests/ui/async-await/pin-reborrow-arg.rs
new file mode 100644
index 00000000000..2008bd1f52d
--- /dev/null
+++ b/tests/ui/async-await/pin-reborrow-arg.rs
@@ -0,0 +1,36 @@
+//@ check-pass
+
+#![feature(pin_ergonomics)]
+#![allow(dead_code, incomplete_features)]
+
+use std::pin::Pin;
+
+struct Foo;
+
+impl Foo {
+    fn baz(self: Pin<&mut Self>) {
+    }
+}
+
+fn foo(_: Pin<&mut Foo>) {
+}
+
+fn foo_const(_: Pin<&Foo>) {
+}
+
+fn bar(x: Pin<&mut Foo>) {
+    foo(x);
+    foo(x); // for this to work we need to automatically reborrow,
+            // as if the user had written `foo(x.as_mut())`.
+
+    Foo::baz(x);
+    Foo::baz(x);
+
+    foo_const(x); // make sure we can reborrow &mut as &.
+
+    let x: Pin<&Foo> = Pin::new(&Foo);
+
+    foo_const(x); // make sure reborrowing from & to & works.
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/pin-reborrow-const-as-mut.rs b/tests/ui/async-await/pin-reborrow-const-as-mut.rs
new file mode 100644
index 00000000000..27c70a7b4df
--- /dev/null
+++ b/tests/ui/async-await/pin-reborrow-const-as-mut.rs
@@ -0,0 +1,18 @@
+#![feature(pin_ergonomics)]
+#![allow(dead_code, incomplete_features)]
+
+// make sure we can't accidentally reborrow Pin<&T> as Pin<&mut T>
+
+use std::pin::Pin;
+
+struct Foo;
+
+fn foo(_: Pin<&mut Foo>) {
+}
+
+fn bar(x: Pin<&Foo>) {
+    foo(x); //~ ERROR mismatched types
+            //| ERROR types differ in mutability
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/pin-reborrow-const-as-mut.stderr b/tests/ui/async-await/pin-reborrow-const-as-mut.stderr
new file mode 100644
index 00000000000..2c2d9ec2717
--- /dev/null
+++ b/tests/ui/async-await/pin-reborrow-const-as-mut.stderr
@@ -0,0 +1,19 @@
+error[E0308]: mismatched types
+  --> $DIR/pin-reborrow-const-as-mut.rs:14:9
+   |
+LL |     foo(x);
+   |     --- ^ types differ in mutability
+   |     |
+   |     arguments to this function are incorrect
+   |
+   = note: expected struct `Pin<&mut Foo>`
+              found struct `Pin<&Foo>`
+note: function defined here
+  --> $DIR/pin-reborrow-const-as-mut.rs:10:4
+   |
+LL | fn foo(_: Pin<&mut Foo>) {
+   |    ^^^ ----------------
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/async-await/pin-reborrow-once.rs b/tests/ui/async-await/pin-reborrow-once.rs
new file mode 100644
index 00000000000..241efadef7d
--- /dev/null
+++ b/tests/ui/async-await/pin-reborrow-once.rs
@@ -0,0 +1,13 @@
+#![feature(pin_ergonomics)]
+#![allow(dead_code, incomplete_features)]
+
+// Make sure with pin reborrowing that we can only get one mutable reborrow of a pinned reference.
+
+use std::pin::{pin, Pin};
+
+fn twice(_: Pin<&mut i32>, _: Pin<&mut i32>) {}
+
+fn main() {
+    let x = pin!(42);
+    twice(x, x); //~ ERROR cannot borrow
+}
diff --git a/tests/ui/async-await/pin-reborrow-once.stderr b/tests/ui/async-await/pin-reborrow-once.stderr
new file mode 100644
index 00000000000..b8fde8ffee8
--- /dev/null
+++ b/tests/ui/async-await/pin-reborrow-once.stderr
@@ -0,0 +1,12 @@
+error[E0499]: cannot borrow `*x.__pointer` as mutable more than once at a time
+  --> $DIR/pin-reborrow-once.rs:12:14
+   |
+LL |     twice(x, x);
+   |     ----- -  ^ second mutable borrow occurs here
+   |     |     |
+   |     |     first mutable borrow occurs here
+   |     first borrow later used by call
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0499`.
diff --git a/tests/ui/async-await/pin-reborrow-self.rs b/tests/ui/async-await/pin-reborrow-self.rs
new file mode 100644
index 00000000000..b60b6982bb8
--- /dev/null
+++ b/tests/ui/async-await/pin-reborrow-self.rs
@@ -0,0 +1,24 @@
+//@ check-pass
+//@ignore-test
+
+// Currently ignored due to self reborrowing not being implemented for Pin
+
+#![feature(pin_ergonomics)]
+#![allow(incomplete_features)]
+
+use std::pin::Pin;
+
+struct Foo;
+
+impl Foo {
+    fn foo(self: Pin<&mut Self>) {
+    }
+}
+
+fn bar(x: Pin<&mut Foo>) {
+    x.foo();
+    x.foo(); // for this to work we need to automatically reborrow,
+             // as if the user had written `x.as_mut().foo()`.
+}
+
+fn main() {}
diff --git a/tests/ui/async-await/pin-reborrow-shorter.rs b/tests/ui/async-await/pin-reborrow-shorter.rs
new file mode 100644
index 00000000000..06c266e0035
--- /dev/null
+++ b/tests/ui/async-await/pin-reborrow-shorter.rs
@@ -0,0 +1,14 @@
+//@check-pass
+
+#![feature(pin_ergonomics)]
+#![allow(dead_code, incomplete_features)]
+
+use std::pin::Pin;
+
+fn shorter<'b, T: 'b>(_: Pin<&'b mut T>) {}
+
+fn test<'a: 'b, 'b, T: 'a>(x: Pin<&'a mut T>) {
+    shorter::<'b>(x);
+}
+
+fn main() {}
diff --git a/tests/ui/attributes/issue-105594-invalid-attr-validation.rs b/tests/ui/attributes/issue-105594-invalid-attr-validation.rs
index bea5faf7253..cb196471fd7 100644
--- a/tests/ui/attributes/issue-105594-invalid-attr-validation.rs
+++ b/tests/ui/attributes/issue-105594-invalid-attr-validation.rs
@@ -1,13 +1,7 @@
 // This checks that the attribute validation ICE in issue #105594 doesn't
 // recur.
-//
-//@ ignore-thumbv8m.base-none-eabi
-#![feature(cmse_nonsecure_entry)]
 
 fn main() {}
 
 #[track_caller] //~ ERROR attribute should be applied to a function
 static _A: () = ();
-
-#[cmse_nonsecure_entry] //~ ERROR attribute should be applied to a function
-static _B: () = (); //~| ERROR #[cmse_nonsecure_entry]` is only valid for targets
diff --git a/tests/ui/attributes/issue-105594-invalid-attr-validation.stderr b/tests/ui/attributes/issue-105594-invalid-attr-validation.stderr
index c6b2d6e7813..1248967c47b 100644
--- a/tests/ui/attributes/issue-105594-invalid-attr-validation.stderr
+++ b/tests/ui/attributes/issue-105594-invalid-attr-validation.stderr
@@ -1,26 +1,11 @@
 error[E0739]: attribute should be applied to a function definition
-  --> $DIR/issue-105594-invalid-attr-validation.rs:9:1
+  --> $DIR/issue-105594-invalid-attr-validation.rs:6:1
    |
 LL | #[track_caller]
    | ^^^^^^^^^^^^^^^
 LL | static _A: () = ();
    | ------------------- not a function definition
 
-error: attribute should be applied to a function definition
-  --> $DIR/issue-105594-invalid-attr-validation.rs:12:1
-   |
-LL | #[cmse_nonsecure_entry]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-LL | static _B: () = ();
-   | ------------------- not a function definition
-
-error[E0775]: `#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension
-  --> $DIR/issue-105594-invalid-attr-validation.rs:12:1
-   |
-LL | #[cmse_nonsecure_entry]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0739, E0775.
-For more information about an error, try `rustc --explain E0739`.
+For more information about this error, try `rustc --explain E0739`.
diff --git a/tests/ui/binding/order-drop-with-match.rs b/tests/ui/binding/order-drop-with-match.rs
index c12c5e4c627..cd0ff73cf12 100644
--- a/tests/ui/binding/order-drop-with-match.rs
+++ b/tests/ui/binding/order-drop-with-match.rs
@@ -5,6 +5,8 @@
 // in ORDER matching up to when it ran.
 // Correct order is: matched, inner, outer
 
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
 
 static mut ORDER: [usize; 3] = [0, 0, 0];
 static mut INDEX: usize = 0;
diff --git a/tests/ui/borrowck/borrowck-access-permissions.rs b/tests/ui/borrowck/borrowck-access-permissions.rs
index be11286a523..0e9e2bc1354 100644
--- a/tests/ui/borrowck/borrowck-access-permissions.rs
+++ b/tests/ui/borrowck/borrowck-access-permissions.rs
@@ -16,7 +16,6 @@ fn main() {
         let _y1 = &mut static_x; //~ ERROR [E0596]
         unsafe {
             let _y2 = &mut static_x_mut;
-            //~^ WARN mutable reference to mutable static is discouraged [static_mut_refs]
         }
     }
 
diff --git a/tests/ui/borrowck/borrowck-access-permissions.stderr b/tests/ui/borrowck/borrowck-access-permissions.stderr
index 36e259fa6e8..ade10dbbfbd 100644
--- a/tests/ui/borrowck/borrowck-access-permissions.stderr
+++ b/tests/ui/borrowck/borrowck-access-permissions.stderr
@@ -1,18 +1,3 @@
-warning: creating a mutable reference to mutable static is discouraged
-  --> $DIR/borrowck-access-permissions.rs:18:23
-   |
-LL |             let _y2 = &mut static_x_mut;
-   |                       ^^^^^^^^^^^^^^^^^ 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
-   = note: `#[warn(static_mut_refs)]` on by default
-help: use `addr_of_mut!` instead to create a raw pointer
-   |
-LL |             let _y2 = addr_of_mut!(static_x_mut);
-   |                       ~~~~~~~~~~~~~            +
-
 error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
   --> $DIR/borrowck-access-permissions.rs:10:19
    |
@@ -31,7 +16,7 @@ LL |         let _y1 = &mut static_x;
    |                   ^^^^^^^^^^^^^ cannot borrow as mutable
 
 error[E0596]: cannot borrow `*box_x` as mutable, as `box_x` is not declared as mutable
-  --> $DIR/borrowck-access-permissions.rs:28:19
+  --> $DIR/borrowck-access-permissions.rs:27:19
    |
 LL |         let _y1 = &mut *box_x;
    |                   ^^^^^^^^^^^ cannot borrow as mutable
@@ -42,7 +27,7 @@ LL |         let mut box_x = Box::new(1);
    |             +++
 
 error[E0596]: cannot borrow `*ref_x` as mutable, as it is behind a `&` reference
-  --> $DIR/borrowck-access-permissions.rs:37:19
+  --> $DIR/borrowck-access-permissions.rs:36:19
    |
 LL |         let _y1 = &mut *ref_x;
    |                   ^^^^^^^^^^^ `ref_x` is a `&` reference, so the data it refers to cannot be borrowed as mutable
@@ -53,7 +38,7 @@ LL |         let ref_x = &mut x;
    |                      +++
 
 error[E0596]: cannot borrow `*ptr_x` as mutable, as it is behind a `*const` pointer
-  --> $DIR/borrowck-access-permissions.rs:47:23
+  --> $DIR/borrowck-access-permissions.rs:46:23
    |
 LL |             let _y1 = &mut *ptr_x;
    |                       ^^^^^^^^^^^ `ptr_x` is a `*const` pointer, so the data it refers to cannot be borrowed as mutable
@@ -64,7 +49,7 @@ LL |         let ptr_x: *const _ = &mut x;
    |                                +++
 
 error[E0596]: cannot borrow `*foo_ref.f` as mutable, as it is behind a `&` reference
-  --> $DIR/borrowck-access-permissions.rs:60:18
+  --> $DIR/borrowck-access-permissions.rs:59:18
    |
 LL |         let _y = &mut *foo_ref.f;
    |                  ^^^^^^^^^^^^^^^ `foo_ref` is a `&` reference, so the data it refers to cannot be borrowed as mutable
@@ -74,6 +59,6 @@ help: consider changing this to be a mutable reference
 LL |         let foo_ref = &mut foo;
    |                        +++
 
-error: aborting due to 6 previous errors; 1 warning emitted
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr b/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr
index a727c9414c5..e4dfa6d7fba 100644
--- a/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr
+++ b/tests/ui/borrowck/borrowck-unsafe-static-mutable-borrows.stderr
@@ -4,14 +4,13 @@ warning: creating a mutable reference to mutable static is discouraged
 LL |         let sfoo: *mut Foo = &mut SFOO;
    |                              ^^^^^^^^^ 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
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives
    = note: `#[warn(static_mut_refs)]` on by default
-help: use `addr_of_mut!` instead to create a raw pointer
+help: use `&raw mut` instead to create a raw pointer
    |
-LL |         let sfoo: *mut Foo = addr_of_mut!(SFOO);
-   |                              ~~~~~~~~~~~~~    +
+LL |         let sfoo: *mut Foo = &raw mut SFOO;
+   |                              ~~~~~~~~
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/borrowck/issue-20801.rs b/tests/ui/borrowck/issue-20801.rs
index 7e3d3703dc7..c3f136f2876 100644
--- a/tests/ui/borrowck/issue-20801.rs
+++ b/tests/ui/borrowck/issue-20801.rs
@@ -12,7 +12,6 @@ fn imm_ref() -> &'static T {
 
 fn mut_ref() -> &'static mut T {
     unsafe { &mut GLOBAL_MUT_T }
-    //~^ WARN mutable reference to mutable static is discouraged [static_mut_refs]
 }
 
 fn mut_ptr() -> *mut T {
diff --git a/tests/ui/borrowck/issue-20801.stderr b/tests/ui/borrowck/issue-20801.stderr
index 769b34831c1..5fda92634d8 100644
--- a/tests/ui/borrowck/issue-20801.stderr
+++ b/tests/ui/borrowck/issue-20801.stderr
@@ -1,20 +1,5 @@
-warning: creating a mutable reference to mutable static is discouraged
-  --> $DIR/issue-20801.rs:14:14
-   |
-LL |     unsafe { &mut GLOBAL_MUT_T }
-   |              ^^^^^^^^^^^^^^^^^ 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
-   = note: `#[warn(static_mut_refs)]` on by default
-help: use `addr_of_mut!` instead to create a raw pointer
-   |
-LL |     unsafe { addr_of_mut!(GLOBAL_MUT_T) }
-   |              ~~~~~~~~~~~~~            +
-
 error[E0507]: cannot move out of a mutable reference
-  --> $DIR/issue-20801.rs:27:22
+  --> $DIR/issue-20801.rs:26:22
    |
 LL |     let a = unsafe { *mut_ref() };
    |                      ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
@@ -34,7 +19,7 @@ LL +     let a = unsafe { mut_ref() };
    |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/issue-20801.rs:30:22
+  --> $DIR/issue-20801.rs:29:22
    |
 LL |     let b = unsafe { *imm_ref() };
    |                      ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
@@ -54,7 +39,7 @@ LL +     let b = unsafe { imm_ref() };
    |
 
 error[E0507]: cannot move out of a raw pointer
-  --> $DIR/issue-20801.rs:33:22
+  --> $DIR/issue-20801.rs:32:22
    |
 LL |     let c = unsafe { *mut_ptr() };
    |                      ^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
@@ -69,7 +54,7 @@ LL |     let c = unsafe { *mut_ptr() };
    |                      ---------- you could clone this value
 
 error[E0507]: cannot move out of a raw pointer
-  --> $DIR/issue-20801.rs:36:22
+  --> $DIR/issue-20801.rs:35:22
    |
 LL |     let d = unsafe { *const_ptr() };
    |                      ^^^^^^^^^^^^ move occurs because value has type `T`, which does not implement the `Copy` trait
@@ -83,6 +68,6 @@ LL | struct T(u8);
 LL |     let d = unsafe { *const_ptr() };
    |                      ------------ you could clone this value
 
-error: aborting due to 4 previous errors; 1 warning emitted
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0507`.
diff --git a/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs
index c3909d05963..e22bf42e021 100644
--- a/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs
+++ b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.rs
@@ -10,7 +10,6 @@ mod borrowck_closures_unique {
         //~^ ERROR is not declared as mutable
         unsafe {
             c1(&mut Y);
-            //~^ WARN mutable reference to mutable static is discouraged [static_mut_refs]
         }
     }
 }
@@ -25,7 +24,6 @@ mod borrowck_closures_unique_grandparent {
         };
         unsafe {
             c1(&mut Z);
-            //~^ WARN mutable reference to mutable static is discouraged [static_mut_refs]
         }
     }
 }
@@ -62,7 +60,6 @@ fn main() {
     static mut X: isize = 2;
     unsafe {
         borrowck_closures_unique::e(&mut X);
-        //~^ WARN mutable reference to mutable static is discouraged [static_mut_refs]
     }
 
     mutability_errors::capture_assign_whole((1000,));
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 72fd0d8ce16..6fc8d3a6c35 100644
--- a/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr
+++ b/tests/ui/borrowck/issue-55492-borrowck-migrate-scans-parents.stderr
@@ -1,46 +1,3 @@
-warning: creating a mutable reference to mutable static is discouraged
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:12:16
-   |
-LL |             c1(&mut Y);
-   |                ^^^^^^ 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
-   = note: `#[warn(static_mut_refs)]` on by default
-help: use `addr_of_mut!` instead to create a raw pointer
-   |
-LL |             c1(addr_of_mut!(Y));
-   |                ~~~~~~~~~~~~~ +
-
-warning: creating a mutable reference to mutable static is discouraged
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:27:16
-   |
-LL |             c1(&mut Z);
-   |                ^^^^^^ 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 |             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
    |
@@ -53,7 +10,7 @@ LL |     pub fn e(mut x: &'static mut isize) {
    |              +++
 
 error[E0594]: cannot assign to `x`, as it is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:22:50
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:21:50
    |
 LL |             let mut c2 = |y: &'static mut isize| x = y;
    |                                                  ^^^^^ cannot assign
@@ -64,7 +21,7 @@ LL |     pub fn ee(mut x: &'static mut isize) {
    |               +++
 
 error[E0594]: cannot assign to `x`, as it is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:37:13
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:35:13
    |
 LL |             x = (1,);
    |             ^^^^^^^^ cannot assign
@@ -75,7 +32,7 @@ LL |     pub fn capture_assign_whole(mut x: (i32,)) {
    |                                 +++
 
 error[E0594]: cannot assign to `x.0`, as `x` is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:43:13
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:41:13
    |
 LL |             x.0 = 1;
    |             ^^^^^^^ cannot assign
@@ -86,7 +43,7 @@ LL |     pub fn capture_assign_part(mut x: (i32,)) {
    |                                +++
 
 error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:49:13
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:47:13
    |
 LL |             &mut x;
    |             ^^^^^^ cannot borrow as mutable
@@ -97,7 +54,7 @@ LL |     pub fn capture_reborrow_whole(mut x: (i32,)) {
    |                                   +++
 
 error[E0596]: cannot borrow `x.0` as mutable, as `x` is not declared as mutable
-  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:55:13
+  --> $DIR/issue-55492-borrowck-migrate-scans-parents.rs:53:13
    |
 LL |             &mut x.0;
    |             ^^^^^^^^ cannot borrow as mutable
@@ -107,7 +64,7 @@ help: consider changing this to be mutable
 LL |     pub fn capture_reborrow_part(mut x: (i32,)) {
    |                                  +++
 
-error: aborting due to 6 previous errors; 3 warnings emitted
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0594, E0596.
 For more information about an error, try `rustc --explain E0594`.
diff --git a/tests/ui/cfg/cfg-false-feature.rs b/tests/ui/cfg/cfg-false-feature.rs
index 6645f667d7e..716b18492c7 100644
--- a/tests/ui/cfg/cfg-false-feature.rs
+++ b/tests/ui/cfg/cfg-false-feature.rs
@@ -5,7 +5,7 @@
 
 #![feature(decl_macro)]
 #![cfg(FALSE)]
-#![feature(box_syntax)]
+#![feature(box_patterns)]
 
 macro mac() {} // OK
 
diff --git a/tests/ui/check-cfg/raw-keywords.edition2015.stderr b/tests/ui/check-cfg/raw-keywords.edition2015.stderr
new file mode 100644
index 00000000000..ab7e77686ee
--- /dev/null
+++ b/tests/ui/check-cfg/raw-keywords.edition2015.stderr
@@ -0,0 +1,40 @@
+warning: unexpected `cfg` condition name: `tru`
+  --> $DIR/raw-keywords.rs:14:7
+   |
+LL | #[cfg(tru)]
+   |       ^^^ help: there is a config with a similar name: `r#true`
+   |
+   = help: to expect this configuration use `--check-cfg=cfg(tru)`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+   = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: unexpected `cfg` condition name: `r#false`
+  --> $DIR/raw-keywords.rs:19:7
+   |
+LL | #[cfg(r#false)]
+   |       ^^^^^^^
+   |
+   = help: expected names are: `async`, `clippy`, `debug_assertions`, `doc`, `doctest`, `edition2015`, `edition2021`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `r#true`, `ub_checks`, `unix`, and `windows`
+   = help: to expect this configuration use `--check-cfg=cfg(r#false)`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+
+warning: unexpected `cfg` condition name: `await`
+  --> $DIR/raw-keywords.rs:27:29
+   |
+LL | #[cfg_attr(edition2015, cfg(await))]
+   |                             ^^^^^
+   |
+   = help: to expect this configuration use `--check-cfg=cfg(await)`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+
+warning: unexpected `cfg` condition name: `raw`
+  --> $DIR/raw-keywords.rs:33:7
+   |
+LL | #[cfg(r#raw)]
+   |       ^^^^^
+   |
+   = help: to expect this configuration use `--check-cfg=cfg(raw)`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+
+warning: 4 warnings emitted
+
diff --git a/tests/ui/check-cfg/raw-keywords.edition2021.stderr b/tests/ui/check-cfg/raw-keywords.edition2021.stderr
new file mode 100644
index 00000000000..1ae1cad4e6b
--- /dev/null
+++ b/tests/ui/check-cfg/raw-keywords.edition2021.stderr
@@ -0,0 +1,40 @@
+warning: unexpected `cfg` condition name: `tru`
+  --> $DIR/raw-keywords.rs:14:7
+   |
+LL | #[cfg(tru)]
+   |       ^^^ help: there is a config with a similar name: `r#true`
+   |
+   = help: to expect this configuration use `--check-cfg=cfg(tru)`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+   = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: unexpected `cfg` condition name: `r#false`
+  --> $DIR/raw-keywords.rs:19:7
+   |
+LL | #[cfg(r#false)]
+   |       ^^^^^^^
+   |
+   = help: expected names are: `r#async`, `clippy`, `debug_assertions`, `doc`, `doctest`, `edition2015`, `edition2021`, `fmt_debug`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `rustfmt`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `r#true`, `ub_checks`, `unix`, and `windows`
+   = help: to expect this configuration use `--check-cfg=cfg(r#false)`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+
+warning: unexpected `cfg` condition name: `r#await`
+  --> $DIR/raw-keywords.rs:28:29
+   |
+LL | #[cfg_attr(edition2021, cfg(r#await))]
+   |                             ^^^^^^^
+   |
+   = help: to expect this configuration use `--check-cfg=cfg(r#await)`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+
+warning: unexpected `cfg` condition name: `raw`
+  --> $DIR/raw-keywords.rs:33:7
+   |
+LL | #[cfg(r#raw)]
+   |       ^^^^^
+   |
+   = help: to expect this configuration use `--check-cfg=cfg(raw)`
+   = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
+
+warning: 4 warnings emitted
+
diff --git a/tests/ui/check-cfg/raw-keywords.rs b/tests/ui/check-cfg/raw-keywords.rs
new file mode 100644
index 00000000000..5de13240d7e
--- /dev/null
+++ b/tests/ui/check-cfg/raw-keywords.rs
@@ -0,0 +1,40 @@
+// This test check that using raw keywords works with --cfg and --check-cfg
+// and that the diagnostics suggestions are coherent
+//
+//@ check-pass
+//@ no-auto-check-cfg
+//@ compile-flags: --cfg=true --cfg=async --check-cfg=cfg(r#true,r#async,edition2015,edition2021)
+//
+//@ revisions: edition2015 edition2021
+//@ [edition2021] compile-flags: --edition 2021
+
+#[cfg(r#true)]
+fn foo() {}
+
+#[cfg(tru)]
+//~^ WARNING unexpected `cfg` condition name: `tru`
+//~^^ SUGGESTION r#true
+fn foo() {}
+
+#[cfg(r#false)]
+//~^ WARNING unexpected `cfg` condition name: `r#false`
+fn foo() {}
+
+#[cfg_attr(edition2015, cfg(async))]
+#[cfg_attr(edition2021, cfg(r#async))]
+fn bar() {}
+
+#[cfg_attr(edition2015, cfg(await))]
+#[cfg_attr(edition2021, cfg(r#await))]
+//[edition2015]~^^ WARNING unexpected `cfg` condition name: `await`
+//[edition2021]~^^ WARNING unexpected `cfg` condition name: `r#await`
+fn zoo() {}
+
+#[cfg(r#raw)]
+//~^ WARNING unexpected `cfg` condition name: `raw`
+fn foo() {}
+
+fn main() {
+    foo();
+    bar();
+}
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/callback-as-argument.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/callback-as-argument.rs
new file mode 100644
index 00000000000..37c8319d98d
--- /dev/null
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/callback-as-argument.rs
@@ -0,0 +1,20 @@
+//@ build-pass
+//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
+//@ needs-llvm-components: arm
+#![feature(abi_c_cmse_nonsecure_call, cmse_nonsecure_entry, no_core, lang_items, intrinsics)]
+#![no_core]
+#[lang = "sized"]
+pub trait Sized {}
+#[lang = "copy"]
+pub trait Copy {}
+impl Copy for u32 {}
+
+#[no_mangle]
+pub extern "C-cmse-nonsecure-entry" fn test(
+    f: extern "C-cmse-nonsecure-call" fn(u32, u32, u32, u32) -> u32,
+    a: u32,
+    b: u32,
+    c: u32,
+) -> u32 {
+    f(a, b, c, 42)
+}
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs
index 02d5f20febc..6061451b2e9 100644
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.rs
@@ -1,10 +1,9 @@
 // gate-test-cmse_nonsecure_entry
 
 #[no_mangle]
-#[cmse_nonsecure_entry]
-//~^ ERROR [E0775]
-//~| ERROR [E0658]
-pub extern "C" fn entry_function(input: u32) -> u32 {
+pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 {
+    //~^ ERROR [E0570]
+    //~| ERROR [E0658]
     input + 6
 }
 
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr
index beb9716d590..dabf16cab30 100644
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr
@@ -1,20 +1,20 @@
-error[E0658]: the `#[cmse_nonsecure_entry]` attribute is an experimental feature
-  --> $DIR/gate_test.rs:4:1
+error[E0658]: C-cmse-nonsecure-entry ABI is experimental and subject to change
+  --> $DIR/gate_test.rs:4:12
    |
-LL | #[cmse_nonsecure_entry]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
+LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 {
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: see issue #75835 <https://github.com/rust-lang/rust/issues/75835> for more information
    = help: add `#![feature(cmse_nonsecure_entry)]` 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[E0775]: `#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension
+error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target
   --> $DIR/gate_test.rs:4:1
    |
-LL | #[cmse_nonsecure_entry]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
+LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0658, E0775.
-For more information about an error, try `rustc --explain E0658`.
+Some errors have detailed explanations: E0570, E0658.
+For more information about an error, try `rustc --explain E0570`.
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs
deleted file mode 100644
index a839406cd0a..00000000000
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-// Regression test for the ICE described in #83475.
-
-#![crate_type="lib"]
-
-#![feature(cmse_nonsecure_entry)]
-#[cmse_nonsecure_entry]
-//~^ ERROR: attribute should be applied to a function definition
-struct XEmpty2;
-//~^ NOTE: not a function definition
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr
deleted file mode 100644
index 26d3bfe7837..00000000000
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/issue-83475.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error: attribute should be applied to a function definition
-  --> $DIR/issue-83475.rs:6:1
-   |
-LL | #[cmse_nonsecure_entry]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-LL |
-LL | struct XEmpty2;
-   | --------------- not a function definition
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs
index e197f94096d..de6888fae62 100644
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-registers.rs
@@ -3,14 +3,14 @@
 //@ needs-llvm-components: arm
 #![feature(cmse_nonsecure_entry, no_core, lang_items)]
 #![no_core]
-#[lang="sized"]
-trait Sized { }
-#[lang="copy"]
-trait Copy { }
+#![crate_type = "lib"]
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
 impl Copy for u32 {}
 
 #[no_mangle]
-#[cmse_nonsecure_entry]
-pub extern "C" fn entry_function(_: u32, _: u32, _: u32, d: u32) -> u32 {
+pub extern "C-cmse-nonsecure-entry" fn entry_function(_: u32, _: u32, _: u32, d: u32) -> u32 {
     d
 }
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs
index e2da3ebb6ae..4413c461c04 100644
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/params-on-stack.rs
@@ -3,14 +3,19 @@
 //@ needs-llvm-components: arm
 #![feature(cmse_nonsecure_entry, no_core, lang_items)]
 #![no_core]
-#[lang="sized"]
-trait Sized { }
-#[lang="copy"]
-trait Copy { }
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
 impl Copy for u32 {}
 
 #[no_mangle]
-#[cmse_nonsecure_entry]
-pub extern "C" fn entry_function(_: u32, _: u32, _: u32, _: u32, e: u32) -> u32 {
+pub extern "C-cmse-nonsecure-entry" fn entry_function(
+    _: u32,
+    _: u32,
+    _: u32,
+    _: u32,
+    e: u32,
+) -> u32 {
     e
 }
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.aarch64.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.aarch64.stderr
new file mode 100644
index 00000000000..26409279fbe
--- /dev/null
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.aarch64.stderr
@@ -0,0 +1,9 @@
+error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target
+  --> $DIR/trustzone-only.rs:20:1
+   |
+LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0570`.
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs
index 87eccb4fc6e..a4ea7a1757d 100644
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.rs
@@ -1,10 +1,25 @@
-//@ ignore-thumbv8m.main-none-eabi
-#![feature(cmse_nonsecure_entry)]
+//@ revisions: x86 aarch64 thumb7
+//
+//@[x86] compile-flags: --target x86_64-unknown-linux-gnu
+//@[x86] needs-llvm-components: x86
+//@[aarch64] compile-flags: --target aarch64-unknown-linux-gnu
+//@[aarch64] needs-llvm-components: aarch64
+//@[thumb7] compile-flags: --target thumbv7em-none-eabi
+//@[thumb7] needs-llvm-components: arm
+#![feature(no_core, lang_items, rustc_attrs, cmse_nonsecure_entry)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+impl Copy for u32 {}
 
 #[no_mangle]
-#[cmse_nonsecure_entry] //~ ERROR [E0775]
-pub extern "C" fn entry_function(input: u32) -> u32 {
-    input + 6
+pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 {
+    //~^ ERROR [E0570]
+    input
 }
 
 fn main() {}
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr
deleted file mode 100644
index 3e6954394f4..00000000000
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0775]: `#[cmse_nonsecure_entry]` is only valid for targets with the TrustZone-M extension
-  --> $DIR/trustzone-only.rs:5:1
-   |
-LL | #[cmse_nonsecure_entry]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0775`.
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.thumb7.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.thumb7.stderr
new file mode 100644
index 00000000000..26409279fbe
--- /dev/null
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.thumb7.stderr
@@ -0,0 +1,9 @@
+error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target
+  --> $DIR/trustzone-only.rs:20:1
+   |
+LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0570`.
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.x86.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.x86.stderr
new file mode 100644
index 00000000000..26409279fbe
--- /dev/null
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/trustzone-only.x86.stderr
@@ -0,0 +1,9 @@
+error[E0570]: `"C-cmse-nonsecure-entry"` is not a supported ABI for the current target
+  --> $DIR/trustzone-only.rs:20:1
+   |
+LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0570`.
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs
deleted file mode 100644
index db4f90e9923..00000000000
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.rs
+++ /dev/null
@@ -1,16 +0,0 @@
-//@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib
-//@ needs-llvm-components: arm
-#![feature(cmse_nonsecure_entry, no_core, lang_items)]
-#![no_core]
-#[lang = "sized"]
-trait Sized {}
-
-#[lang = "copy"]
-trait Copy {}
-
-#[no_mangle]
-#[cmse_nonsecure_entry]
-//~^ ERROR `#[cmse_nonsecure_entry]` requires C ABI [E0776]
-pub fn entry_function(_: u32, _: u32, _: u32, d: u32) -> u32 {
-    d
-}
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr
deleted file mode 100644
index c3fae3d8bbb..00000000000
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/wrong-abi.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-error[E0776]: `#[cmse_nonsecure_entry]` requires C ABI
-  --> $DIR/wrong-abi.rs:12:1
-   |
-LL | #[cmse_nonsecure_entry]
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0776`.
diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro-braced-expansion.rs b/tests/ui/const-generics/early/trivial-const-arg-macro-braced-expansion.rs
new file mode 100644
index 00000000000..33630205369
--- /dev/null
+++ b/tests/ui/const-generics/early/trivial-const-arg-macro-braced-expansion.rs
@@ -0,0 +1,14 @@
+macro_rules! y {
+    () => {
+        N
+    };
+}
+
+struct A<const N: usize>;
+
+fn foo<const N: usize>() -> A<{ y!() }> {
+    A::<1>
+    //~^ ERROR: mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro-braced-expansion.stderr b/tests/ui/const-generics/early/trivial-const-arg-macro-braced-expansion.stderr
new file mode 100644
index 00000000000..4461477f3e9
--- /dev/null
+++ b/tests/ui/const-generics/early/trivial-const-arg-macro-braced-expansion.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/trivial-const-arg-macro-braced-expansion.rs:10:5
+   |
+LL | fn foo<const N: usize>() -> A<{ y!() }> {
+   |                             ----------- expected `A<N>` because of return type
+LL |     A::<1>
+   |     ^^^^^^ expected `N`, found `1`
+   |
+   = note: expected struct `A<N>`
+              found struct `A<1>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces-2.rs b/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces-2.rs
new file mode 100644
index 00000000000..5a9e62561dc
--- /dev/null
+++ b/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces-2.rs
@@ -0,0 +1,15 @@
+macro_rules! y {
+    () => {
+        N
+        //~^ ERROR: generic parameters may not be used in const operations
+    };
+}
+
+struct A<const N: usize>;
+
+#[rustfmt::skip]
+fn foo<const N: usize>() -> A<{{ y!() }}> {
+    A::<1>
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces-2.stderr b/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces-2.stderr
new file mode 100644
index 00000000000..e40d05924b1
--- /dev/null
+++ b/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces-2.stderr
@@ -0,0 +1,15 @@
+error: generic parameters may not be used in const operations
+  --> $DIR/trivial-const-arg-macro-nested-braces-2.rs:3:9
+   |
+LL |         N
+   |         ^ cannot perform const operation using `N`
+...
+LL | fn foo<const N: usize>() -> A<{{ y!() }}> {
+   |                                  ---- in this macro invocation
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
+   = note: this error originates in the macro `y` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces.rs b/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces.rs
new file mode 100644
index 00000000000..45c0768dde4
--- /dev/null
+++ b/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces.rs
@@ -0,0 +1,15 @@
+#[rustfmt::skip]
+macro_rules! y {
+    () => {
+        { N }
+        //~^ ERROR: generic parameters may not be used in const operations
+    };
+}
+
+struct A<const N: usize>;
+
+fn foo<const N: usize>() -> A<{ y!() }> {
+    A::<1>
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces.stderr b/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces.stderr
new file mode 100644
index 00000000000..b91d6c7a024
--- /dev/null
+++ b/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces.stderr
@@ -0,0 +1,15 @@
+error: generic parameters may not be used in const operations
+  --> $DIR/trivial-const-arg-macro-nested-braces.rs:4:11
+   |
+LL |         { N }
+   |           ^ cannot perform const operation using `N`
+...
+LL | fn foo<const N: usize>() -> A<{ y!() }> {
+   |                                 ---- in this macro invocation
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
+   = note: this error originates in the macro `y` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/const-generics/early/trivial-const-arg-nested-braces.rs b/tests/ui/const-generics/early/trivial-const-arg-nested-braces.rs
new file mode 100644
index 00000000000..941ba6bfea7
--- /dev/null
+++ b/tests/ui/const-generics/early/trivial-const-arg-nested-braces.rs
@@ -0,0 +1,9 @@
+struct A<const N: usize>;
+
+#[rustfmt::skip]
+fn foo<const N: usize>() -> A<{ { N } }> {
+    //~^ ERROR: generic parameters may not be used in const operations
+    A::<1>
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/early/trivial-const-arg-nested-braces.stderr b/tests/ui/const-generics/early/trivial-const-arg-nested-braces.stderr
new file mode 100644
index 00000000000..d60516ba4bc
--- /dev/null
+++ b/tests/ui/const-generics/early/trivial-const-arg-nested-braces.stderr
@@ -0,0 +1,11 @@
+error: generic parameters may not be used in const operations
+  --> $DIR/trivial-const-arg-nested-braces.rs:4:35
+   |
+LL | fn foo<const N: usize>() -> A<{ { N } }> {
+   |                                   ^ cannot perform const operation using `N`
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-109141.rs b/tests/ui/const-generics/generic_const_exprs/issue-109141.rs
index c6dd981cced..5303b247173 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-109141.rs
+++ b/tests/ui/const-generics/generic_const_exprs/issue-109141.rs
@@ -3,8 +3,7 @@
 
 impl EntriesBuffer {
     fn a(&self) -> impl Iterator {
-        self.0.iter_mut() //~ ERROR: cannot borrow `*self.0` as mutable, as it is behind a `&` reference
-                          //~| ERROR captures lifetime that does not appear in bounds
+        self.0.iter_mut()
     }
 }
 
diff --git a/tests/ui/const-generics/generic_const_exprs/issue-109141.stderr b/tests/ui/const-generics/generic_const_exprs/issue-109141.stderr
index 24f3ed7cdf1..fcbd6904599 100644
--- a/tests/ui/const-generics/generic_const_exprs/issue-109141.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/issue-109141.stderr
@@ -1,5 +1,5 @@
 error[E0425]: cannot find value `HashesEntryLEN` in this scope
-  --> $DIR/issue-109141.rs:11:32
+  --> $DIR/issue-109141.rs:10:32
    |
 LL | struct EntriesBuffer(Box<[[u8; HashesEntryLEN]; 5]>);
    |                                ^^^^^^^^^^^^^^ not found in this scope
@@ -9,33 +9,6 @@ help: you might be missing a const parameter
 LL | struct EntriesBuffer<const HashesEntryLEN: /* Type */>(Box<[[u8; HashesEntryLEN]; 5]>);
    |                     ++++++++++++++++++++++++++++++++++
 
-error[E0596]: cannot borrow `*self.0` as mutable, as it is behind a `&` reference
-  --> $DIR/issue-109141.rs:6:9
-   |
-LL |         self.0.iter_mut()
-   |         ^^^^^^ `self` is a `&` reference, so the data it refers to cannot be borrowed as mutable
-   |
-help: consider changing this to be a mutable reference
-   |
-LL |     fn a(&mut self) -> impl Iterator {
-   |          ~~~~~~~~~
-
-error[E0700]: hidden type for `impl Iterator` captures lifetime that does not appear in bounds
-  --> $DIR/issue-109141.rs:6:9
-   |
-LL |     fn a(&self) -> impl Iterator {
-   |          -----     ------------- opaque type defined here
-   |          |
-   |          hidden type `std::slice::IterMut<'_, [u8; {const error}]>` captures the anonymous lifetime defined here
-LL |         self.0.iter_mut()
-   |         ^^^^^^^^^^^^^^^^^
-   |
-help: add a `use<...>` bound to explicitly capture `'_`
-   |
-LL |     fn a(&self) -> impl Iterator + use<'_> {
-   |                                  +++++++++
-
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0425, E0596, E0700.
-For more information about an error, try `rustc --explain E0425`.
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/const-generics/generic_const_exprs/opaque_type.rs b/tests/ui/const-generics/generic_const_exprs/opaque_type.rs
index 7209290a36e..56b8acbf88c 100644
--- a/tests/ui/const-generics/generic_const_exprs/opaque_type.rs
+++ b/tests/ui/const-generics/generic_const_exprs/opaque_type.rs
@@ -2,7 +2,6 @@
 #![allow(incomplete_features)]
 
 type Foo = impl Sized;
-//~^ ERROR: unconstrained opaque type
 
 fn with_bound<const N: usize>() -> Foo
 where
diff --git a/tests/ui/const-generics/generic_const_exprs/opaque_type.stderr b/tests/ui/const-generics/generic_const_exprs/opaque_type.stderr
index c7a266205b4..e9fb8c0f403 100644
--- a/tests/ui/const-generics/generic_const_exprs/opaque_type.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/opaque_type.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/opaque_type.rs:11:17
+  --> $DIR/opaque_type.rs:10:17
    |
 LL | type Foo = impl Sized;
    |            ---------- the found opaque type
@@ -11,20 +11,12 @@ LL |     let _: [u8; (N / 2) as Foo] = [0; (N / 2) as usize];
            found opaque type `Foo`
 
 error[E0605]: non-primitive cast: `usize` as `Foo`
-  --> $DIR/opaque_type.rs:11:17
+  --> $DIR/opaque_type.rs:10:17
    |
 LL |     let _: [u8; (N / 2) as Foo] = [0; (N / 2) as usize];
    |                 ^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
-error: unconstrained opaque type
-  --> $DIR/opaque_type.rs:4:12
-   |
-LL | type Foo = impl Sized;
-   |            ^^^^^^^^^^
-   |
-   = note: `Foo` must be used in combination with a concrete type within the same module
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0308, E0605.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/const-generics/issue-112505-overflow.rs b/tests/ui/const-generics/issue-112505-overflow.rs
deleted file mode 100644
index 0dd7776d595..00000000000
--- a/tests/ui/const-generics/issue-112505-overflow.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-#![feature(transmute_generic_consts)]
-
-fn overflow(v: [[[u32; 8888888]; 9999999]; 777777777]) -> [[[u32; 9999999]; 777777777]; 239] {
-    unsafe { std::mem::transmute(v) } //~ ERROR cannot transmute between types of different sizes
-}
-
-fn main() { }
diff --git a/tests/ui/const-generics/issue-112505-overflow.stderr b/tests/ui/const-generics/issue-112505-overflow.stderr
deleted file mode 100644
index 0bd3f6eddd4..00000000000
--- a/tests/ui/const-generics/issue-112505-overflow.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/issue-112505-overflow.rs:4:14
-   |
-LL |     unsafe { 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]; 239]` (values of the type `[[u32; 9999999]; 777777777]` are too big for the current architecture)
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0512`.
diff --git a/tests/ui/const-generics/transmute-fail.rs b/tests/ui/const-generics/transmute-fail.rs
index 7faf670e468..95c71160567 100644
--- a/tests/ui/const-generics/transmute-fail.rs
+++ b/tests/ui/const-generics/transmute-fail.rs
@@ -1,3 +1,8 @@
+// ignore-tidy-linelength
+//@ normalize-stderr-32bit: "values of the type `[^`]+` are too big" -> "values of the type $$REALLY_TOO_BIG are too big"
+//@ normalize-stderr-64bit: "values of the type `[^`]+` are too big" -> "values of the type $$REALLY_TOO_BIG are too big"
+
+
 #![feature(transmute_generic_consts)]
 #![feature(generic_const_exprs)]
 #![allow(incomplete_features)]
@@ -31,6 +36,11 @@ fn overflow(v: [[[u32; 8888888]; 9999999]; 777777777]) -> [[[u32; 9999999]; 7777
     }
 }
 
+fn overflow_more(v: [[[u32; 8888888]; 9999999]; 777777777]) -> [[[u32; 9999999]; 777777777]; 239] {
+    unsafe { std::mem::transmute(v) } //~ ERROR cannot transmute between types of different sizes
+}
+
+
 fn transpose<const W: usize, const H: usize>(v: [[u32; H]; W]) -> [[u32; W]; H] {
     unsafe {
         std::mem::transmute(v)
diff --git a/tests/ui/const-generics/transmute-fail.stderr b/tests/ui/const-generics/transmute-fail.stderr
index 4a20034910d..638ce790345 100644
--- a/tests/ui/const-generics/transmute-fail.stderr
+++ b/tests/ui/const-generics/transmute-fail.stderr
@@ -1,11 +1,11 @@
 error: the constant `W` is not of type `usize`
-  --> $DIR/transmute-fail.rs:12:42
+  --> $DIR/transmute-fail.rs:17:42
    |
 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:7:9
+  --> $DIR/transmute-fail.rs:12:9
    |
 LL |         std::mem::transmute(v)
    |         ^^^^^^^^^^^^^^^^^^^
@@ -14,13 +14,13 @@ LL |         std::mem::transmute(v)
    = note: target type: `[[u32; W + 1]; H]` (size can vary because of [u32; W + 1])
 
 error: the constant `W` is not of type `usize`
-  --> $DIR/transmute-fail.rs:15:9
+  --> $DIR/transmute-fail.rs:20:9
    |
 LL |         std::mem::transmute(v)
    |         ^^^^^^^^^^^^^^^^^^^ expected `usize`, found `bool`
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:22:9
+  --> $DIR/transmute-fail.rs:27:9
    |
 LL |         std::mem::transmute(v)
    |         ^^^^^^^^^^^^^^^^^^^
@@ -29,16 +29,25 @@ LL |         std::mem::transmute(v)
    = note: target type: `[u32; W * H * H]` (this type does not have a fixed size)
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:29:9
+  --> $DIR/transmute-fail.rs:34:9
    |
 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)
+   = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type $REALLY_TOO_BIG are too big for the target architecture)
+   = note: target type: `[[[u32; 9999999]; 777777777]; 8888888]` (values of the type $REALLY_TOO_BIG are too big for the target architecture)
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:36:9
+  --> $DIR/transmute-fail.rs:40:14
+   |
+LL |     unsafe { std::mem::transmute(v) }
+   |              ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `[[[u32; 8888888]; 9999999]; 777777777]` (values of the type $REALLY_TOO_BIG are too big for the target architecture)
+   = note: target type: `[[[u32; 9999999]; 777777777]; 239]` (values of the type $REALLY_TOO_BIG are too big for the target architecture)
+
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/transmute-fail.rs:46:9
    |
 LL |         std::mem::transmute(v)
    |         ^^^^^^^^^^^^^^^^^^^
@@ -47,7 +56,7 @@ LL |         std::mem::transmute(v)
    = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W])
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:47:9
+  --> $DIR/transmute-fail.rs:57:9
    |
 LL |         std::mem::transmute(v)
    |         ^^^^^^^^^^^^^^^^^^^
@@ -56,7 +65,7 @@ LL |         std::mem::transmute(v)
    = note: target type: `[u32; W * H]` (this type does not have a fixed size)
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:54:9
+  --> $DIR/transmute-fail.rs:64:9
    |
 LL |         std::mem::transmute(v)
    |         ^^^^^^^^^^^^^^^^^^^
@@ -65,7 +74,7 @@ LL |         std::mem::transmute(v)
    = note: target type: `[[u32; W]; H]` (size can vary because of [u32; W])
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:63:9
+  --> $DIR/transmute-fail.rs:73:9
    |
 LL |         std::mem::transmute(v)
    |         ^^^^^^^^^^^^^^^^^^^
@@ -74,7 +83,7 @@ LL |         std::mem::transmute(v)
    = note: target type: `[u32; D * W * H]` (this type does not have a fixed size)
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:72:9
+  --> $DIR/transmute-fail.rs:82:9
    |
 LL |         std::mem::transmute(v)
    |         ^^^^^^^^^^^^^^^^^^^
@@ -83,7 +92,7 @@ LL |         std::mem::transmute(v)
    = note: target type: `[[u32; D * W]; H]` (size can vary because of [u32; D * W])
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:79:9
+  --> $DIR/transmute-fail.rs:89:9
    |
 LL |         std::mem::transmute(v)
    |         ^^^^^^^^^^^^^^^^^^^
@@ -92,7 +101,7 @@ LL |         std::mem::transmute(v)
    = note: target type: `[u8; L * 2]` (this type does not have a fixed size)
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:86:9
+  --> $DIR/transmute-fail.rs:96:9
    |
 LL |         std::mem::transmute(v)
    |         ^^^^^^^^^^^^^^^^^^^
@@ -101,7 +110,7 @@ LL |         std::mem::transmute(v)
    = note: target type: `[u16; L]` (this type does not have a fixed size)
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:93:9
+  --> $DIR/transmute-fail.rs:103:9
    |
 LL |         std::mem::transmute(v)
    |         ^^^^^^^^^^^^^^^^^^^
@@ -110,7 +119,7 @@ LL |         std::mem::transmute(v)
    = note: target type: `[[u8; 1]; L]` (this type does not have a fixed size)
 
 error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
-  --> $DIR/transmute-fail.rs:102:9
+  --> $DIR/transmute-fail.rs:112:9
    |
 LL |         std::mem::transmute(v)
    |         ^^^^^^^^^^^^^^^^^^^
@@ -118,6 +127,6 @@ LL |         std::mem::transmute(v)
    = note: source type: `[[u32; 2 * H]; W + W]` (size can vary because of [u32; 2 * H])
    = note: target type: `[[u32; W + W]; 2 * H]` (size can vary because of [u32; W + W])
 
-error: aborting due to 14 previous errors
+error: aborting due to 15 previous errors
 
 For more information about this error, try `rustc --explain E0512`.
diff --git a/tests/ui/consts/const-eval/stable-metric/evade-deduplication-issue-118612.rs b/tests/ui/consts/const-eval/stable-metric/evade-deduplication-issue-118612.rs
new file mode 100644
index 00000000000..a2d34eaa384
--- /dev/null
+++ b/tests/ui/consts/const-eval/stable-metric/evade-deduplication-issue-118612.rs
@@ -0,0 +1,24 @@
+//@ check-pass
+
+#![allow(long_running_const_eval)]
+
+//@ compile-flags: -Z tiny-const-eval-limit -Z deduplicate-diagnostics=yes
+const FOO: () = {
+    let mut i = 0;
+    loop {
+        //~^ WARN is taking a long time
+        //~| WARN is taking a long time
+        //~| WARN is taking a long time
+        //~| WARN is taking a long time
+        //~| WARN is taking a long time
+        if i == 1000 {
+            break;
+        } else {
+            i += 1;
+        }
+    }
+};
+
+fn main() {
+    FOO
+}
diff --git a/tests/ui/consts/const-eval/stable-metric/evade-deduplication-issue-118612.stderr b/tests/ui/consts/const-eval/stable-metric/evade-deduplication-issue-118612.stderr
new file mode 100644
index 00000000000..cb19c59b15b
--- /dev/null
+++ b/tests/ui/consts/const-eval/stable-metric/evade-deduplication-issue-118612.stderr
@@ -0,0 +1,92 @@
+warning: constant evaluation is taking a long time
+  --> $DIR/evade-deduplication-issue-118612.rs:8:5
+   |
+LL | /     loop {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |         }
+LL | |     }
+   | |_____^ the const evaluator is currently interpreting this expression
+   |
+help: the constant being evaluated
+  --> $DIR/evade-deduplication-issue-118612.rs:6:1
+   |
+LL | const FOO: () = {
+   | ^^^^^^^^^^^^^
+
+warning: constant evaluation is taking a long time
+  --> $DIR/evade-deduplication-issue-118612.rs:8:5
+   |
+LL | /     loop {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |         }
+LL | |     }
+   | |_____^ the const evaluator is currently interpreting this expression
+   |
+help: the constant being evaluated
+  --> $DIR/evade-deduplication-issue-118612.rs:6:1
+   |
+LL | const FOO: () = {
+   | ^^^^^^^^^^^^^
+
+warning: constant evaluation is taking a long time
+  --> $DIR/evade-deduplication-issue-118612.rs:8:5
+   |
+LL | /     loop {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |         }
+LL | |     }
+   | |_____^ the const evaluator is currently interpreting this expression
+   |
+help: the constant being evaluated
+  --> $DIR/evade-deduplication-issue-118612.rs:6:1
+   |
+LL | const FOO: () = {
+   | ^^^^^^^^^^^^^
+
+warning: constant evaluation is taking a long time
+  --> $DIR/evade-deduplication-issue-118612.rs:8:5
+   |
+LL | /     loop {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |         }
+LL | |     }
+   | |_____^ the const evaluator is currently interpreting this expression
+   |
+help: the constant being evaluated
+  --> $DIR/evade-deduplication-issue-118612.rs:6:1
+   |
+LL | const FOO: () = {
+   | ^^^^^^^^^^^^^
+
+warning: constant evaluation is taking a long time
+  --> $DIR/evade-deduplication-issue-118612.rs:8:5
+   |
+LL | /     loop {
+LL | |
+LL | |
+LL | |
+...  |
+LL | |         }
+LL | |     }
+   | |_____^ the const evaluator is currently interpreting this expression
+   |
+help: the constant being evaluated
+  --> $DIR/evade-deduplication-issue-118612.rs:6:1
+   |
+LL | const FOO: () = {
+   | ^^^^^^^^^^^^^
+
+warning: 5 warnings emitted
+
diff --git a/tests/ui/consts/const_let_assign2.stderr b/tests/ui/consts/const_let_assign2.stderr
index 87b94a7be67..9a1b84dbf09 100644
--- a/tests/ui/consts/const_let_assign2.stderr
+++ b/tests/ui/consts/const_let_assign2.stderr
@@ -4,14 +4,13 @@ warning: creating a mutable reference to mutable static is discouraged
 LL |     let ptr = unsafe { &mut BB };
    |                        ^^^^^^^ 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
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives
    = note: `#[warn(static_mut_refs)]` on by default
-help: use `addr_of_mut!` instead to create a raw pointer
+help: use `&raw mut` instead to create a raw pointer
    |
-LL |     let ptr = unsafe { addr_of_mut!(BB) };
-   |                        ~~~~~~~~~~~~~  +
+LL |     let ptr = unsafe { &raw mut BB };
+   |                        ~~~~~~~~
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/consts/issue-116186.rs b/tests/ui/consts/issue-116186.rs
index a77c38c64dc..8bfb47629e7 100644
--- a/tests/ui/consts/issue-116186.rs
+++ b/tests/ui/consts/issue-116186.rs
@@ -4,7 +4,7 @@
 fn something(path: [usize; N]) -> impl Clone {
     //~^ ERROR cannot find value `N` in this scope
     match path {
-        [] => 0, //~ ERROR cannot pattern-match on an array without a fixed length
+        [] => 0,
         _ => 1,
     };
 }
diff --git a/tests/ui/consts/issue-116186.stderr b/tests/ui/consts/issue-116186.stderr
index e6eae2d9f55..46931f79dd0 100644
--- a/tests/ui/consts/issue-116186.stderr
+++ b/tests/ui/consts/issue-116186.stderr
@@ -9,13 +9,6 @@ help: you might be missing a const parameter
 LL | fn something<const N: /* Type */>(path: [usize; N]) -> impl Clone {
    |             +++++++++++++++++++++
 
-error[E0730]: cannot pattern-match on an array without a fixed length
-  --> $DIR/issue-116186.rs:7:9
-   |
-LL |         [] => 0,
-   |         ^^
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0425, E0730.
-For more information about an error, try `rustc --explain E0425`.
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/consts/static-mut-refs.rs b/tests/ui/consts/static-mut-refs.rs
index d4ebfbbf17a..c0d0bb61332 100644
--- a/tests/ui/consts/static-mut-refs.rs
+++ b/tests/ui/consts/static-mut-refs.rs
@@ -1,6 +1,9 @@
 //@ run-pass
 #![allow(dead_code)]
 
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
 // Checks that mutable static items can have mutable slices and other references
 
 
diff --git a/tests/ui/coroutine/static-mut-reference-across-yield.rs b/tests/ui/coroutine/static-mut-reference-across-yield.rs
index 40d5fdf2d57..d45d6e6428b 100644
--- a/tests/ui/coroutine/static-mut-reference-across-yield.rs
+++ b/tests/ui/coroutine/static-mut-reference-across-yield.rs
@@ -1,6 +1,8 @@
 //@ build-pass
 
 #![feature(coroutines, stmt_expr_attributes)]
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
 
 static mut A: [i32; 5] = [1, 2, 3, 4, 5];
 
diff --git a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.rs b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.rs
index dc68f6cf71f..a1922c98ef6 100644
--- a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.rs
+++ b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.rs
@@ -3,7 +3,7 @@
 
 //@ compile-flags:-C debuginfo=2
 //@ build-fail
-//@ error-pattern: too big for the current architecture
+//@ error-pattern: too big for the target architecture
 //@ normalize-stderr-64bit: "18446744073709551615" -> "SIZE"
 //@ normalize-stderr-32bit: "4294967295" -> "SIZE"
 
diff --git a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.stderr b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.stderr
index 06aad9616cb..a3772e509ed 100644
--- a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.stderr
+++ b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-1.stderr
@@ -1,4 +1,4 @@
-error: values of the type `[u8; usize::MAX]` are too big for the current architecture
+error: values of the type `[u8; usize::MAX]` are too big for the target architecture
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs
index 2b6e85362b6..3456cd55b75 100644
--- a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs
+++ b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.rs
@@ -5,7 +5,7 @@
 
 //@ compile-flags:-C debuginfo=2
 //@ build-fail
-//@ error-pattern: too big for the current architecture
+//@ error-pattern: too big for the target architecture
 //@ normalize-stderr-64bit: "18446744073709551615" -> "SIZE"
 //@ normalize-stderr-32bit: "4294967295" -> "SIZE"
 
diff --git a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.stderr b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.stderr
index 06aad9616cb..a3772e509ed 100644
--- a/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.stderr
+++ b/tests/ui/debuginfo/debuginfo-type-name-layout-ice-94961-2.stderr
@@ -1,4 +1,4 @@
-error: values of the type `[u8; usize::MAX]` are too big for the current architecture
+error: values of the type `[u8; usize::MAX]` are too big for the target architecture
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/drop/drop-struct-as-object.rs b/tests/ui/drop/drop-struct-as-object.rs
index 07c8950f1b2..46633bd7075 100644
--- a/tests/ui/drop/drop-struct-as-object.rs
+++ b/tests/ui/drop/drop-struct-as-object.rs
@@ -5,6 +5,9 @@
 // Test that destructor on a struct runs successfully after the struct
 // is boxed and converted to an object.
 
+// FIXME(static_mut_refs): this could use an atomic
+#![allow(static_mut_refs)]
+
 static mut value: usize = 0;
 
 struct Cat {
diff --git a/tests/ui/drop/drop-struct-as-object.stderr b/tests/ui/drop/drop-struct-as-object.stderr
index 10527c968ed..16f6d1110ba 100644
--- a/tests/ui/drop/drop-struct-as-object.stderr
+++ b/tests/ui/drop/drop-struct-as-object.stderr
@@ -1,5 +1,5 @@
 warning: method `get` is never used
-  --> $DIR/drop-struct-as-object.rs:15:8
+  --> $DIR/drop-struct-as-object.rs:18:8
    |
 LL | trait Dummy {
    |       ----- method in this trait
diff --git a/tests/ui/drop/issue-23338-ensure-param-drop-order.rs b/tests/ui/drop/issue-23338-ensure-param-drop-order.rs
index 1fa68a2e738..6fee4520cbc 100644
--- a/tests/ui/drop/issue-23338-ensure-param-drop-order.rs
+++ b/tests/ui/drop/issue-23338-ensure-param-drop-order.rs
@@ -1,5 +1,7 @@
 //@ run-pass
 #![allow(non_upper_case_globals)]
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
 
 // This test is ensuring that parameters are indeed dropped after
 // temporaries in a fn body.
@@ -91,7 +93,6 @@ pub mod d {
     pub fn max_width() -> u32 {
         unsafe {
             (mem::size_of_val(&trails) * 8) as u32
-            //~^ WARN shared reference to mutable static is discouraged [static_mut_refs]
         }
     }
 
diff --git a/tests/ui/drop/issue-23338-ensure-param-drop-order.stderr b/tests/ui/drop/issue-23338-ensure-param-drop-order.stderr
deleted file mode 100644
index 9126e602391..00000000000
--- a/tests/ui/drop/issue-23338-ensure-param-drop-order.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-warning: creating a shared reference to mutable static is discouraged
-  --> $DIR/issue-23338-ensure-param-drop-order.rs:93:31
-   |
-LL |             (mem::size_of_val(&trails) * 8) as u32
-   |                               ^^^^^^^ shared 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 shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
-   = note: `#[warn(static_mut_refs)]` on by default
-help: use `addr_of!` instead to create a raw pointer
-   |
-LL |             (mem::size_of_val(addr_of!(trails)) * 8) as u32
-   |                               ~~~~~~~~~      +
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/drop/issue-23611-enum-swap-in-drop.rs b/tests/ui/drop/issue-23611-enum-swap-in-drop.rs
index 1afaff0f735..410b07b16fc 100644
--- a/tests/ui/drop/issue-23611-enum-swap-in-drop.rs
+++ b/tests/ui/drop/issue-23611-enum-swap-in-drop.rs
@@ -1,5 +1,7 @@
 //@ run-pass
 #![allow(non_upper_case_globals)]
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
 
 // Issue 23611: this test is ensuring that, for an instance `X` of the
 // enum `E`, if you swap in a different variant during the execution
@@ -187,7 +189,6 @@ pub mod d {
     pub fn max_width() -> u32 {
         unsafe {
             (mem::size_of_val(&trails) * 8) as u32
-            //~^ WARN shared reference to mutable static is discouraged [static_mut_refs]
         }
     }
 
diff --git a/tests/ui/drop/issue-23611-enum-swap-in-drop.stderr b/tests/ui/drop/issue-23611-enum-swap-in-drop.stderr
deleted file mode 100644
index 6da87416802..00000000000
--- a/tests/ui/drop/issue-23611-enum-swap-in-drop.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-warning: creating a shared reference to mutable static is discouraged
-  --> $DIR/issue-23611-enum-swap-in-drop.rs:189:31
-   |
-LL |             (mem::size_of_val(&trails) * 8) as u32
-   |                               ^^^^^^^ shared 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 shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
-   = note: `#[warn(static_mut_refs)]` on by default
-help: use `addr_of!` instead to create a raw pointer
-   |
-LL |             (mem::size_of_val(addr_of!(trails)) * 8) as u32
-   |                               ~~~~~~~~~      +
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/drop/issue-48962.rs b/tests/ui/drop/issue-48962.rs
index 428a6ca6cd2..98d3af49ac1 100644
--- a/tests/ui/drop/issue-48962.rs
+++ b/tests/ui/drop/issue-48962.rs
@@ -1,6 +1,9 @@
 //@ run-pass
 #![allow(unused_must_use)]
 // Test that we are able to reinitialize box with moved referent
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
 static mut ORDER: [usize; 3] = [0, 0, 0];
 static mut INDEX: usize = 0;
 
diff --git a/tests/ui/drop/repeat-drop.rs b/tests/ui/drop/repeat-drop.rs
index b83bee8c1bf..7488d9113b0 100644
--- a/tests/ui/drop/repeat-drop.rs
+++ b/tests/ui/drop/repeat-drop.rs
@@ -3,6 +3,9 @@
 
 #![allow(dropping_references, dropping_copy_types)]
 
+// FIXME(static_mut_refs): this could use an atomic
+#![allow(static_mut_refs)]
+
 static mut CHECK: usize = 0;
 
 struct DropChecker(usize);
diff --git a/tests/ui/issues/issue-17302.rs b/tests/ui/drop/static-issue-17302.rs
index c499cc5281f..060f5564efd 100644
--- a/tests/ui/issues/issue-17302.rs
+++ b/tests/ui/drop/static-issue-17302.rs
@@ -1,5 +1,8 @@
 //@ run-pass
 
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
 static mut DROPPED: [bool; 2] = [false, false];
 
 struct A(usize);
diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs
new file mode 100644
index 00000000000..8d36981b41b
--- /dev/null
+++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs
@@ -0,0 +1,19 @@
+// Here, there are two types with the same name. One of these has a `derive` annotation, but in the
+// expansion these `impl`s are associated to the the *other* type. There is a suggestion to remove
+// unneded type parameters, but because we're now point at a type with no type parameters, the
+// suggestion would suggest removing code from an empty span, which would ICE in nightly.
+//
+// issue: rust-lang/rust#108748
+
+struct NotSM;
+
+#[derive(PartialEq, Eq)]
+//~^ ERROR struct takes 0 generic arguments
+//~| ERROR struct takes 0 generic arguments
+//~| ERROR struct takes 0 generic arguments
+//~| ERROR struct takes 0 generic arguments
+struct NotSM<T>(T);
+//~^ ERROR the name `NotSM` is defined multiple times
+//~| ERROR no field `0`
+
+fn main() {}
diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr
new file mode 100644
index 00000000000..32c3cf44031
--- /dev/null
+++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr
@@ -0,0 +1,71 @@
+error[E0428]: the name `NotSM` is defined multiple times
+  --> $DIR/multiple-types-with-same-name-and-derive.rs:15:1
+   |
+LL | struct NotSM;
+   | ------------- previous definition of the type `NotSM` here
+...
+LL | struct NotSM<T>(T);
+   | ^^^^^^^^^^^^^^^^^^^ `NotSM` redefined here
+   |
+   = note: `NotSM` must be defined only once in the type namespace of this module
+
+error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied
+  --> $DIR/multiple-types-with-same-name-and-derive.rs:10:10
+   |
+LL | #[derive(PartialEq, Eq)]
+   |          ^^^^^^^^^ expected 0 generic arguments
+   |
+note: struct defined here, with 0 generic parameters
+  --> $DIR/multiple-types-with-same-name-and-derive.rs:8:8
+   |
+LL | struct NotSM;
+   |        ^^^^^
+
+error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied
+  --> $DIR/multiple-types-with-same-name-and-derive.rs:10:10
+   |
+LL | #[derive(PartialEq, Eq)]
+   |          ^^^^^^^^^ expected 0 generic arguments
+   |
+note: struct defined here, with 0 generic parameters
+  --> $DIR/multiple-types-with-same-name-and-derive.rs:8:8
+   |
+LL | struct NotSM;
+   |        ^^^^^
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied
+  --> $DIR/multiple-types-with-same-name-and-derive.rs:10:21
+   |
+LL | #[derive(PartialEq, Eq)]
+   |                     ^^ expected 0 generic arguments
+   |
+note: struct defined here, with 0 generic parameters
+  --> $DIR/multiple-types-with-same-name-and-derive.rs:8:8
+   |
+LL | struct NotSM;
+   |        ^^^^^
+
+error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied
+  --> $DIR/multiple-types-with-same-name-and-derive.rs:10:10
+   |
+LL | #[derive(PartialEq, Eq)]
+   |          ^^^^^^^^^ expected 0 generic arguments
+   |
+note: struct defined here, with 0 generic parameters
+  --> $DIR/multiple-types-with-same-name-and-derive.rs:8:8
+   |
+LL | struct NotSM;
+   |        ^^^^^
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error[E0609]: no field `0` on type `&NotSM`
+  --> $DIR/multiple-types-with-same-name-and-derive.rs:15:17
+   |
+LL | struct NotSM<T>(T);
+   |                 ^ unknown field
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0107, E0428, E0609.
+For more information about an error, try `rustc --explain E0107`.
diff --git a/tests/ui/extern/extern-static-size-overflow.rs b/tests/ui/extern/extern-static-size-overflow.rs
index a96ce0cf47e..f33e482aa66 100644
--- a/tests/ui/extern/extern-static-size-overflow.rs
+++ b/tests/ui/extern/extern-static-size-overflow.rs
@@ -4,31 +4,13 @@ struct ReallyBig {
 }
 
 // The limit for "too big for the current architecture" is dependent on the target pointer size
-// however it's artificially limited on 64 bits
-// logic copied from rustc_target::abi::TargetDataLayout::obj_size_bound()
+// but is artificially limited due to LLVM's internal architecture
+// logic based on rustc_target::abi::TargetDataLayout::obj_size_bound()
 const fn max_size() -> usize {
-    #[cfg(target_pointer_width = "16")]
-    {
-        1 << 15
-    }
-
-    #[cfg(target_pointer_width = "32")]
-    {
-        1 << 31
-    }
-
-    #[cfg(target_pointer_width = "64")]
-    {
-        1 << 47
-    }
-
-    #[cfg(not(any(
-        target_pointer_width = "16",
-        target_pointer_width = "32",
-        target_pointer_width = "64"
-    )))]
-    {
-        isize::MAX as usize
+    if usize::BITS < 61 {
+        1 << (usize::BITS - 1)
+    } else {
+        1 << 61
     }
 }
 
diff --git a/tests/ui/extern/extern-static-size-overflow.stderr b/tests/ui/extern/extern-static-size-overflow.stderr
index 1c926399591..c6490e96a8e 100644
--- a/tests/ui/extern/extern-static-size-overflow.stderr
+++ b/tests/ui/extern/extern-static-size-overflow.stderr
@@ -1,17 +1,17 @@
-error: extern static is too large for the current architecture
-  --> $DIR/extern-static-size-overflow.rs:38:5
+error: extern static is too large for the target architecture
+  --> $DIR/extern-static-size-overflow.rs:20:5
    |
 LL |     static BAZ: [u8; max_size()];
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: extern static is too large for the current architecture
-  --> $DIR/extern-static-size-overflow.rs:39:5
+error: extern static is too large for the target architecture
+  --> $DIR/extern-static-size-overflow.rs:21:5
    |
 LL |     static UWU: [usize; usize::MAX];
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: extern static is too large for the current architecture
-  --> $DIR/extern-static-size-overflow.rs:40:5
+error: extern static is too large for the target architecture
+  --> $DIR/extern-static-size-overflow.rs:22:5
    |
 LL |     static A: ReallyBig;
    |     ^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/feature-gates/feature-gate-pin_ergonomics.rs b/tests/ui/feature-gates/feature-gate-pin_ergonomics.rs
new file mode 100644
index 00000000000..d694531d53a
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-pin_ergonomics.rs
@@ -0,0 +1,15 @@
+#![allow(dead_code, incomplete_features)]
+
+use std::pin::Pin;
+
+struct Foo;
+
+fn foo(_: Pin<&mut Foo>) {
+}
+
+fn bar(mut x: Pin<&mut Foo>) {
+    foo(x);
+    foo(x); //~ ERROR use of moved value: `x`
+}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-pin_ergonomics.stderr b/tests/ui/feature-gates/feature-gate-pin_ergonomics.stderr
new file mode 100644
index 00000000000..6c9029d8176
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-pin_ergonomics.stderr
@@ -0,0 +1,21 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/feature-gate-pin_ergonomics.rs:12:9
+   |
+LL | fn bar(mut x: Pin<&mut Foo>) {
+   |        ----- move occurs because `x` has type `Pin<&mut Foo>`, which does not implement the `Copy` trait
+LL |     foo(x);
+   |         - value moved here
+LL |     foo(x);
+   |         ^ value used here after move
+   |
+note: consider changing this parameter type in function `foo` to borrow instead if owning the value isn't necessary
+  --> $DIR/feature-gate-pin_ergonomics.rs:7:11
+   |
+LL | fn foo(_: Pin<&mut Foo>) {
+   |    ---    ^^^^^^^^^^^^^ this parameter takes ownership of the value
+   |    |
+   |    in this function
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0382`.
diff --git a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs
index 667bc9f8ddf..7ae4a8d911b 100644
--- a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs
+++ b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.rs
@@ -2,6 +2,6 @@
 
 #[rustc_variance] //~ ERROR the `#[rustc_variance]` attribute is just used for rustc unit tests and will never be stable
 #[rustc_error] //~ ERROR the `#[rustc_error]` attribute is just used for rustc unit tests and will never be stable
-#[rustc_nonnull_optimization_guaranteed] //~ ERROR the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable niche optimizations in libcore and libstd and will never be stable
+#[rustc_nonnull_optimization_guaranteed] //~ ERROR the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to document guaranteed niche optimizations in libcore and libstd and will never be stable
 
 fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr
index 8177d5ef6be..8c3a8eb2df8 100644
--- a/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr
+++ b/tests/ui/feature-gates/feature-gate-rustc-attrs-1.stderr
@@ -16,7 +16,8 @@ LL | #[rustc_error]
    = help: add `#![feature(rustc_attrs)]` 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]: the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to enable niche optimizations in libcore and libstd and will never be stable
+error[E0658]: the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to document guaranteed niche optimizations in libcore and libstd and will never be stable
+              (note that the compiler does not even check whether the type indeed is being non-null-optimized; it is your responsibility to ensure that the attribute is only used on types that are optimized)
   --> $DIR/feature-gate-rustc-attrs-1.rs:5:1
    |
 LL | #[rustc_nonnull_optimization_guaranteed]
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs
index ca60bc62b51..afffb3b1443 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs
+++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.rs
@@ -164,4 +164,28 @@ mod repr {
     //~| NOTE not a struct, enum, or union
 }
 
+
+#[repr(Rust)]
+//~^ ERROR: attribute should be applied to a struct, enum, or union
+mod repr_rust {
+//~^ NOTE not a struct, enum, or union
+    mod inner { #![repr(Rust)] }
+    //~^ ERROR: attribute should be applied to a struct, enum, or union
+    //~| NOTE not a struct, enum, or union
+
+    #[repr(Rust)] fn f() { }
+    //~^ ERROR: attribute should be applied to a struct, enum, or union
+    //~| NOTE not a struct, enum, or union
+
+    struct S;
+
+    #[repr(Rust)] type T = S;
+    //~^ ERROR: attribute should be applied to a struct, enum, or union
+    //~| NOTE not a struct, enum, or union
+
+    #[repr(Rust)] impl S { }
+    //~^ ERROR: attribute should be applied to a struct, enum, or union
+    //~| NOTE not a struct, enum, or union
+}
+
 fn main() {}
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
index ac2bf78157d..fe764ff4925 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
+++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
@@ -107,6 +107,21 @@ LL | |
 LL | | }
    | |_- not a struct, enum, or union
 
+error[E0517]: attribute should be applied to a struct, enum, or union
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:168:8
+   |
+LL |   #[repr(Rust)]
+   |          ^^^^
+LL |
+LL | / mod repr_rust {
+LL | |
+LL | |     mod inner { #![repr(Rust)] }
+LL | |
+...  |
+LL | |
+LL | | }
+   | |_- not a struct, enum, or union
+
 error: attribute should be applied to an `extern crate` item
   --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:26:1
    |
@@ -329,7 +344,31 @@ error[E0517]: attribute should be applied to a struct, enum, or union
 LL |     #[repr(C)] impl S { }
    |            ^   ---------- not a struct, enum, or union
 
-error: aborting due to 39 previous errors
+error[E0517]: attribute should be applied to a struct, enum, or union
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:172:25
+   |
+LL |     mod inner { #![repr(Rust)] }
+   |     --------------------^^^^---- not a struct, enum, or union
+
+error[E0517]: attribute should be applied to a struct, enum, or union
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:176:12
+   |
+LL |     #[repr(Rust)] fn f() { }
+   |            ^^^^   ---------- not a struct, enum, or union
+
+error[E0517]: attribute should be applied to a struct, enum, or union
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:182:12
+   |
+LL |     #[repr(Rust)] type T = S;
+   |            ^^^^   ----------- not a struct, enum, or union
+
+error[E0517]: attribute should be applied to a struct, enum, or union
+  --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:186:12
+   |
+LL |     #[repr(Rust)] impl S { }
+   |            ^^^^   ---------- not a struct, enum, or union
+
+error: aborting due to 44 previous errors
 
 Some errors have detailed explanations: E0517, E0518, E0658.
 For more information about an error, try `rustc --explain E0517`.
diff --git a/tests/ui/for-loop-while/cleanup-rvalue-during-if-and-while.rs b/tests/ui/for-loop-while/cleanup-rvalue-during-if-and-while.rs
index fef9f24d462..57e8b228649 100644
--- a/tests/ui/for-loop-while/cleanup-rvalue-during-if-and-while.rs
+++ b/tests/ui/for-loop-while/cleanup-rvalue-during-if-and-while.rs
@@ -2,6 +2,9 @@
 // This test verifies that temporaries created for `while`'s and `if`
 // conditions are dropped after the condition is evaluated.
 
+// FIXME(static_mut_refs): this could use an atomic
+#![allow(static_mut_refs)]
+
 struct Temporary;
 
 static mut DROPPED: isize = 0;
diff --git a/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.rs b/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.rs
index 500633edf12..a05d20ffbd2 100644
--- a/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.rs
+++ b/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.rs
@@ -2,6 +2,10 @@
 
 // The `foo` module attempts to maintains an invariant that each `S`
 // has a unique `u64` id.
+
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
 use self::foo::S;
 mod foo {
     use std::cell::{UnsafeCell};
diff --git a/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.stderr b/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.stderr
index 692d98bc53c..8924800ef27 100644
--- a/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.stderr
+++ b/tests/ui/functional-struct-update/functional-struct-update-respects-privacy.stderr
@@ -1,5 +1,5 @@
 error[E0451]: field `secret_uid` of struct `S` is private
-  --> $DIR/functional-struct-update-respects-privacy.rs:28:49
+  --> $DIR/functional-struct-update-respects-privacy.rs:32:49
    |
 LL |     let s_2 = foo::S { b: format!("ess two"), ..s_1 }; // FRU ...
    |                                                 ^^^ field `secret_uid` is private
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr
index c14021e009b..9831348de75 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr
@@ -3,6 +3,17 @@ error: expected a pattern range bound, found an expression
    |
 LL |             0..5+1 => errors_only.push(x),
    |                ^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider extracting the expression into a `const`
+   |
+LL +         const VAL: /* Type */ = 5+1;
+LL ~         match x as i32 {
+LL ~             0..VAL => errors_only.push(x),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |             0..const { 5+1 } => errors_only.push(x),
+   |                +++++++     +
 
 error[E0408]: variable `n` is not bound in all patterns
   --> $DIR/range_pat_interactions1.rs:10:25
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr
index 136296fa5b0..1b5e875cccb 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr
@@ -1,9 +1,3 @@
-error: expected a pattern range bound, found an expression
-  --> $DIR/range_pat_interactions2.rs:10:18
-   |
-LL |             0..=(5+1) => errors_only.push(x),
-   |                  ^^^ arbitrary expressions are not allowed in patterns
-
 error: range pattern bounds cannot have parentheses
   --> $DIR/range_pat_interactions2.rs:10:17
    |
@@ -16,6 +10,23 @@ LL -             0..=(5+1) => errors_only.push(x),
 LL +             0..=5+1 => errors_only.push(x),
    |
 
+error: expected a pattern range bound, found an expression
+  --> $DIR/range_pat_interactions2.rs:10:18
+   |
+LL |             0..=(5+1) => errors_only.push(x),
+   |                  ^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider extracting the expression into a `const`
+   |
+LL +         const VAL: /* Type */ = 5+1;
+LL ~         match x as i32 {
+LL ~             0..=(VAL) => errors_only.push(x),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |             0..=(const { 5+1 }) => errors_only.push(x),
+   |                  +++++++     +
+
 error[E0658]: inline-const in pattern position is experimental
   --> $DIR/range_pat_interactions2.rs:15:20
    |
diff --git a/tests/ui/instrument-coverage/mcdc-condition-limit.bad.stderr b/tests/ui/instrument-coverage/mcdc-condition-limit.bad.stderr
index 15fa3f6ee11..b8b7d6e1a5e 100644
--- a/tests/ui/instrument-coverage/mcdc-condition-limit.bad.stderr
+++ b/tests/ui/instrument-coverage/mcdc-condition-limit.bad.stderr
@@ -1,5 +1,5 @@
 warning: number of conditions in decision (7) exceeds limit (6), so MC/DC analysis will not count this expression
-  --> $DIR/mcdc-condition-limit.rs:29:8
+  --> $DIR/mcdc-condition-limit.rs:28:8
    |
 LL |     if a && b && c && d && e && f && g {
    |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/instrument-coverage/mcdc-condition-limit.rs b/tests/ui/instrument-coverage/mcdc-condition-limit.rs
index eb19ddec78f..91ff6381df7 100644
--- a/tests/ui/instrument-coverage/mcdc-condition-limit.rs
+++ b/tests/ui/instrument-coverage/mcdc-condition-limit.rs
@@ -1,5 +1,4 @@
 //@ edition: 2021
-//@ min-llvm-version: 18
 //@ revisions: good bad
 //@ check-pass
 //@ compile-flags: -Cinstrument-coverage -Zcoverage-options=mcdc -Zno-profiler-runtime
diff --git a/tests/ui/issues/issue-10734.rs b/tests/ui/issues/issue-10734.rs
index 8daa401748c..6d815aeca07 100644
--- a/tests/ui/issues/issue-10734.rs
+++ b/tests/ui/issues/issue-10734.rs
@@ -1,6 +1,9 @@
 //@ run-pass
 #![allow(non_upper_case_globals)]
 
+// FIXME(static_mut_refs): this could use an atomic
+#![allow(static_mut_refs)]
+
 static mut drop_count: usize = 0;
 
 struct Foo {
diff --git a/tests/ui/issues/issue-15858.rs b/tests/ui/issues/issue-15858.rs
index 2d4aac01fbe..27887d49e3e 100644
--- a/tests/ui/issues/issue-15858.rs
+++ b/tests/ui/issues/issue-15858.rs
@@ -1,4 +1,6 @@
 //@ run-pass
+// FIXME(static_mut_refs): this could use an atomic
+#![allow(static_mut_refs)]
 static mut DROP_RAN: bool = false;
 
 trait Bar {
diff --git a/tests/ui/issues/issue-15858.stderr b/tests/ui/issues/issue-15858.stderr
index f36bcc21bd7..0c082cc0862 100644
--- a/tests/ui/issues/issue-15858.stderr
+++ b/tests/ui/issues/issue-15858.stderr
@@ -1,5 +1,5 @@
 warning: method `do_something` is never used
-  --> $DIR/issue-15858.rs:5:8
+  --> $DIR/issue-15858.rs:7:8
    |
 LL | trait Bar {
    |       --- method in this trait
diff --git a/tests/ui/issues/issue-16151.rs b/tests/ui/issues/issue-16151.rs
index 20a3b5a04da..b18108e0a8a 100644
--- a/tests/ui/issues/issue-16151.rs
+++ b/tests/ui/issues/issue-16151.rs
@@ -1,5 +1,8 @@
 //@ run-pass
 
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
 use std::mem;
 
 static mut DROP_COUNT: usize = 0;
diff --git a/tests/ui/issues/issue-39367.rs b/tests/ui/issues/issue-39367.rs
index dd16d4da1bd..937d6c4b9e0 100644
--- a/tests/ui/issues/issue-39367.rs
+++ b/tests/ui/issues/issue-39367.rs
@@ -20,6 +20,7 @@ fn arena() -> &'static ArenaSet<Vec<u8>> {
 
             static mut ONCE: Once = Once::new();
             ONCE.call_once(|| {
+            //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs]
                 DATA = transmute
                     ::<Box<ArenaSet<Vec<u8>>>, *const ArenaSet<Vec<u8>>>
                     (Box::new(__static_ref_initialize()));
diff --git a/tests/ui/issues/issue-39367.stderr b/tests/ui/issues/issue-39367.stderr
new file mode 100644
index 00000000000..333c9f9634a
--- /dev/null
+++ b/tests/ui/issues/issue-39367.stderr
@@ -0,0 +1,17 @@
+warning: creating a shared reference to mutable static is discouraged
+  --> $DIR/issue-39367.rs:22:13
+   |
+LL | /             ONCE.call_once(|| {
+LL | |
+LL | |                 DATA = transmute
+LL | |                     ::<Box<ArenaSet<Vec<u8>>>, *const ArenaSet<Vec<u8>>>
+LL | |                     (Box::new(__static_ref_initialize()));
+LL | |             });
+   | |______________^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+   = note: `#[warn(static_mut_refs)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/issues/issue-4734.rs b/tests/ui/issues/issue-4734.rs
index 938d7064789..58aa0179693 100644
--- a/tests/ui/issues/issue-4734.rs
+++ b/tests/ui/issues/issue-4734.rs
@@ -3,7 +3,8 @@
 // Ensures that destructors are run for expressions of the form "e;" where
 // `e` is a type which requires a destructor.
 
-
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
 #![allow(path_statements)]
 
 struct A { n: isize }
diff --git a/tests/ui/issues/issue-54410.rs b/tests/ui/issues/issue-54410.rs
index 208be6f221c..e3e8ca985b9 100644
--- a/tests/ui/issues/issue-54410.rs
+++ b/tests/ui/issues/issue-54410.rs
@@ -5,5 +5,4 @@ extern "C" {
 
 fn main() {
     println!("{:p}", unsafe { &symbol });
-    //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs]
 }
diff --git a/tests/ui/issues/issue-54410.stderr b/tests/ui/issues/issue-54410.stderr
index 6cc5cd95e2f..97e5990750e 100644
--- a/tests/ui/issues/issue-54410.stderr
+++ b/tests/ui/issues/issue-54410.stderr
@@ -6,21 +6,6 @@ LL |     pub static mut symbol: [i8];
    |
    = help: the trait `Sized` is not implemented for `[i8]`
 
-warning: creating a shared reference to mutable static is discouraged
-  --> $DIR/issue-54410.rs:7:31
-   |
-LL |     println!("{:p}", unsafe { &symbol });
-   |                               ^^^^^^^ shared 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 shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
-   = note: `#[warn(static_mut_refs)]` on by default
-help: use `addr_of!` instead to create a raw pointer
-   |
-LL |     println!("{:p}", unsafe { addr_of!(symbol) });
-   |                               ~~~~~~~~~      +
-
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/issues/issue-6892.rs b/tests/ui/issues/issue-6892.rs
index aff00cf60ba..7d99aef4ac5 100644
--- a/tests/ui/issues/issue-6892.rs
+++ b/tests/ui/issues/issue-6892.rs
@@ -3,6 +3,8 @@
 // Ensures that destructors are run for expressions of the form "let _ = e;"
 // where `e` is a type which requires a destructor.
 
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
 
 struct Foo;
 struct Bar { x: isize }
diff --git a/tests/ui/issues/issue-8860.rs b/tests/ui/issues/issue-8860.rs
index 67e9a276ae4..3af61576fe1 100644
--- a/tests/ui/issues/issue-8860.rs
+++ b/tests/ui/issues/issue-8860.rs
@@ -1,4 +1,6 @@
 //@ run-pass
+// FIXME(static_mut_refs): this could use an atomic
+#![allow(static_mut_refs)]
 #![allow(dead_code)]
 
 static mut DROP: isize = 0;
diff --git a/tests/ui/layout/size-of-val-raw-too-big.rs b/tests/ui/layout/size-of-val-raw-too-big.rs
index 8d82c78d953..dfca6d6eb76 100644
--- a/tests/ui/layout/size-of-val-raw-too-big.rs
+++ b/tests/ui/layout/size-of-val-raw-too-big.rs
@@ -1,7 +1,7 @@
 //@ build-fail
 //@ compile-flags: --crate-type lib
 //@ only-32bit Layout computation rejects this layout for different reasons on 64-bit.
-//@ error-pattern: too big for the current architecture
+//@ error-pattern: too big for the target architecture
 #![feature(core_intrinsics)]
 #![allow(internal_features)]
 
diff --git a/tests/ui/layout/size-of-val-raw-too-big.stderr b/tests/ui/layout/size-of-val-raw-too-big.stderr
index aa9abd644fa..886bba9ec9d 100644
--- a/tests/ui/layout/size-of-val-raw-too-big.stderr
+++ b/tests/ui/layout/size-of-val-raw-too-big.stderr
@@ -1,4 +1,4 @@
-error: values of the type `Example` are too big for the current architecture
+error: values of the type `Example` are too big for the target architecture
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/layout/too-big-with-padding.rs b/tests/ui/layout/too-big-with-padding.rs
index 76703100145..8423ad2e1d6 100644
--- a/tests/ui/layout/too-big-with-padding.rs
+++ b/tests/ui/layout/too-big-with-padding.rs
@@ -10,7 +10,7 @@
 #[repr(C, align(2))]
 pub struct Example([u8; 0x7fffffff]);
 
-pub fn lib(_x: Example) {} //~ERROR: too big for the current architecture
+pub fn lib(_x: Example) {} //~ERROR: too big for the target architecture
 
 #[lang = "sized"]
 pub trait Sized {}
diff --git a/tests/ui/layout/too-big-with-padding.stderr b/tests/ui/layout/too-big-with-padding.stderr
index 71309788dac..fc3b4db049a 100644
--- a/tests/ui/layout/too-big-with-padding.stderr
+++ b/tests/ui/layout/too-big-with-padding.stderr
@@ -1,4 +1,4 @@
-error: values of the type `Example` are too big for the current architecture
+error: values of the type `Example` are too big for the target architecture
   --> $DIR/too-big-with-padding.rs:13:1
    |
 LL | pub fn lib(_x: Example) {}
diff --git a/tests/ui/limits/huge-array-simple-32.rs b/tests/ui/limits/huge-array-simple-32.rs
index 6ff981cd160..db75cc57e9a 100644
--- a/tests/ui/limits/huge-array-simple-32.rs
+++ b/tests/ui/limits/huge-array-simple-32.rs
@@ -4,6 +4,6 @@
 #![allow(arithmetic_overflow)]
 
 fn main() {
-    let _fat: [u8; (1<<31)+(1<<15)] = //~ ERROR too big for the current architecture
+    let _fat: [u8; (1<<31)+(1<<15)] = //~ ERROR too big for the target architecture
         [0; (1u32<<31) as usize +(1u32<<15) as usize];
 }
diff --git a/tests/ui/limits/huge-array-simple-32.stderr b/tests/ui/limits/huge-array-simple-32.stderr
index 1b86b02297f..33979915feb 100644
--- a/tests/ui/limits/huge-array-simple-32.stderr
+++ b/tests/ui/limits/huge-array-simple-32.stderr
@@ -1,4 +1,4 @@
-error: values of the type `[u8; 2147516416]` are too big for the current architecture
+error: values of the type `[u8; 2147516416]` are too big for the target architecture
   --> $DIR/huge-array-simple-32.rs:7:9
    |
 LL |     let _fat: [u8; (1<<31)+(1<<15)] =
diff --git a/tests/ui/limits/huge-array-simple-64.rs b/tests/ui/limits/huge-array-simple-64.rs
index 13b284503bf..d2838e0d41e 100644
--- a/tests/ui/limits/huge-array-simple-64.rs
+++ b/tests/ui/limits/huge-array-simple-64.rs
@@ -4,6 +4,6 @@
 #![allow(arithmetic_overflow)]
 
 fn main() {
-    let _fat: [u8; (1<<61)+(1<<31)] = //~ ERROR too big for the current architecture
+    let _fat: [u8; (1<<61)+(1<<31)] = //~ ERROR too big for the target architecture
         [0; (1u64<<61) as usize +(1u64<<31) as usize];
 }
diff --git a/tests/ui/limits/huge-array-simple-64.stderr b/tests/ui/limits/huge-array-simple-64.stderr
index 8d395c3c6a9..46df288d4f7 100644
--- a/tests/ui/limits/huge-array-simple-64.stderr
+++ b/tests/ui/limits/huge-array-simple-64.stderr
@@ -1,4 +1,4 @@
-error: values of the type `[u8; 2305843011361177600]` are too big for the current architecture
+error: values of the type `[u8; 2305843011361177600]` are too big for the target architecture
   --> $DIR/huge-array-simple-64.rs:7:9
    |
 LL |     let _fat: [u8; (1<<61)+(1<<31)] =
diff --git a/tests/ui/limits/huge-array.stderr b/tests/ui/limits/huge-array.stderr
index 2ebaf17a138..ce0c0d650c2 100644
--- a/tests/ui/limits/huge-array.stderr
+++ b/tests/ui/limits/huge-array.stderr
@@ -1,4 +1,4 @@
-error: values of the type `[[u8; 1518599999]; 1518600000]` are too big for the current architecture
+error: values of the type `[[u8; 1518599999]; 1518600000]` are too big for the target architecture
   --> $DIR/huge-array.rs:4:9
    |
 LL |     let s: [T; 1518600000] = [t; 1518600000];
diff --git a/tests/ui/limits/huge-enum.rs b/tests/ui/limits/huge-enum.rs
index cf6e637388c..5664d0ba516 100644
--- a/tests/ui/limits/huge-enum.rs
+++ b/tests/ui/limits/huge-enum.rs
@@ -6,9 +6,9 @@
 type BIG = Option<[u32; (1<<29)-1]>;
 
 #[cfg(target_pointer_width = "64")]
-type BIG = Option<[u32; (1<<45)-1]>;
+type BIG = Option<[u32; (1<<59)-1]>;
 
 fn main() {
     let big: BIG = None;
-    //~^ ERROR are too big for the current architecture
+    //~^ ERROR are too big for the target architecture
 }
diff --git a/tests/ui/limits/huge-enum.stderr b/tests/ui/limits/huge-enum.stderr
index fcd40607af4..18168b3fa5c 100644
--- a/tests/ui/limits/huge-enum.stderr
+++ b/tests/ui/limits/huge-enum.stderr
@@ -1,4 +1,4 @@
-error: values of the type `Option<TYPE>` are too big for the current architecture
+error: values of the type `Option<TYPE>` are too big for the target architecture
   --> $DIR/huge-enum.rs:12:9
    |
 LL |     let big: BIG = None;
diff --git a/tests/ui/limits/issue-56762.rs b/tests/ui/limits/huge-static.rs
index 17b3ad8b01e..4709b46e59d 100644
--- a/tests/ui/limits/issue-56762.rs
+++ b/tests/ui/limits/huge-static.rs
@@ -1,6 +1,9 @@
-//@ only-x86_64
+//@ only-64bit
 
-const HUGE_SIZE: usize = !0usize / 8;
+// This test validates we gracefully fail computing a const or static of absurdly large size.
+// The oddly-specific number is because of LLVM measuring object sizes in bits.
+
+const HUGE_SIZE: usize = 1 << 61;
 
 
 pub struct TooBigArray {
diff --git a/tests/ui/limits/issue-56762.stderr b/tests/ui/limits/huge-static.stderr
index 3a6c3559ac1..684efeeb4a3 100644
--- a/tests/ui/limits/issue-56762.stderr
+++ b/tests/ui/limits/huge-static.stderr
@@ -1,14 +1,14 @@
 error[E0080]: could not evaluate static initializer
-  --> $DIR/issue-56762.rs:16:1
+  --> $DIR/huge-static.rs:19:1
    |
 LL | static MY_TOO_BIG_ARRAY_1: TooBigArray = TooBigArray::new();
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ values of the type `[u8; 2305843009213693951]` are too big for the current architecture
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ values of the type `[u8; 2305843009213693952]` are too big for the target architecture
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/issue-56762.rs:19:1
+  --> $DIR/huge-static.rs:22:1
    |
 LL | static MY_TOO_BIG_ARRAY_2: [u8; HUGE_SIZE] = [0x00; HUGE_SIZE];
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ values of the type `[u8; 2305843009213693951]` are too big for the current architecture
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ values of the type `[u8; 2305843009213693952]` are too big for the target architecture
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/limits/huge-struct.rs b/tests/ui/limits/huge-struct.rs
index b9e90b3e9d1..f7ce4f26db1 100644
--- a/tests/ui/limits/huge-struct.rs
+++ b/tests/ui/limits/huge-struct.rs
@@ -1,7 +1,9 @@
+// ignore-tidy-linelength
 //@ build-fail
 //@ normalize-stderr-test: "S32" -> "SXX"
 //@ normalize-stderr-test: "S1M" -> "SXX"
-//@ error-pattern: too big for the current
+//@ normalize-stderr-32bit: "values of the type `[^`]+` are too big" -> "values of the type $$REALLY_TOO_BIG are too big"
+//@ normalize-stderr-64bit: "values of the type `[^`]+` are too big" -> "values of the type $$REALLY_TOO_BIG are too big"
 
 struct S32<T> {
     v0: T,
@@ -44,6 +46,6 @@ struct S1M<T> { val: S1k<S1k<T>> }
 
 fn main() {
     let fat: Option<S1M<S1M<S1M<u32>>>> = None;
-    //~^ ERROR are too big for the current architecture
+    //~^ ERROR are too big for the target architecture
 
 }
diff --git a/tests/ui/limits/huge-struct.stderr b/tests/ui/limits/huge-struct.stderr
index 782db20c7f3..b10455ffd2d 100644
--- a/tests/ui/limits/huge-struct.stderr
+++ b/tests/ui/limits/huge-struct.stderr
@@ -1,5 +1,5 @@
-error: values of the type `SXX<SXX<SXX<u32>>>` are too big for the current architecture
-  --> $DIR/huge-struct.rs:46:9
+error: values of the type $REALLY_TOO_BIG are too big for the target architecture
+  --> $DIR/huge-struct.rs:48:9
    |
 LL |     let fat: Option<SXX<SXX<SXX<u32>>>> = None;
    |         ^^^
diff --git a/tests/ui/limits/issue-15919-32.stderr b/tests/ui/limits/issue-15919-32.stderr
index abd65ff3c9e..f162838d37d 100644
--- a/tests/ui/limits/issue-15919-32.stderr
+++ b/tests/ui/limits/issue-15919-32.stderr
@@ -1,4 +1,4 @@
-error: values of the type `[usize; usize::MAX]` are too big for the current architecture
+error: values of the type `[usize; usize::MAX]` are too big for the target architecture
   --> $DIR/issue-15919-32.rs:5:9
    |
 LL |     let x = [0usize; 0xffff_ffff];
diff --git a/tests/ui/limits/issue-15919-64.stderr b/tests/ui/limits/issue-15919-64.stderr
index d1f0cc39c18..cd443f2065b 100644
--- a/tests/ui/limits/issue-15919-64.stderr
+++ b/tests/ui/limits/issue-15919-64.stderr
@@ -1,4 +1,4 @@
-error: values of the type `[usize; usize::MAX]` are too big for the current architecture
+error: values of the type `[usize; usize::MAX]` are too big for the target architecture
   --> $DIR/issue-15919-64.rs:5:9
    |
 LL |     let x = [0usize; 0xffff_ffff_ffff_ffff];
diff --git a/tests/ui/limits/issue-17913.rs b/tests/ui/limits/issue-17913.rs
index 325923f32f3..24fd3b542e6 100644
--- a/tests/ui/limits/issue-17913.rs
+++ b/tests/ui/limits/issue-17913.rs
@@ -1,6 +1,6 @@
 //@ build-fail
 //@ normalize-stderr-test: "\[&usize; \d+\]" -> "[&usize; usize::MAX]"
-//@ error-pattern: too big for the current architecture
+//@ error-pattern: too big for the target architecture
 
 #[cfg(target_pointer_width = "64")]
 fn main() {
diff --git a/tests/ui/limits/issue-17913.stderr b/tests/ui/limits/issue-17913.stderr
index 893730cbbd2..e9c3c14e181 100644
--- a/tests/ui/limits/issue-17913.stderr
+++ b/tests/ui/limits/issue-17913.stderr
@@ -1,4 +1,4 @@
-error: values of the type `[&usize; usize::MAX]` are too big for the current architecture
+error: values of the type `[&usize; usize::MAX]` are too big for the target architecture
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/limits/issue-55878.rs b/tests/ui/limits/issue-55878.rs
index 4d91a173240..81696e226fd 100644
--- a/tests/ui/limits/issue-55878.rs
+++ b/tests/ui/limits/issue-55878.rs
@@ -2,7 +2,7 @@
 //@ normalize-stderr-64bit: "18446744073709551615" -> "SIZE"
 //@ normalize-stderr-32bit: "4294967295" -> "SIZE"
 
-//@ error-pattern: are too big for the current architecture
+//@ error-pattern: are too big for the target architecture
 fn main() {
     println!("Size: {}", std::mem::size_of::<[u8; u64::MAX as usize]>());
 }
diff --git a/tests/ui/limits/issue-55878.stderr b/tests/ui/limits/issue-55878.stderr
index 97ca0f4fb59..0a5f17be804 100644
--- a/tests/ui/limits/issue-55878.stderr
+++ b/tests/ui/limits/issue-55878.stderr
@@ -1,7 +1,7 @@
 error[E0080]: evaluation of constant value failed
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
    |
-   = note: values of the type `[u8; usize::MAX]` are too big for the current architecture
+   = note: values of the type `[u8; usize::MAX]` are too big for the target architecture
    |
 note: inside `std::mem::size_of::<[u8; usize::MAX]>`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
diff --git a/tests/ui/limits/issue-69485-var-size-diffs-too-large.rs b/tests/ui/limits/issue-69485-var-size-diffs-too-large.rs
index 9c150c119d0..6133183a55c 100644
--- a/tests/ui/limits/issue-69485-var-size-diffs-too-large.rs
+++ b/tests/ui/limits/issue-69485-var-size-diffs-too-large.rs
@@ -3,7 +3,7 @@
 //@ compile-flags: -Zmir-opt-level=0
 
 fn main() {
-    Bug::V([0; !0]); //~ ERROR are too big for the current
+    Bug::V([0; !0]); //~ ERROR are too big for the target
 }
 
 enum Bug {
diff --git a/tests/ui/limits/issue-69485-var-size-diffs-too-large.stderr b/tests/ui/limits/issue-69485-var-size-diffs-too-large.stderr
index 7b9b8f76d0c..7fa0ab95981 100644
--- a/tests/ui/limits/issue-69485-var-size-diffs-too-large.stderr
+++ b/tests/ui/limits/issue-69485-var-size-diffs-too-large.stderr
@@ -1,4 +1,4 @@
-error: values of the type `[u8; usize::MAX]` are too big for the current architecture
+error: values of the type `[u8; usize::MAX]` are too big for the target architecture
   --> $DIR/issue-69485-var-size-diffs-too-large.rs:6:5
    |
 LL |     Bug::V([0; !0]);
diff --git a/tests/ui/limits/issue-75158-64.stderr b/tests/ui/limits/issue-75158-64.stderr
index 06aad9616cb..a3772e509ed 100644
--- a/tests/ui/limits/issue-75158-64.stderr
+++ b/tests/ui/limits/issue-75158-64.stderr
@@ -1,4 +1,4 @@
-error: values of the type `[u8; usize::MAX]` are too big for the current architecture
+error: values of the type `[u8; usize::MAX]` are too big for the target architecture
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/link-section.rs b/tests/ui/link-section.rs
index 1a791b88ef9..a8de8c2e1e7 100644
--- a/tests/ui/link-section.rs
+++ b/tests/ui/link-section.rs
@@ -1,5 +1,8 @@
 //@ run-pass
 
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
 #![allow(non_upper_case_globals)]
 #[cfg(not(target_vendor = "apple"))]
 #[link_section = ".moretext"]
diff --git a/tests/ui/linkage-attr/linkage-attr-mutable-static.rs b/tests/ui/linkage-attr/linkage-attr-mutable-static.rs
index ed11947f59e..cc93f61e28f 100644
--- a/tests/ui/linkage-attr/linkage-attr-mutable-static.rs
+++ b/tests/ui/linkage-attr/linkage-attr-mutable-static.rs
@@ -2,6 +2,8 @@
 //! them at runtime, so deny mutable statics with #[linkage].
 
 #![feature(linkage)]
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
 
 fn main() {
     #[rustfmt::skip]
diff --git a/tests/ui/linkage-attr/linkage-attr-mutable-static.stderr b/tests/ui/linkage-attr/linkage-attr-mutable-static.stderr
index ad999769047..50d5d812196 100644
--- a/tests/ui/linkage-attr/linkage-attr-mutable-static.stderr
+++ b/tests/ui/linkage-attr/linkage-attr-mutable-static.stderr
@@ -1,5 +1,5 @@
 error: extern mutable statics are not allowed with `#[linkage]`
-  --> $DIR/linkage-attr-mutable-static.rs:9:9
+  --> $DIR/linkage-attr-mutable-static.rs:11:9
    |
 LL |         #[linkage = "extern_weak"]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/extern-C-fnptr-lints-slices.rs b/tests/ui/lint/extern-C-fnptr-lints-slices.rs
new file mode 100644
index 00000000000..0c35eb37a48
--- /dev/null
+++ b/tests/ui/lint/extern-C-fnptr-lints-slices.rs
@@ -0,0 +1,9 @@
+#[deny(improper_ctypes_definitions)]
+
+// It's an improper ctype (a slice) arg in an extern "C" fnptr.
+
+pub type F = extern "C" fn(&[u8]);
+//~^ ERROR: `extern` fn uses type `[u8]`, which is not FFI-safe
+
+
+fn main() {}
diff --git a/tests/ui/lint/extern-C-fnptr-lints-slices.stderr b/tests/ui/lint/extern-C-fnptr-lints-slices.stderr
new file mode 100644
index 00000000000..d13f93ca96f
--- /dev/null
+++ b/tests/ui/lint/extern-C-fnptr-lints-slices.stderr
@@ -0,0 +1,16 @@
+error: `extern` fn uses type `[u8]`, which is not FFI-safe
+  --> $DIR/extern-C-fnptr-lints-slices.rs:5:14
+   |
+LL | pub type F = extern "C" fn(&[u8]);
+   |              ^^^^^^^^^^^^^^^^^^^^ not FFI-safe
+   |
+   = help: consider using a raw pointer instead
+   = note: slices have no C equivalent
+note: the lint level is defined here
+  --> $DIR/extern-C-fnptr-lints-slices.rs:1:8
+   |
+LL | #[deny(improper_ctypes_definitions)]
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/lint/improper-types-stack-overflow-130310.rs b/tests/ui/lint/improper-types-stack-overflow-130310.rs
new file mode 100644
index 00000000000..60eb8739817
--- /dev/null
+++ b/tests/ui/lint/improper-types-stack-overflow-130310.rs
@@ -0,0 +1,20 @@
+// Regression test for #130310
+// Tests that we do not fall into infinite
+// recursion while checking FFI safety of
+// recursive types like `A<T>` below
+
+//@ build-pass
+use std::marker::PhantomData;
+
+#[repr(C)]
+struct A<T> {
+    a: *const A<A<T>>, // Recursive because of this field
+    p: PhantomData<T>,
+}
+
+extern "C" {
+    fn f(a: *const A<()>);
+    //~^ WARN `extern` block uses type `*const A<()>`, which is not FFI-safe
+}
+
+fn main() {}
diff --git a/tests/ui/lint/improper-types-stack-overflow-130310.stderr b/tests/ui/lint/improper-types-stack-overflow-130310.stderr
new file mode 100644
index 00000000000..6981bb25755
--- /dev/null
+++ b/tests/ui/lint/improper-types-stack-overflow-130310.stderr
@@ -0,0 +1,11 @@
+warning: `extern` block uses type `*const A<()>`, which is not FFI-safe
+  --> $DIR/improper-types-stack-overflow-130310.rs:16:13
+   |
+LL |     fn f(a: *const A<()>);
+   |             ^^^^^^^^^^^^ not FFI-safe
+   |
+   = note: type is infinitely recursive
+   = note: `#[warn(improper_ctypes)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin.rs
deleted file mode 100644
index f8aad88ecee..00000000000
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@ only-x86_64-unknown-linux-gnu
-//@ check-pass
-#![crate_name = "NonSnakeCase"]
-
-#![deny(non_snake_case)]
-
-fn main() {}
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin2.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin2.rs
deleted file mode 100644
index c077d81e9e5..00000000000
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin2.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@ only-x86_64-unknown-linux-gnu
-//@ compile-flags: --crate-name NonSnakeCase
-//@ check-pass
-
-#![deny(non_snake_case)]
-
-fn main() {}
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin3.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin3.rs
deleted file mode 100644
index 278f7cfd3ee..00000000000
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-bin3.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-//@ only-x86_64-unknown-linux-gnu
-//@ check-pass
-#![crate_type = "bin"]
-#![crate_name = "NonSnakeCase"]
-
-#![deny(non_snake_case)]
-
-fn main() {}
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-cdylib.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-cdylib.rs
deleted file mode 100644
index 781c6794fc2..00000000000
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-cdylib.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@ only-x86_64-unknown-linux-gnu
-#![crate_type = "cdylib"]
-#![crate_name = "NonSnakeCase"]
-//~^ ERROR crate `NonSnakeCase` should have a snake case name
-#![deny(non_snake_case)]
-
-fn main() {}
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-dylib.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-dylib.rs
deleted file mode 100644
index 3f65295f068..00000000000
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-dylib.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@ only-x86_64-unknown-linux-gnu
-#![crate_type = "dylib"]
-#![crate_name = "NonSnakeCase"]
-//~^ ERROR crate `NonSnakeCase` should have a snake case name
-#![deny(non_snake_case)]
-
-fn main() {}
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-lib.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-lib.rs
deleted file mode 100644
index 20c58e66aa6..00000000000
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-lib.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@ only-x86_64-unknown-linux-gnu
-#![crate_type = "lib"]
-#![crate_name = "NonSnakeCase"]
-//~^ ERROR crate `NonSnakeCase` should have a snake case name
-#![deny(non_snake_case)]
-
-fn main() {}
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-proc-macro.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-proc-macro.rs
deleted file mode 100644
index f0f2fa4393e..00000000000
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-proc-macro.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@ only-x86_64-unknown-linux-gnu
-#![crate_type = "proc-macro"]
-#![crate_name = "NonSnakeCase"]
-//~^ ERROR crate `NonSnakeCase` should have a snake case name
-#![deny(non_snake_case)]
-
-fn main() {}
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-proc-macro.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-proc-macro.stderr
deleted file mode 100644
index e0091057bc9..00000000000
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-proc-macro.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error: crate `NonSnakeCase` should have a snake case name
-  --> $DIR/lint-non-snake-case-crate-proc-macro.rs:3:18
-   |
-LL | #![crate_name = "NonSnakeCase"]
-   |                  ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case`
-   |
-note: the lint level is defined here
-  --> $DIR/lint-non-snake-case-crate-proc-macro.rs:5:9
-   |
-LL | #![deny(non_snake_case)]
-   |         ^^^^^^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-rlib.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-rlib.rs
deleted file mode 100644
index 1a558def3d0..00000000000
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-rlib.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@ only-x86_64-unknown-linux-gnu
-#![crate_type = "rlib"]
-#![crate_name = "NonSnakeCase"]
-//~^ ERROR crate `NonSnakeCase` should have a snake case name
-#![deny(non_snake_case)]
-
-fn main() {}
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-staticlib.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-staticlib.rs
deleted file mode 100644
index 2ec53c15eb8..00000000000
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-staticlib.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-//@ only-x86_64-unknown-linux-gnu
-#![crate_type = "staticlib"]
-#![crate_name = "NonSnakeCase"]
-//~^ ERROR crate `NonSnakeCase` should have a snake case name
-#![deny(non_snake_case)]
-
-fn main() {}
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-staticlib.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-staticlib.stderr
deleted file mode 100644
index 4ee6d5bd4d4..00000000000
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-staticlib.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error: crate `NonSnakeCase` should have a snake case name
-  --> $DIR/lint-non-snake-case-crate-staticlib.rs:3:18
-   |
-LL | #![crate_name = "NonSnakeCase"]
-   |                  ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case`
-   |
-note: the lint level is defined here
-  --> $DIR/lint-non-snake-case-crate-staticlib.rs:5:9
-   |
-LL | #![deny(non_snake_case)]
-   |         ^^^^^^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-lib.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr
index a68c0e832b8..9bccb270627 100644
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-lib.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.cdylib_.stderr
@@ -1,11 +1,11 @@
 error: crate `NonSnakeCase` should have a snake case name
-  --> $DIR/lint-non-snake-case-crate-lib.rs:3:18
+  --> $DIR/lint-non-snake-case-crate.rs:25:18
    |
 LL | #![crate_name = "NonSnakeCase"]
    |                  ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case`
    |
 note: the lint level is defined here
-  --> $DIR/lint-non-snake-case-crate-lib.rs:5:9
+  --> $DIR/lint-non-snake-case-crate.rs:27:9
    |
 LL | #![deny(non_snake_case)]
    |         ^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-rlib.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr
index 6e9d54bd5bc..9bccb270627 100644
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-rlib.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.dylib_.stderr
@@ -1,11 +1,11 @@
 error: crate `NonSnakeCase` should have a snake case name
-  --> $DIR/lint-non-snake-case-crate-rlib.rs:3:18
+  --> $DIR/lint-non-snake-case-crate.rs:25:18
    |
 LL | #![crate_name = "NonSnakeCase"]
    |                  ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case`
    |
 note: the lint level is defined here
-  --> $DIR/lint-non-snake-case-crate-rlib.rs:5:9
+  --> $DIR/lint-non-snake-case-crate.rs:27:9
    |
 LL | #![deny(non_snake_case)]
    |         ^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-dylib.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr
index 4ee1a9cb3dd..9bccb270627 100644
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-dylib.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.lib_.stderr
@@ -1,11 +1,11 @@
 error: crate `NonSnakeCase` should have a snake case name
-  --> $DIR/lint-non-snake-case-crate-dylib.rs:3:18
+  --> $DIR/lint-non-snake-case-crate.rs:25:18
    |
 LL | #![crate_name = "NonSnakeCase"]
    |                  ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case`
    |
 note: the lint level is defined here
-  --> $DIR/lint-non-snake-case-crate-dylib.rs:5:9
+  --> $DIR/lint-non-snake-case-crate.rs:27:9
    |
 LL | #![deny(non_snake_case)]
    |         ^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-cdylib.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr
index f9167aa8df3..9bccb270627 100644
--- a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate-cdylib.stderr
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.proc_macro_.stderr
@@ -1,11 +1,11 @@
 error: crate `NonSnakeCase` should have a snake case name
-  --> $DIR/lint-non-snake-case-crate-cdylib.rs:3:18
+  --> $DIR/lint-non-snake-case-crate.rs:25:18
    |
 LL | #![crate_name = "NonSnakeCase"]
    |                  ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case`
    |
 note: the lint level is defined here
-  --> $DIR/lint-non-snake-case-crate-cdylib.rs:5:9
+  --> $DIR/lint-non-snake-case-crate.rs:27:9
    |
 LL | #![deny(non_snake_case)]
    |         ^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr
new file mode 100644
index 00000000000..9bccb270627
--- /dev/null
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rlib_.stderr
@@ -0,0 +1,14 @@
+error: crate `NonSnakeCase` should have a snake case name
+  --> $DIR/lint-non-snake-case-crate.rs:25:18
+   |
+LL | #![crate_name = "NonSnakeCase"]
+   |                  ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case`
+   |
+note: the lint level is defined here
+  --> $DIR/lint-non-snake-case-crate.rs:27:9
+   |
+LL | #![deny(non_snake_case)]
+   |         ^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs
new file mode 100644
index 00000000000..57604d99a07
--- /dev/null
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.rs
@@ -0,0 +1,29 @@
+//! Don't lint on binary crate with non-snake-case names.
+//!
+//! See <https://github.com/rust-lang/rust/issues/45127>.
+
+//@ revisions: bin_ cdylib_ dylib_ lib_ proc_macro_ rlib_ staticlib_
+
+// Should not fire on binary crates.
+//@[bin_] compile-flags: --crate-type=bin
+//@[bin_] check-pass
+
+// But should fire on non-binary crates.
+
+//@[cdylib_] ignore-musl (dylibs are not supported)
+//@[dylib_] ignore-musl (dylibs are not supported)
+//@[dylib_] ignore-wasm (dylib is not supported)
+//@[proc_macro_] ignore-wasm (dylib is not supported)
+
+//@[cdylib_] compile-flags: --crate-type=cdylib
+//@[dylib_] compile-flags: --crate-type=dylib
+//@[lib_] compile-flags: --crate-type=lib
+//@[proc_macro_] compile-flags: --crate-type=proc-macro
+//@[rlib_] compile-flags: --crate-type=rlib
+//@[staticlib_] compile-flags: --crate-type=staticlib
+
+#![crate_name = "NonSnakeCase"]
+//[cdylib_,dylib_,lib_,proc_macro_,rlib_,staticlib_]~^ ERROR crate `NonSnakeCase` should have a snake case name
+#![deny(non_snake_case)]
+
+fn main() {}
diff --git a/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr
new file mode 100644
index 00000000000..9bccb270627
--- /dev/null
+++ b/tests/ui/lint/non-snake-case/lint-non-snake-case-crate.staticlib_.stderr
@@ -0,0 +1,14 @@
+error: crate `NonSnakeCase` should have a snake case name
+  --> $DIR/lint-non-snake-case-crate.rs:25:18
+   |
+LL | #![crate_name = "NonSnakeCase"]
+   |                  ^^^^^^^^^^^^ help: convert the identifier to snake case: `non_snake_case`
+   |
+note: the lint level is defined here
+  --> $DIR/lint-non-snake-case-crate.rs:27:9
+   |
+LL | #![deny(non_snake_case)]
+   |         ^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/lint/rust-cold-fn-accept-improper-ctypes.rs b/tests/ui/lint/rust-cold-fn-accept-improper-ctypes.rs
new file mode 100644
index 00000000000..dc929e14527
--- /dev/null
+++ b/tests/ui/lint/rust-cold-fn-accept-improper-ctypes.rs
@@ -0,0 +1,14 @@
+//@ check-pass
+#![feature(rust_cold_cc)]
+
+// extern "rust-cold" is a "Rust" ABI so we accept `repr(Rust)` types as arg/ret without warnings.
+
+pub extern "rust-cold" fn f(_: ()) -> Result<(), ()> {
+    Ok(())
+}
+
+extern "rust-cold" {
+    pub fn g(_: ()) -> Result<(), ()>;
+}
+
+fn main() {}
diff --git a/tests/ui/lint/static-mut-refs.e2021.stderr b/tests/ui/lint/static-mut-refs.e2021.stderr
new file mode 100644
index 00000000000..09f560652e7
--- /dev/null
+++ b/tests/ui/lint/static-mut-refs.e2021.stderr
@@ -0,0 +1,143 @@
+warning: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-refs.rs:39:18
+   |
+LL |         let _y = &X;
+   |                  ^^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+   = note: `#[warn(static_mut_refs)]` on by default
+help: use `&raw const` instead to create a raw pointer
+   |
+LL |         let _y = &raw const X;
+   |                  ~~~~~~~~~~
+
+warning: creating a mutable reference to mutable static is discouraged
+  --> $DIR/static-mut-refs.rs:43:18
+   |
+LL |         let _y = &mut X;
+   |                  ^^^^^^ mutable reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives
+help: use `&raw mut` instead to create a raw pointer
+   |
+LL |         let _y = &raw mut X;
+   |                  ~~~~~~~~
+
+warning: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-refs.rs:51:22
+   |
+LL |         let ref _a = X;
+   |                      ^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+
+warning: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-refs.rs:55:25
+   |
+LL |         let (_b, _c) = (&X, &Y);
+   |                         ^^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+help: use `&raw const` instead to create a raw pointer
+   |
+LL |         let (_b, _c) = (&raw const X, &Y);
+   |                         ~~~~~~~~~~
+
+warning: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-refs.rs:55:29
+   |
+LL |         let (_b, _c) = (&X, &Y);
+   |                             ^^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+help: use `&raw const` instead to create a raw pointer
+   |
+LL |         let (_b, _c) = (&X, &raw const Y);
+   |                             ~~~~~~~~~~
+
+warning: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-refs.rs:61:13
+   |
+LL |         foo(&X);
+   |             ^^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+help: use `&raw const` instead to create a raw pointer
+   |
+LL |         foo(&raw const X);
+   |             ~~~~~~~~~~
+
+warning: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-refs.rs:67:17
+   |
+LL |         let _ = Z.len();
+   |                 ^^^^^^^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+
+warning: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-refs.rs:73:33
+   |
+LL |         let _ = format!("{:?}", Z);
+   |                                 ^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+
+warning: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-refs.rs:77:18
+   |
+LL |         let _v = &A.value;
+   |                  ^^^^^^^^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+help: use `&raw const` instead to create a raw pointer
+   |
+LL |         let _v = &raw const A.value;
+   |                  ~~~~~~~~~~
+
+warning: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-refs.rs:81:18
+   |
+LL |         let _s = &A.s.value;
+   |                  ^^^^^^^^^^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+help: use `&raw const` instead to create a raw pointer
+   |
+LL |         let _s = &raw const A.s.value;
+   |                  ~~~~~~~~~~
+
+warning: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-refs.rs:85:22
+   |
+LL |         let ref _v = A.value;
+   |                      ^^^^^^^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+
+warning: creating a mutable reference to mutable static is discouraged
+  --> $DIR/static-mut-refs.rs:15:14
+   |
+LL |         &mut ($x.0)
+   |              ^^^^^^ mutable reference to mutable static
+...
+LL |         let _x = bar!(FOO);
+   |                  --------- in this macro invocation
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives
+   = note: this warning originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: 12 warnings emitted
+
diff --git a/tests/ui/lint/static-mut-refs.e2024.stderr b/tests/ui/lint/static-mut-refs.e2024.stderr
new file mode 100644
index 00000000000..2d2a4f7afe0
--- /dev/null
+++ b/tests/ui/lint/static-mut-refs.e2024.stderr
@@ -0,0 +1,143 @@
+error: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-refs.rs:39:18
+   |
+LL |         let _y = &X;
+   |                  ^^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+   = note: `#[deny(static_mut_refs)]` on by default
+help: use `&raw const` instead to create a raw pointer
+   |
+LL |         let _y = &raw const X;
+   |                  ~~~~~~~~~~
+
+error: creating a mutable reference to mutable static is discouraged
+  --> $DIR/static-mut-refs.rs:43:18
+   |
+LL |         let _y = &mut X;
+   |                  ^^^^^^ mutable reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives
+help: use `&raw mut` instead to create a raw pointer
+   |
+LL |         let _y = &raw mut X;
+   |                  ~~~~~~~~
+
+error: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-refs.rs:51:22
+   |
+LL |         let ref _a = X;
+   |                      ^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+
+error: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-refs.rs:55:25
+   |
+LL |         let (_b, _c) = (&X, &Y);
+   |                         ^^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+help: use `&raw const` instead to create a raw pointer
+   |
+LL |         let (_b, _c) = (&raw const X, &Y);
+   |                         ~~~~~~~~~~
+
+error: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-refs.rs:55:29
+   |
+LL |         let (_b, _c) = (&X, &Y);
+   |                             ^^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+help: use `&raw const` instead to create a raw pointer
+   |
+LL |         let (_b, _c) = (&X, &raw const Y);
+   |                             ~~~~~~~~~~
+
+error: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-refs.rs:61:13
+   |
+LL |         foo(&X);
+   |             ^^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+help: use `&raw const` instead to create a raw pointer
+   |
+LL |         foo(&raw const X);
+   |             ~~~~~~~~~~
+
+error: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-refs.rs:67:17
+   |
+LL |         let _ = Z.len();
+   |                 ^^^^^^^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+
+error: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-refs.rs:73:33
+   |
+LL |         let _ = format!("{:?}", Z);
+   |                                 ^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+
+error: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-refs.rs:77:18
+   |
+LL |         let _v = &A.value;
+   |                  ^^^^^^^^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+help: use `&raw const` instead to create a raw pointer
+   |
+LL |         let _v = &raw const A.value;
+   |                  ~~~~~~~~~~
+
+error: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-refs.rs:81:18
+   |
+LL |         let _s = &A.s.value;
+   |                  ^^^^^^^^^^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+help: use `&raw const` instead to create a raw pointer
+   |
+LL |         let _s = &raw const A.s.value;
+   |                  ~~~~~~~~~~
+
+error: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-refs.rs:85:22
+   |
+LL |         let ref _v = A.value;
+   |                      ^^^^^^^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+
+error: creating a mutable reference to mutable static is discouraged
+  --> $DIR/static-mut-refs.rs:15:14
+   |
+LL |         &mut ($x.0)
+   |              ^^^^^^ mutable reference to mutable static
+...
+LL |         let _x = bar!(FOO);
+   |                  --------- in this macro invocation
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives
+   = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 12 previous errors
+
diff --git a/tests/ui/lint/static-mut-refs.rs b/tests/ui/lint/static-mut-refs.rs
new file mode 100644
index 00000000000..3d84d7dbf40
--- /dev/null
+++ b/tests/ui/lint/static-mut-refs.rs
@@ -0,0 +1,95 @@
+// Test `static_mut_refs` lint.
+
+//@ revisions: e2021 e2024
+
+//@ [e2021] edition:2021
+//@ [e2021] run-pass
+
+//@ [e2024] edition:2024
+//@ [e2024] compile-flags: -Zunstable-options
+
+static mut FOO: (u32, u32) = (1, 2);
+
+macro_rules! bar {
+    ($x:expr) => {
+        &mut ($x.0)
+        //[e2021]~^ WARN creating a mutable reference to mutable static is discouraged [static_mut_refs]
+        //[e2024]~^^ ERROR creating a mutable reference to mutable static is discouraged [static_mut_refs]
+    };
+}
+
+static mut STATIC: i64 = 1;
+
+fn main() {
+    static mut X: i32 = 1;
+
+    static mut Y: i32 = 1;
+
+    struct TheStruct {
+        pub value: i32,
+    }
+    struct MyStruct {
+        pub value: i32,
+        pub s: TheStruct,
+    }
+
+    static mut A: MyStruct = MyStruct { value: 1, s: TheStruct { value: 2 } };
+
+    unsafe {
+        let _y = &X;
+        //[e2021]~^ WARN shared reference to mutable static is discouraged [static_mut_refs]
+        //[e2024]~^^ ERROR shared reference to mutable static is discouraged [static_mut_refs]
+
+        let _y = &mut X;
+        //[e2021]~^ WARN mutable reference to mutable static is discouraged [static_mut_refs]
+        //[e2024]~^^ ERROR mutable reference to mutable static is discouraged [static_mut_refs]
+
+        let _z = &raw mut X;
+
+        let _p = &raw const X;
+
+        let ref _a = X;
+        //[e2021]~^ WARN shared reference to mutable static is discouraged [static_mut_refs]
+        //[e2024]~^^ ERROR shared reference to mutable static is discouraged [static_mut_refs]
+
+        let (_b, _c) = (&X, &Y);
+        //[e2021]~^ WARN shared reference to mutable static is discouraged [static_mut_refs]
+        //[e2024]~^^ ERROR shared reference to mutable static is discouraged [static_mut_refs]
+        //[e2021]~^^^ WARN shared reference to mutable static is discouraged [static_mut_refs]
+        //[e2024]~^^^^ ERROR shared reference to mutable static is discouraged [static_mut_refs]
+
+        foo(&X);
+        //[e2021]~^ WARN shared reference to mutable static is discouraged [static_mut_refs]
+        //[e2024]~^^ ERROR shared reference to mutable static is discouraged [static_mut_refs]
+
+        static mut Z: &[i32; 3] = &[0, 1, 2];
+
+        let _ = Z.len();
+        //[e2021]~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs]
+        //[e2024]~^^ ERROR creating a shared reference to mutable static is discouraged [static_mut_refs]
+
+        let _ = Z[0];
+
+        let _ = format!("{:?}", Z);
+        //[e2021]~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs]
+        //[e2024]~^^ ERROR creating a shared reference to mutable static is discouraged [static_mut_refs]
+
+        let _v = &A.value;
+        //[e2021]~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs]
+        //[e2024]~^^ ERROR creating a shared reference to mutable static is discouraged [static_mut_refs]
+
+        let _s = &A.s.value;
+        //[e2021]~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs]
+        //[e2024]~^^ ERROR creating a shared reference to mutable static is discouraged [static_mut_refs]
+
+        let ref _v = A.value;
+        //[e2021]~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs]
+        //[e2024]~^^ ERROR creating a shared reference to mutable static is discouraged [static_mut_refs]
+
+        let _x = bar!(FOO);
+
+        STATIC += 1;
+    }
+}
+
+fn foo<'a>(_x: &'a i32) {}
diff --git a/tests/ui/lto/lto-still-runs-thread-dtors.rs b/tests/ui/lto/lto-still-runs-thread-dtors.rs
index 504923a93c2..900368496eb 100644
--- a/tests/ui/lto/lto-still-runs-thread-dtors.rs
+++ b/tests/ui/lto/lto-still-runs-thread-dtors.rs
@@ -3,6 +3,9 @@
 //@ no-prefer-dynamic
 //@ needs-threads
 
+// FIXME(static_mut_refs): this could use an atomic
+#![allow(static_mut_refs)]
+
 use std::thread;
 
 static mut HIT: usize = 0;
diff --git a/tests/ui/macros/auxiliary/metavar_2018.rs b/tests/ui/macros/auxiliary/metavar_2018.rs
new file mode 100644
index 00000000000..7e8523a9edf
--- /dev/null
+++ b/tests/ui/macros/auxiliary/metavar_2018.rs
@@ -0,0 +1,14 @@
+//@ edition: 2018
+#[macro_export]
+macro_rules! make_matcher {
+    ($name:ident, $fragment_type:ident, $d:tt) => {
+        #[macro_export]
+        macro_rules! $name {
+            ($d _:$fragment_type) => { true };
+            (const { 0 }) => { false };
+            (A | B) => { false };
+        }
+    };
+}
+make_matcher!(is_expr_from_2018, expr, $);
+make_matcher!(is_pat_from_2018, pat, $);
diff --git a/tests/ui/macros/metavar_cross_edition_recursive_macros.rs b/tests/ui/macros/metavar_cross_edition_recursive_macros.rs
new file mode 100644
index 00000000000..3eec1208b89
--- /dev/null
+++ b/tests/ui/macros/metavar_cross_edition_recursive_macros.rs
@@ -0,0 +1,38 @@
+//@ compile-flags: --edition=2024 -Z unstable-options
+//@ aux-build: metavar_2018.rs
+//@ known-bug: #130484
+//@ run-pass
+
+// This test captures the behavior of macro-generating-macros with fragment
+// specifiers across edition boundaries.
+
+#![feature(expr_fragment_specifier_2024)]
+#![feature(macro_metavar_expr)]
+#![allow(incomplete_features)]
+
+extern crate metavar_2018;
+
+use metavar_2018::{is_expr_from_2018, is_pat_from_2018, make_matcher};
+
+make_matcher!(is_expr_from_2024, expr, $);
+make_matcher!(is_pat_from_2024, pat, $);
+
+fn main() {
+    // Check expr
+    let from_2018 = is_expr_from_2018!(const { 0 });
+    dbg!(from_2018);
+    let from_2024 = is_expr_from_2024!(const { 0 });
+    dbg!(from_2024);
+
+    assert!(!from_2018);
+    assert!(!from_2024); // from_2024 will be true once #130484 is fixed
+
+    // Check pat
+    let from_2018 = is_pat_from_2018!(A | B);
+    dbg!(from_2018);
+    let from_2024 = is_pat_from_2024!(A | B);
+    dbg!(from_2024);
+
+    assert!(!from_2018);
+    assert!(!from_2024); // from_2024 will be true once #130484 is fixed
+}
diff --git a/tests/ui/methods/method-self-arg-trait.rs b/tests/ui/methods/method-self-arg-trait.rs
index 63594380753..ccffe02328b 100644
--- a/tests/ui/methods/method-self-arg-trait.rs
+++ b/tests/ui/methods/method-self-arg-trait.rs
@@ -1,6 +1,9 @@
 //@ run-pass
 // Test method calls with self as an argument
 
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
 static mut COUNT: u64 = 1;
 
 #[derive(Copy, Clone)]
diff --git a/tests/ui/methods/method-self-arg.rs b/tests/ui/methods/method-self-arg.rs
index d26b9663fd0..2e058ee1077 100644
--- a/tests/ui/methods/method-self-arg.rs
+++ b/tests/ui/methods/method-self-arg.rs
@@ -1,6 +1,9 @@
 //@ run-pass
 // Test method calls with self as an argument
 
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
 static mut COUNT: usize = 1;
 
 #[derive(Copy, Clone)]
diff --git a/tests/ui/mir/mir_early_return_scope.rs b/tests/ui/mir/mir_early_return_scope.rs
index 6dc3f8bc39b..42f1cc50d15 100644
--- a/tests/ui/mir/mir_early_return_scope.rs
+++ b/tests/ui/mir/mir_early_return_scope.rs
@@ -1,5 +1,7 @@
 //@ run-pass
 #![allow(unused_variables)]
+// FIXME(static_mut_refs): this could use an atomic
+#![allow(static_mut_refs)]
 static mut DROP: bool = false;
 
 struct ConnWrap(Conn);
diff --git a/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr b/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr
index a6d4f9a2a5c..1f01d3e8260 100644
--- a/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr
+++ b/tests/ui/nll/borrowck-thread-local-static-mut-borrow-outlives-fn.stderr
@@ -4,14 +4,13 @@ warning: creating a mutable reference to mutable static is discouraged
 LL |         S1 { a: unsafe { &mut X1 } }
    |                          ^^^^^^^ 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
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives
    = note: `#[warn(static_mut_refs)]` on by default
-help: use `addr_of_mut!` instead to create a raw pointer
+help: use `&raw mut` instead to create a raw pointer
    |
-LL |         S1 { a: unsafe { addr_of_mut!(X1) } }
-   |                          ~~~~~~~~~~~~~  +
+LL |         S1 { a: unsafe { &raw mut X1 } }
+   |                          ~~~~~~~~
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/nll/issue-69114-static-mut-ty.rs b/tests/ui/nll/issue-69114-static-mut-ty.rs
index ce37da053e3..95c787488c0 100644
--- a/tests/ui/nll/issue-69114-static-mut-ty.rs
+++ b/tests/ui/nll/issue-69114-static-mut-ty.rs
@@ -1,5 +1,8 @@
 // Check that borrowck ensures that `static mut` items have the expected type.
 
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
 static FOO: u8 = 42;
 static mut BAR: &'static u8 = &FOO;
 static mut BAR_ELIDED: &u8 = &FOO;
diff --git a/tests/ui/nll/issue-69114-static-mut-ty.stderr b/tests/ui/nll/issue-69114-static-mut-ty.stderr
index 1b41230d7ba..eebfdee2896 100644
--- a/tests/ui/nll/issue-69114-static-mut-ty.stderr
+++ b/tests/ui/nll/issue-69114-static-mut-ty.stderr
@@ -1,5 +1,5 @@
 error[E0597]: `n` does not live long enough
-  --> $DIR/issue-69114-static-mut-ty.rs:19:15
+  --> $DIR/issue-69114-static-mut-ty.rs:22:15
    |
 LL |     let n = 42;
    |         - binding `n` declared here
@@ -14,7 +14,7 @@ LL | }
    | - `n` dropped here while still borrowed
 
 error[E0597]: `n` does not live long enough
-  --> $DIR/issue-69114-static-mut-ty.rs:27:22
+  --> $DIR/issue-69114-static-mut-ty.rs:30:22
    |
 LL |     let n = 42;
    |         - binding `n` declared here
diff --git a/tests/ui/numbers-arithmetic/shift-near-oflo.rs b/tests/ui/numbers-arithmetic/shift-near-oflo.rs
index 5cca31af0e3..97227bd843f 100644
--- a/tests/ui/numbers-arithmetic/shift-near-oflo.rs
+++ b/tests/ui/numbers-arithmetic/shift-near-oflo.rs
@@ -1,6 +1,9 @@
 //@ run-pass
 //@ compile-flags: -C debug-assertions
 
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
 // Check that we do *not* overflow on a number of edge cases.
 // (compare with test/run-fail/overflowing-{lsh,rsh}*.rs)
 
diff --git a/tests/ui/parser/bad-name.rs b/tests/ui/parser/bad-name.rs
index 59432a1d9a5..fefe9122a08 100644
--- a/tests/ui/parser/bad-name.rs
+++ b/tests/ui/parser/bad-name.rs
@@ -1,5 +1,6 @@
-//@ error-pattern: expected
-
 fn main() {
   let x.y::<isize>.z foo;
+  //~^ error: field expressions cannot have generic arguments
+  //~| error: expected a pattern, found an expression
+  //~| error: expected one of `(`, `.`, `::`, `:`, `;`, `=`, `?`, `|`, or an operator, found `foo`
 }
diff --git a/tests/ui/parser/bad-name.stderr b/tests/ui/parser/bad-name.stderr
index e133d4e4839..3fc416dd531 100644
--- a/tests/ui/parser/bad-name.stderr
+++ b/tests/ui/parser/bad-name.stderr
@@ -1,8 +1,20 @@
-error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
-  --> $DIR/bad-name.rs:4:8
+error: field expressions cannot have generic arguments
+  --> $DIR/bad-name.rs:2:12
    |
 LL |   let x.y::<isize>.z foo;
-   |        ^ expected one of `:`, `;`, `=`, `@`, or `|`
+   |            ^^^^^^^
 
-error: aborting due to 1 previous error
+error: expected a pattern, found an expression
+  --> $DIR/bad-name.rs:2:7
+   |
+LL |   let x.y::<isize>.z foo;
+   |       ^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
+
+error: expected one of `(`, `.`, `::`, `:`, `;`, `=`, `?`, `|`, or an operator, found `foo`
+  --> $DIR/bad-name.rs:2:22
+   |
+LL |   let x.y::<isize>.z foo;
+   |                      ^^^ expected one of 9 possible tokens
+
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/circular-module-with-doc-comment-issue-97589.rs b/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/circular-module-with-doc-comment-issue-97589.rs
new file mode 100644
index 00000000000..ff28548b795
--- /dev/null
+++ b/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/circular-module-with-doc-comment-issue-97589.rs
@@ -0,0 +1,6 @@
+//@ error-pattern: circular modules
+// Regression test for #97589: a doc-comment on a circular module bypassed cycle detection
+
+#![crate_type = "lib"]
+
+pub mod recursive;
diff --git a/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/circular-module-with-doc-comment-issue-97589.stderr b/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/circular-module-with-doc-comment-issue-97589.stderr
new file mode 100644
index 00000000000..02d6406775a
--- /dev/null
+++ b/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/circular-module-with-doc-comment-issue-97589.stderr
@@ -0,0 +1,8 @@
+error: circular modules: $DIR/recursive.rs -> $DIR/recursive.rs
+  --> $DIR/recursive.rs:6:1
+   |
+LL | mod recursive;
+   | ^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/recursive.rs b/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/recursive.rs
new file mode 100644
index 00000000000..3d758be8c05
--- /dev/null
+++ b/tests/ui/parser/issues/circular-module-with-doc-comment-issue-97589/recursive.rs
@@ -0,0 +1,6 @@
+//@ ignore-test: this is an auxiliary file for circular-module-with-doc-comment-issue-97589.rs
+
+//! this comment caused the circular dependency checker to break
+
+#[path = "recursive.rs"]
+mod recursive;
diff --git a/tests/ui/parser/issues/issue-24375.stderr b/tests/ui/parser/issues/issue-24375.stderr
index e6ef07d13fd..a25c277d78a 100644
--- a/tests/ui/parser/issues/issue-24375.stderr
+++ b/tests/ui/parser/issues/issue-24375.stderr
@@ -3,6 +3,21 @@ error: expected a pattern, found an expression
    |
 LL |         tmp[0] => {}
    |         ^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == tmp[0] => {}
+   |         ~~~ ++++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = tmp[0];
+LL ~     match z {
+LL ~         VAL => {}
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { tmp[0] } => {}
+   |         +++++++        +
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/pat-lt-bracket-6.stderr b/tests/ui/parser/pat-lt-bracket-6.stderr
index 10c638a63e4..892883c4aed 100644
--- a/tests/ui/parser/pat-lt-bracket-6.stderr
+++ b/tests/ui/parser/pat-lt-bracket-6.stderr
@@ -1,8 +1,8 @@
 error: expected a pattern, found an expression
-  --> $DIR/pat-lt-bracket-6.rs:5:15
+  --> $DIR/pat-lt-bracket-6.rs:5:14
    |
 LL |     let Test(&desc[..]) = x;
-   |               ^^^^^^^^ arbitrary expressions are not allowed in patterns
+   |              ^^^^^^^^^ arbitrary expressions are not allowed in patterns
 
 error[E0308]: mismatched types
   --> $DIR/pat-lt-bracket-6.rs:10:30
diff --git a/tests/ui/parser/pat-recover-exprs.rs b/tests/ui/parser/pat-recover-exprs.rs
deleted file mode 100644
index ecd471467e3..00000000000
--- a/tests/ui/parser/pat-recover-exprs.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-fn main() {
-    match u8::MAX {
-        u8::MAX.abs() => (),
-        //~^ error: expected a pattern, found a method call
-        x.sqrt() @ .. => (),
-        //~^ error: expected a pattern, found a method call
-        //~| error: left-hand side of `@` must be a binding
-        z @ w @ v.u() => (),
-        //~^ error: expected a pattern, found a method call
-        y.ilog(3) => (),
-        //~^ error: expected a pattern, found a method call
-        n + 1 => (),
-        //~^ error: expected a pattern, found an expression
-        ("".f() + 14 * 8) => (),
-        //~^ error: expected a pattern, found an expression
-        0 | ((1) | 2) | 3 => (),
-        f?() => (),
-        //~^ error: expected a pattern, found an expression
-        (_ + 1) => (),
-        //~^ error: expected one of `)`, `,`, or `|`, found `+`
-    }
-
-    let 1 + 1 = 2;
-    //~^ error: expected a pattern, found an expression
-
-    let b = matches!(x, (x * x | x.f()) | x[0]);
-    //~^ error: expected one of `)`, `,`, `@`, or `|`, found `*`
-}
diff --git a/tests/ui/parser/pat-recover-exprs.stderr b/tests/ui/parser/pat-recover-exprs.stderr
deleted file mode 100644
index 787fd03b0c3..00000000000
--- a/tests/ui/parser/pat-recover-exprs.stderr
+++ /dev/null
@@ -1,76 +0,0 @@
-error: expected a pattern, found a method call
-  --> $DIR/pat-recover-exprs.rs:3:9
-   |
-LL |         u8::MAX.abs() => (),
-   |         ^^^^^^^^^^^^^ method calls are not allowed in patterns
-
-error: expected a pattern, found a method call
-  --> $DIR/pat-recover-exprs.rs:5:9
-   |
-LL |         x.sqrt() @ .. => (),
-   |         ^^^^^^^^ method calls are not allowed in patterns
-
-error: left-hand side of `@` must be a binding
-  --> $DIR/pat-recover-exprs.rs:5:9
-   |
-LL |         x.sqrt() @ .. => (),
-   |         --------^^^--
-   |         |          |
-   |         |          also a pattern
-   |         interpreted as a pattern, not a binding
-   |
-   = note: bindings are `x`, `mut x`, `ref x`, and `ref mut x`
-
-error: expected a pattern, found a method call
-  --> $DIR/pat-recover-exprs.rs:8:17
-   |
-LL |         z @ w @ v.u() => (),
-   |                 ^^^^^ method calls are not allowed in patterns
-
-error: expected a pattern, found a method call
-  --> $DIR/pat-recover-exprs.rs:10:9
-   |
-LL |         y.ilog(3) => (),
-   |         ^^^^^^^^^ method calls are not allowed in patterns
-
-error: expected a pattern, found an expression
-  --> $DIR/pat-recover-exprs.rs:12:9
-   |
-LL |         n + 1 => (),
-   |         ^^^^^ arbitrary expressions are not allowed in patterns
-
-error: expected a pattern, found an expression
-  --> $DIR/pat-recover-exprs.rs:14:10
-   |
-LL |         ("".f() + 14 * 8) => (),
-   |          ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
-
-error: expected a pattern, found an expression
-  --> $DIR/pat-recover-exprs.rs:17:9
-   |
-LL |         f?() => (),
-   |         ^^^^ arbitrary expressions are not allowed in patterns
-
-error: expected one of `)`, `,`, or `|`, found `+`
-  --> $DIR/pat-recover-exprs.rs:19:12
-   |
-LL |         (_ + 1) => (),
-   |            ^ expected one of `)`, `,`, or `|`
-
-error: expected a pattern, found an expression
-  --> $DIR/pat-recover-exprs.rs:23:9
-   |
-LL |     let 1 + 1 = 2;
-   |         ^^^^^ arbitrary expressions are not allowed in patterns
-
-error: expected one of `)`, `,`, `@`, or `|`, found `*`
-  --> $DIR/pat-recover-exprs.rs:26:28
-   |
-LL |     let b = matches!(x, (x * x | x.f()) | x[0]);
-   |                            ^ expected one of `)`, `,`, `@`, or `|`
-  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
-   |
-   = note: while parsing argument for this `pat` macro fragment
-
-error: aborting due to 11 previous errors
-
diff --git a/tests/ui/parser/pat-recover-methodcalls.rs b/tests/ui/parser/pat-recover-methodcalls.rs
deleted file mode 100644
index 54104e9a535..00000000000
--- a/tests/ui/parser/pat-recover-methodcalls.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-struct Foo(String);
-struct Bar { baz: String }
-
-fn foo(foo: Foo) -> bool {
-    match foo {
-        Foo("hi".to_owned()) => true,
-        //~^ error: expected a pattern, found a method call
-        _ => false
-    }
-}
-
-fn bar(bar: Bar) -> bool {
-    match bar {
-        Bar { baz: "hi".to_owned() } => true,
-        //~^ error: expected a pattern, found a method call
-        _ => false
-    }
-}
-
-fn baz() { // issue #90121
-    let foo = vec!["foo".to_string()];
-
-    match foo.as_slice() {
-        &["foo".to_string()] => {}
-        //~^ error: expected a pattern, found a method call
-        _ => {}
-    };
-}
-
-fn main() {
-    if let (-1.some(4)) = (0, Some(4)) {}
-    //~^ error: expected a pattern, found a method call
-
-    if let (-1.Some(4)) = (0, Some(4)) {}
-    //~^ error: expected one of `)`, `,`, `...`, `..=`, `..`, or `|`, found `.`
-    //~| help: missing `,`
-}
diff --git a/tests/ui/parser/pat-recover-methodcalls.stderr b/tests/ui/parser/pat-recover-methodcalls.stderr
deleted file mode 100644
index 1f9ae81dc0c..00000000000
--- a/tests/ui/parser/pat-recover-methodcalls.stderr
+++ /dev/null
@@ -1,35 +0,0 @@
-error: expected a pattern, found a method call
-  --> $DIR/pat-recover-methodcalls.rs:6:13
-   |
-LL |         Foo("hi".to_owned()) => true,
-   |             ^^^^^^^^^^^^^^^ method calls are not allowed in patterns
-
-error: expected a pattern, found a method call
-  --> $DIR/pat-recover-methodcalls.rs:14:20
-   |
-LL |         Bar { baz: "hi".to_owned() } => true,
-   |                    ^^^^^^^^^^^^^^^ method calls are not allowed in patterns
-
-error: expected a pattern, found a method call
-  --> $DIR/pat-recover-methodcalls.rs:24:11
-   |
-LL |         &["foo".to_string()] => {}
-   |           ^^^^^^^^^^^^^^^^^ method calls are not allowed in patterns
-
-error: expected a pattern, found a method call
-  --> $DIR/pat-recover-methodcalls.rs:31:13
-   |
-LL |     if let (-1.some(4)) = (0, Some(4)) {}
-   |             ^^^^^^^^^^ method calls are not allowed in patterns
-
-error: expected one of `)`, `,`, `...`, `..=`, `..`, or `|`, found `.`
-  --> $DIR/pat-recover-methodcalls.rs:34:15
-   |
-LL |     if let (-1.Some(4)) = (0, Some(4)) {}
-   |               ^
-   |               |
-   |               expected one of `)`, `,`, `...`, `..=`, `..`, or `|`
-   |               help: missing `,`
-
-error: aborting due to 5 previous errors
-
diff --git a/tests/ui/parser/pat-recover-ranges.stderr b/tests/ui/parser/pat-recover-ranges.stderr
deleted file mode 100644
index a7d62bd7f8a..00000000000
--- a/tests/ui/parser/pat-recover-ranges.stderr
+++ /dev/null
@@ -1,132 +0,0 @@
-error: range pattern bounds cannot have parentheses
-  --> $DIR/pat-recover-ranges.rs:4:13
-   |
-LL |         0..=(1) => (),
-   |             ^ ^
-   |
-help: remove these parentheses
-   |
-LL -         0..=(1) => (),
-LL +         0..=1 => (),
-   |
-
-error: range pattern bounds cannot have parentheses
-  --> $DIR/pat-recover-ranges.rs:6:9
-   |
-LL |         (-12)..=4 => (),
-   |         ^   ^
-   |
-help: remove these parentheses
-   |
-LL -         (-12)..=4 => (),
-LL +         -12..=4 => (),
-   |
-
-error: range pattern bounds cannot have parentheses
-  --> $DIR/pat-recover-ranges.rs:8:9
-   |
-LL |         (0)..=(-4) => (),
-   |         ^ ^
-   |
-help: remove these parentheses
-   |
-LL -         (0)..=(-4) => (),
-LL +         0..=(-4) => (),
-   |
-
-error: range pattern bounds cannot have parentheses
-  --> $DIR/pat-recover-ranges.rs:8:15
-   |
-LL |         (0)..=(-4) => (),
-   |               ^  ^
-   |
-help: remove these parentheses
-   |
-LL -         (0)..=(-4) => (),
-LL +         (0)..=-4 => (),
-   |
-
-error: expected a pattern range bound, found an expression
-  --> $DIR/pat-recover-ranges.rs:11:12
-   |
-LL |         ..=1 + 2 => (),
-   |            ^^^^^ arbitrary expressions are not allowed in patterns
-
-error: range pattern bounds cannot have parentheses
-  --> $DIR/pat-recover-ranges.rs:13:9
-   |
-LL |         (4).. => (),
-   |         ^ ^
-   |
-help: remove these parentheses
-   |
-LL -         (4).. => (),
-LL +         4.. => (),
-   |
-
-error: expected a pattern range bound, found an expression
-  --> $DIR/pat-recover-ranges.rs:15:10
-   |
-LL |         (-4 + 0).. => (),
-   |          ^^^^^^ arbitrary expressions are not allowed in patterns
-
-error: range pattern bounds cannot have parentheses
-  --> $DIR/pat-recover-ranges.rs:15:9
-   |
-LL |         (-4 + 0).. => (),
-   |         ^      ^
-   |
-help: remove these parentheses
-   |
-LL -         (-4 + 0).. => (),
-LL +         -4 + 0.. => (),
-   |
-
-error: expected a pattern range bound, found an expression
-  --> $DIR/pat-recover-ranges.rs:18:10
-   |
-LL |         (1 + 4)...1 * 2 => (),
-   |          ^^^^^ arbitrary expressions are not allowed in patterns
-
-error: range pattern bounds cannot have parentheses
-  --> $DIR/pat-recover-ranges.rs:18:9
-   |
-LL |         (1 + 4)...1 * 2 => (),
-   |         ^     ^
-   |
-help: remove these parentheses
-   |
-LL -         (1 + 4)...1 * 2 => (),
-LL +         1 + 4...1 * 2 => (),
-   |
-
-error: expected a pattern range bound, found an expression
-  --> $DIR/pat-recover-ranges.rs:18:19
-   |
-LL |         (1 + 4)...1 * 2 => (),
-   |                   ^^^^^ arbitrary expressions are not allowed in patterns
-
-error: expected a pattern range bound, found a method call
-  --> $DIR/pat-recover-ranges.rs:24:9
-   |
-LL |         0.x()..="y".z() => (),
-   |         ^^^^^ method calls are not allowed in patterns
-
-error: expected a pattern range bound, found a method call
-  --> $DIR/pat-recover-ranges.rs:24:17
-   |
-LL |         0.x()..="y".z() => (),
-   |                 ^^^^^^^ method calls are not allowed in patterns
-
-warning: `...` range patterns are deprecated
-  --> $DIR/pat-recover-ranges.rs:18:16
-   |
-LL |         (1 + 4)...1 * 2 => (),
-   |                ^^^ help: use `..=` for an inclusive range
-   |
-   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
-   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
-   = note: `#[warn(ellipsis_inclusive_range_patterns)]` on by default
-
-error: aborting due to 13 previous errors; 1 warning emitted
-
diff --git a/tests/ui/parser/recover/recover-pat-exprs.rs b/tests/ui/parser/recover/recover-pat-exprs.rs
new file mode 100644
index 00000000000..e5e25df0c01
--- /dev/null
+++ b/tests/ui/parser/recover/recover-pat-exprs.rs
@@ -0,0 +1,106 @@
+// FieldExpression, TupleIndexingExpression
+fn field_access() {
+    match 0 {
+        x => (),
+        x.y => (), //~ error: expected a pattern, found an expression
+        x.0 => (), //~ error: expected a pattern, found an expression
+        x._0 => (), //~ error: expected a pattern, found an expression
+        x.0.1 => (), //~ error: expected a pattern, found an expression
+        x.4.y.17.__z => (), //~ error: expected a pattern, found an expression
+    }
+
+    { let x.0e0; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
+    { let x.-0.0; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
+    { let x.-0; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
+
+    { let x.0u32; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
+    { let x.0.0_f64; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
+}
+
+// IndexExpression, ArrayExpression
+fn array_indexing() {
+    match 0 {
+        x[0] => (), //~ error: expected a pattern, found an expression
+        x[..] => (), //~ error: expected a pattern, found an expression
+    }
+
+    { let x[0, 1, 2]; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
+    { let x[0; 20]; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
+    { let x[]; } //~ error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
+    { let (x[]); } //~ error: expected one of `)`, `,`, `@`, or `|`, found `[`
+    //~^ missing `,`
+}
+
+// MethodCallExpression, CallExpression, ErrorPropagationExpression
+fn method_call() {
+    match 0 {
+        x.f() => (), //~ error: expected a pattern, found an expression
+        x._f() => (), //~ error: expected a pattern, found an expression
+        x? => (), //~ error: expected a pattern, found an expression
+        ().f() => (), //~ error: expected a pattern, found an expression
+        (0, x)?.f() => (), //~ error: expected a pattern, found an expression
+        x.f().g() => (), //~ error: expected a pattern, found an expression
+        0.f()?.g()?? => (), //~ error: expected a pattern, found an expression
+    }
+}
+
+// TypeCastExpression
+fn type_cast() {
+    match 0 {
+        x as usize => (), //~ error: expected a pattern, found an expression
+        0 as usize => (), //~ error: expected a pattern, found an expression
+        x.f().0.4 as f32 => (), //~ error: expected a pattern, found an expression
+    }
+}
+
+// ArithmeticOrLogicalExpression, also check if parentheses are added as needed
+fn operator() {
+    match 0 {
+        1 + 1 => (), //~ error: expected a pattern, found an expression
+        (1 + 2) * 3 => (),
+        //~^ error: expected a pattern, found an expression
+        //~| error: expected a pattern, found an expression
+        x.0 > 2 => (), //~ error: expected a pattern, found an expression
+        x.0 == 2 => (), //~ error: expected a pattern, found an expression
+    }
+
+    // preexisting match arm guard
+    match (0, 0) {
+        (x, y.0 > 2) if x != 0 => (), //~ error: expected a pattern, found an expression
+        (x, y.0 > 2) if x != 0 || x != 1 => (), //~ error: expected a pattern, found an expression
+    }
+}
+
+const _: u32 = match 12 {
+    1 + 2 * PI.cos() => 2, //~ error: expected a pattern, found an expression
+    _ => 0,
+};
+
+fn main() {
+    match u8::MAX {
+        u8::MAX.abs() => (),
+        //~^ error: expected a pattern, found an expression
+        x.sqrt() @ .. => (),
+        //~^ error: expected a pattern, found an expression
+        //~| error: left-hand side of `@` must be a binding
+        z @ w @ v.u() => (),
+        //~^ error: expected a pattern, found an expression
+        y.ilog(3) => (),
+        //~^ error: expected a pattern, found an expression
+        n + 1 => (),
+        //~^ error: expected a pattern, found an expression
+        ("".f() + 14 * 8) => (),
+        //~^ error: expected a pattern, found an expression
+        0 | ((1) | 2) | 3 => (),
+        f?() => (),
+        //~^ error: expected a pattern, found an expression
+        (_ + 1) => (),
+        //~^ error: expected one of `)`, `,`, or `|`, found `+`
+    }
+
+    let 1 + 1 = 2;
+    //~^ error: expected a pattern, found an expression
+
+    let b = matches!(x, (x * x | x.f()) | x[0]);
+    //~^ error: expected one of `)`, `,`, `@`, or `|`, found `*`
+}
diff --git a/tests/ui/parser/recover/recover-pat-exprs.stderr b/tests/ui/parser/recover/recover-pat-exprs.stderr
new file mode 100644
index 00000000000..63956f35c07
--- /dev/null
+++ b/tests/ui/parser/recover/recover-pat-exprs.stderr
@@ -0,0 +1,772 @@
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:5:9
+   |
+LL |         x.y => (),
+   |         ^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == x.y => (),
+   |         ~~~ +++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = x.y;
+LL ~     match 0 {
+LL |         x => (),
+LL ~         VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { x.y } => (),
+   |         +++++++     +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:6:9
+   |
+LL |         x.0 => (),
+   |         ^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == x.0 => (),
+   |         ~~~ +++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = x.0;
+LL ~     match 0 {
+LL |         x => (),
+LL |         x.y => (),
+LL ~         VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { x.0 } => (),
+   |         +++++++     +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:7:9
+   |
+LL |         x._0 => (),
+   |         ^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == x._0 => (),
+   |         ~~~ ++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = x._0;
+LL ~     match 0 {
+LL |         x => (),
+LL |         x.y => (),
+LL |         x.0 => (),
+LL ~         VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { x._0 } => (),
+   |         +++++++      +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:8:9
+   |
+LL |         x.0.1 => (),
+   |         ^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == x.0.1 => (),
+   |         ~~~ +++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = x.0.1;
+LL ~     match 0 {
+LL |         x => (),
+...
+LL |         x._0 => (),
+LL ~         VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { x.0.1 } => (),
+   |         +++++++       +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:9:9
+   |
+LL |         x.4.y.17.__z => (),
+   |         ^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == x.4.y.17.__z => (),
+   |         ~~~ ++++++++++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = x.4.y.17.__z;
+LL ~     match 0 {
+LL |         x => (),
+...
+LL |         x.0.1 => (),
+LL ~         VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { x.4.y.17.__z } => (),
+   |         +++++++              +
+
+error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
+  --> $DIR/recover-pat-exprs.rs:12:12
+   |
+LL |     { let x.0e0; }
+   |            ^ expected one of `:`, `;`, `=`, `@`, or `|`
+
+error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
+  --> $DIR/recover-pat-exprs.rs:13:12
+   |
+LL |     { let x.-0.0; }
+   |            ^ expected one of `:`, `;`, `=`, `@`, or `|`
+
+error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
+  --> $DIR/recover-pat-exprs.rs:14:12
+   |
+LL |     { let x.-0; }
+   |            ^ expected one of `:`, `;`, `=`, `@`, or `|`
+
+error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
+  --> $DIR/recover-pat-exprs.rs:16:12
+   |
+LL |     { let x.0u32; }
+   |            ^ expected one of `:`, `;`, `=`, `@`, or `|`
+
+error: expected one of `:`, `;`, `=`, `@`, or `|`, found `.`
+  --> $DIR/recover-pat-exprs.rs:17:12
+   |
+LL |     { let x.0.0_f64; }
+   |            ^ expected one of `:`, `;`, `=`, `@`, or `|`
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:23:9
+   |
+LL |         x[0] => (),
+   |         ^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == x[0] => (),
+   |         ~~~ ++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = x[0];
+LL ~     match 0 {
+LL ~         VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { x[0] } => (),
+   |         +++++++      +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:24:9
+   |
+LL |         x[..] => (),
+   |         ^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == x[..] => (),
+   |         ~~~ +++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = x[..];
+LL ~     match 0 {
+LL |         x[0] => (),
+LL ~         VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { x[..] } => (),
+   |         +++++++       +
+
+error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
+  --> $DIR/recover-pat-exprs.rs:27:12
+   |
+LL |     { let x[0, 1, 2]; }
+   |            ^ expected one of `:`, `;`, `=`, `@`, or `|`
+
+error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
+  --> $DIR/recover-pat-exprs.rs:28:12
+   |
+LL |     { let x[0; 20]; }
+   |            ^ expected one of `:`, `;`, `=`, `@`, or `|`
+
+error: expected one of `:`, `;`, `=`, `@`, or `|`, found `[`
+  --> $DIR/recover-pat-exprs.rs:29:12
+   |
+LL |     { let x[]; }
+   |            ^ expected one of `:`, `;`, `=`, `@`, or `|`
+
+error: expected one of `)`, `,`, `@`, or `|`, found `[`
+  --> $DIR/recover-pat-exprs.rs:30:13
+   |
+LL |     { let (x[]); }
+   |             ^
+   |             |
+   |             expected one of `)`, `,`, `@`, or `|`
+   |             help: missing `,`
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:37:9
+   |
+LL |         x.f() => (),
+   |         ^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == x.f() => (),
+   |         ~~~ +++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = x.f();
+LL ~     match 0 {
+LL ~         VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { x.f() } => (),
+   |         +++++++       +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:38:9
+   |
+LL |         x._f() => (),
+   |         ^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == x._f() => (),
+   |         ~~~ ++++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = x._f();
+LL ~     match 0 {
+LL |         x.f() => (),
+LL ~         VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { x._f() } => (),
+   |         +++++++        +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:39:9
+   |
+LL |         x? => (),
+   |         ^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == x? => (),
+   |         ~~~ ++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = x?;
+LL ~     match 0 {
+LL |         x.f() => (),
+LL |         x._f() => (),
+LL ~         VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { x? } => (),
+   |         +++++++    +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:40:9
+   |
+LL |         ().f() => (),
+   |         ^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == ().f() => (),
+   |         ~~~ ++++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = ().f();
+LL ~     match 0 {
+LL |         x.f() => (),
+LL |         x._f() => (),
+LL |         x? => (),
+LL ~         VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { ().f() } => (),
+   |         +++++++        +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:41:9
+   |
+LL |         (0, x)?.f() => (),
+   |         ^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == (0, x)?.f() => (),
+   |         ~~~ +++++++++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = (0, x)?.f();
+LL ~     match 0 {
+LL |         x.f() => (),
+...
+LL |         ().f() => (),
+LL ~         VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { (0, x)?.f() } => (),
+   |         +++++++             +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:42:9
+   |
+LL |         x.f().g() => (),
+   |         ^^^^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == x.f().g() => (),
+   |         ~~~ +++++++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = x.f().g();
+LL ~     match 0 {
+LL |         x.f() => (),
+...
+LL |         (0, x)?.f() => (),
+LL ~         VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { x.f().g() } => (),
+   |         +++++++           +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:43:9
+   |
+LL |         0.f()?.g()?? => (),
+   |         ^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == 0.f()?.g()?? => (),
+   |         ~~~ ++++++++++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = 0.f()?.g()??;
+LL ~     match 0 {
+LL |         x.f() => (),
+...
+LL |         x.f().g() => (),
+LL ~         VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { 0.f()?.g()?? } => (),
+   |         +++++++              +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:50:9
+   |
+LL |         x as usize => (),
+   |         ^^^^^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == x as usize => (),
+   |         ~~~ ++++++++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = x as usize;
+LL ~     match 0 {
+LL ~         VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { x as usize } => (),
+   |         +++++++            +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:51:9
+   |
+LL |         0 as usize => (),
+   |         ^^^^^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == 0 as usize => (),
+   |         ~~~ ++++++++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = 0 as usize;
+LL ~     match 0 {
+LL |         x as usize => (),
+LL ~         VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { 0 as usize } => (),
+   |         +++++++            +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:52:9
+   |
+LL |         x.f().0.4 as f32 => (),
+   |         ^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == x.f().0.4 as f32 => (),
+   |         ~~~ ++++++++++++++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = x.f().0.4 as f32;
+LL ~     match 0 {
+LL |         x as usize => (),
+LL |         0 as usize => (),
+LL ~         VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { x.f().0.4 as f32 } => (),
+   |         +++++++                  +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:59:9
+   |
+LL |         1 + 1 => (),
+   |         ^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == 1 + 1 => (),
+   |         ~~~ +++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = 1 + 1;
+LL ~     match 0 {
+LL ~         VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { 1 + 1 } => (),
+   |         +++++++       +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:60:9
+   |
+LL |         (1 + 2) * 3 => (),
+   |         ^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == (1 + 2) * 3 => (),
+   |         ~~~ +++++++++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = (1 + 2) * 3;
+LL ~     match 0 {
+LL |         1 + 1 => (),
+LL ~         VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { (1 + 2) * 3 } => (),
+   |         +++++++             +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:63:9
+   |
+LL |         x.0 > 2 => (),
+   |         ^^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == (x.0 > 2) => (),
+   |         ~~~ +++++++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = x.0 > 2;
+LL ~     match 0 {
+LL |         1 + 1 => (),
+...
+LL |
+LL ~         VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { x.0 > 2 } => (),
+   |         +++++++         +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:64:9
+   |
+LL |         x.0 == 2 => (),
+   |         ^^^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == (x.0 == 2) => (),
+   |         ~~~ ++++++++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = x.0 == 2;
+LL ~     match 0 {
+LL |         1 + 1 => (),
+...
+LL |         x.0 > 2 => (),
+LL ~         VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { x.0 == 2 } => (),
+   |         +++++++          +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:69:13
+   |
+LL |         (x, y.0 > 2) if x != 0 => (),
+   |             ^^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to the match arm guard
+   |
+LL |         (x, val) if x != 0 && val == (y.0 > 2) => (),
+   |             ~~~            +++++++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = y.0 > 2;
+LL ~     match (0, 0) {
+LL ~         (x, VAL) if x != 0 => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         (x, const { y.0 > 2 }) if x != 0 => (),
+   |             +++++++         +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:70:13
+   |
+LL |         (x, y.0 > 2) if x != 0 || x != 1 => (),
+   |             ^^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to the match arm guard
+   |
+LL |         (x, val) if (x != 0 || x != 1) && val == (y.0 > 2) => (),
+   |             ~~~     +                +++++++++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = y.0 > 2;
+LL ~     match (0, 0) {
+LL |         (x, y.0 > 2) if x != 0 => (),
+LL ~         (x, VAL) if x != 0 || x != 1 => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         (x, const { y.0 > 2 }) if x != 0 || x != 1 => (),
+   |             +++++++         +
+
+error: left-hand side of `@` must be a binding
+  --> $DIR/recover-pat-exprs.rs:83:9
+   |
+LL |         x.sqrt() @ .. => (),
+   |         --------^^^--
+   |         |          |
+   |         |          also a pattern
+   |         interpreted as a pattern, not a binding
+   |
+   = note: bindings are `x`, `mut x`, `ref x`, and `ref mut x`
+
+error: expected one of `)`, `,`, or `|`, found `+`
+  --> $DIR/recover-pat-exprs.rs:97:12
+   |
+LL |         (_ + 1) => (),
+   |            ^ expected one of `)`, `,`, or `|`
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:81:9
+   |
+LL |         u8::MAX.abs() => (),
+   |         ^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == u8::MAX.abs() => (),
+   |         ~~~ +++++++++++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = u8::MAX.abs();
+LL ~     match u8::MAX {
+LL ~         VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { u8::MAX.abs() } => (),
+   |         +++++++               +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:86:17
+   |
+LL |         z @ w @ v.u() => (),
+   |                 ^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         z @ w @ val if val == v.u() => (),
+   |                 ~~~ +++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = v.u();
+LL ~     match u8::MAX {
+LL |         u8::MAX.abs() => (),
+...
+LL |
+LL ~         z @ w @ VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         z @ w @ const { v.u() } => (),
+   |                 +++++++       +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:88:9
+   |
+LL |         y.ilog(3) => (),
+   |         ^^^^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == y.ilog(3) => (),
+   |         ~~~ +++++++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = y.ilog(3);
+LL ~     match u8::MAX {
+LL |         u8::MAX.abs() => (),
+...
+LL |
+LL ~         VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { y.ilog(3) } => (),
+   |         +++++++           +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:90:9
+   |
+LL |         n + 1 => (),
+   |         ^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == n + 1 => (),
+   |         ~~~ +++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = n + 1;
+LL ~     match u8::MAX {
+LL |         u8::MAX.abs() => (),
+...
+LL |
+LL ~         VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { n + 1 } => (),
+   |         +++++++       +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:92:10
+   |
+LL |         ("".f() + 14 * 8) => (),
+   |          ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         (val) if val == "".f() + 14 * 8 => (),
+   |          ~~~  +++++++++++++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = "".f() + 14 * 8;
+LL ~     match u8::MAX {
+LL |         u8::MAX.abs() => (),
+...
+LL |
+LL ~         (VAL) => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         (const { "".f() + 14 * 8 }) => (),
+   |          +++++++                 +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:95:9
+   |
+LL |         f?() => (),
+   |         ^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         val if val == f?() => (),
+   |         ~~~ ++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = f?();
+LL ~     match u8::MAX {
+LL |         u8::MAX.abs() => (),
+...
+LL |         0 | ((1) | 2) | 3 => (),
+LL ~         VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { f?() } => (),
+   |         +++++++      +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:101:9
+   |
+LL |     let 1 + 1 = 2;
+   |         ^^^^^ arbitrary expressions are not allowed in patterns
+
+error: expected one of `)`, `,`, `@`, or `|`, found `*`
+  --> $DIR/recover-pat-exprs.rs:104:28
+   |
+LL |     let b = matches!(x, (x * x | x.f()) | x[0]);
+   |                            ^ expected one of `)`, `,`, `@`, or `|`
+  --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
+   |
+   = note: while parsing argument for this `pat` macro fragment
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:60:10
+   |
+LL |         (1 + 2) * 3 => (),
+   |          ^^^^^ arbitrary expressions are not allowed in patterns
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:75:5
+   |
+LL |     1 + 2 * PI.cos() => 2,
+   |     ^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-exprs.rs:83:9
+   |
+LL |         x.sqrt() @ .. => (),
+   |         ^^^^^^^^ arbitrary expressions are not allowed in patterns
+
+error: aborting due to 45 previous errors
+
diff --git a/tests/ui/parser/recover/recover-pat-issues.rs b/tests/ui/parser/recover/recover-pat-issues.rs
new file mode 100644
index 00000000000..5b900fe80e5
--- /dev/null
+++ b/tests/ui/parser/recover/recover-pat-issues.rs
@@ -0,0 +1,46 @@
+struct Foo(String);
+struct Bar { baz: String }
+
+fn foo(foo: Foo) -> bool {
+    match foo {
+        Foo("hi".to_owned()) => true,
+        //~^ error: expected a pattern, found an expression
+        _ => false
+    }
+}
+
+fn bar(bar: Bar) -> bool {
+    match bar {
+        Bar { baz: "hi".to_owned() } => true,
+        //~^ error: expected a pattern, found an expression
+        _ => false
+    }
+}
+
+/// Issue #90121
+fn baz() {
+    let foo = vec!["foo".to_string()];
+
+    match foo.as_slice() {
+        &["foo".to_string()] => {}
+        //~^ error: expected a pattern, found an expression
+        _ => {}
+    };
+}
+
+/// Issue #104996
+fn qux() {
+    struct Magic(pub u16);
+    const MAGIC: Magic = Magic(42);
+
+    if let Some(MAGIC.0 as usize) = None::<usize> {}
+    //~^ error: expected a pattern, found an expression
+}
+
+fn main() {
+    if let (-1.some(4)) = (0, Some(4)) {}
+    //~^ error: expected a pattern, found an expression
+
+    if let (-1.Some(4)) = (0, Some(4)) {}
+    //~^ error: expected a pattern, found an expression
+}
diff --git a/tests/ui/parser/recover/recover-pat-issues.stderr b/tests/ui/parser/recover/recover-pat-issues.stderr
new file mode 100644
index 00000000000..596bff21395
--- /dev/null
+++ b/tests/ui/parser/recover/recover-pat-issues.stderr
@@ -0,0 +1,113 @@
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-issues.rs:6:13
+   |
+LL |         Foo("hi".to_owned()) => true,
+   |             ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         Foo(val) if val == "hi".to_owned() => true,
+   |             ~~~  +++++++++++++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = "hi".to_owned();
+LL ~     match foo {
+LL ~         Foo(VAL) => true,
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         Foo(const { "hi".to_owned() }) => true,
+   |             +++++++                 +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-issues.rs:14:20
+   |
+LL |         Bar { baz: "hi".to_owned() } => true,
+   |                    ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         Bar { baz } if baz == "hi".to_owned() => true,
+   |               ~~~   +++++++++++++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const BAZ: /* Type */ = "hi".to_owned();
+LL ~     match bar {
+LL ~         Bar { baz: BAZ } => true,
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         Bar { baz: const { "hi".to_owned() } } => true,
+   |                    +++++++                 +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-issues.rs:25:11
+   |
+LL |         &["foo".to_string()] => {}
+   |           ^^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider moving the expression to a match arm guard
+   |
+LL |         &[val] if val == "foo".to_string() => {}
+   |           ~~~  +++++++++++++++++++++++++++
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = "foo".to_string();
+LL ~     match foo.as_slice() {
+LL ~         &[VAL] => {}
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         &[const { "foo".to_string() }] => {}
+   |           +++++++                   +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-issues.rs:36:17
+   |
+LL |     if let Some(MAGIC.0 as usize) = None::<usize> {}
+   |                 ^^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = MAGIC.0 as usize;
+LL ~     if let Some(VAL) = None::<usize> {}
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |     if let Some(const { MAGIC.0 as usize }) = None::<usize> {}
+   |                 +++++++                  +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-issues.rs:41:13
+   |
+LL |     if let (-1.some(4)) = (0, Some(4)) {}
+   |             ^^^^^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = -1.some(4);
+LL ~     if let (VAL) = (0, Some(4)) {}
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |     if let (const { -1.some(4) }) = (0, Some(4)) {}
+   |             +++++++            +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-issues.rs:44:13
+   |
+LL |     if let (-1.Some(4)) = (0, Some(4)) {}
+   |             ^^^^^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = -1.Some(4);
+LL ~     if let (VAL) = (0, Some(4)) {}
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |     if let (const { -1.Some(4) }) = (0, Some(4)) {}
+   |             +++++++            +
+
+error: aborting due to 6 previous errors
+
diff --git a/tests/ui/parser/recover/recover-pat-lets.rs b/tests/ui/parser/recover/recover-pat-lets.rs
new file mode 100644
index 00000000000..6681cc25db3
--- /dev/null
+++ b/tests/ui/parser/recover/recover-pat-lets.rs
@@ -0,0 +1,20 @@
+fn main() {
+    let x = Some(2);
+
+    let x.expect("foo");
+    //~^ error: expected a pattern, found an expression
+
+    let x.unwrap(): u32;
+    //~^ error: expected a pattern, found an expression
+
+    let x[0] = 1;
+    //~^ error: expected a pattern, found an expression
+
+    let Some(1 + 1) = x else { //~ error: expected a pattern, found an expression
+        return;
+    };
+
+    if let Some(1 + 1) = x { //~ error: expected a pattern, found an expression
+        return;
+    }
+}
diff --git a/tests/ui/parser/recover/recover-pat-lets.stderr b/tests/ui/parser/recover/recover-pat-lets.stderr
new file mode 100644
index 00000000000..e54586b0924
--- /dev/null
+++ b/tests/ui/parser/recover/recover-pat-lets.stderr
@@ -0,0 +1,52 @@
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-lets.rs:4:9
+   |
+LL |     let x.expect("foo");
+   |         ^^^^^^^^^^^^^^^ arbitrary expressions are not allowed in patterns
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-lets.rs:7:9
+   |
+LL |     let x.unwrap(): u32;
+   |         ^^^^^^^^^^ arbitrary expressions are not allowed in patterns
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-lets.rs:10:9
+   |
+LL |     let x[0] = 1;
+   |         ^^^^ arbitrary expressions are not allowed in patterns
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-lets.rs:13:14
+   |
+LL |     let Some(1 + 1) = x else {
+   |              ^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = 1 + 1;
+LL ~     let Some(VAL) = x else {
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |     let Some(const { 1 + 1 }) = x else {
+   |              +++++++       +
+
+error: expected a pattern, found an expression
+  --> $DIR/recover-pat-lets.rs:17:17
+   |
+LL |     if let Some(1 + 1) = x {
+   |                 ^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = 1 + 1;
+LL ~     if let Some(VAL) = x {
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |     if let Some(const { 1 + 1 }) = x {
+   |                 +++++++       +
+
+error: aborting due to 5 previous errors
+
diff --git a/tests/ui/parser/pat-recover-ranges.rs b/tests/ui/parser/recover/recover-pat-ranges.rs
index 7d77e950d90..e3f061c625d 100644
--- a/tests/ui/parser/pat-recover-ranges.rs
+++ b/tests/ui/parser/recover/recover-pat-ranges.rs
@@ -22,8 +22,8 @@ fn main() {
         //~| warning: `...` range patterns are deprecated
         //~| warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
         0.x()..="y".z() => (),
-        //~^ error: expected a pattern range bound, found a method call
-        //~| error: expected a pattern range bound, found a method call
+        //~^ error: expected a pattern range bound, found an expression
+        //~| error: expected a pattern range bound, found an expression
     };
 }
 
diff --git a/tests/ui/parser/recover/recover-pat-ranges.stderr b/tests/ui/parser/recover/recover-pat-ranges.stderr
new file mode 100644
index 00000000000..088f83b0ccb
--- /dev/null
+++ b/tests/ui/parser/recover/recover-pat-ranges.stderr
@@ -0,0 +1,216 @@
+error: range pattern bounds cannot have parentheses
+  --> $DIR/recover-pat-ranges.rs:4:13
+   |
+LL |         0..=(1) => (),
+   |             ^ ^
+   |
+help: remove these parentheses
+   |
+LL -         0..=(1) => (),
+LL +         0..=1 => (),
+   |
+
+error: range pattern bounds cannot have parentheses
+  --> $DIR/recover-pat-ranges.rs:6:9
+   |
+LL |         (-12)..=4 => (),
+   |         ^   ^
+   |
+help: remove these parentheses
+   |
+LL -         (-12)..=4 => (),
+LL +         -12..=4 => (),
+   |
+
+error: range pattern bounds cannot have parentheses
+  --> $DIR/recover-pat-ranges.rs:8:9
+   |
+LL |         (0)..=(-4) => (),
+   |         ^ ^
+   |
+help: remove these parentheses
+   |
+LL -         (0)..=(-4) => (),
+LL +         0..=(-4) => (),
+   |
+
+error: range pattern bounds cannot have parentheses
+  --> $DIR/recover-pat-ranges.rs:8:15
+   |
+LL |         (0)..=(-4) => (),
+   |               ^  ^
+   |
+help: remove these parentheses
+   |
+LL -         (0)..=(-4) => (),
+LL +         (0)..=-4 => (),
+   |
+
+error: range pattern bounds cannot have parentheses
+  --> $DIR/recover-pat-ranges.rs:13:9
+   |
+LL |         (4).. => (),
+   |         ^ ^
+   |
+help: remove these parentheses
+   |
+LL -         (4).. => (),
+LL +         4.. => (),
+   |
+
+error: range pattern bounds cannot have parentheses
+  --> $DIR/recover-pat-ranges.rs:15:9
+   |
+LL |         (-4 + 0).. => (),
+   |         ^      ^
+   |
+help: remove these parentheses
+   |
+LL -         (-4 + 0).. => (),
+LL +         -4 + 0.. => (),
+   |
+
+error: range pattern bounds cannot have parentheses
+  --> $DIR/recover-pat-ranges.rs:18:9
+   |
+LL |         (1 + 4)...1 * 2 => (),
+   |         ^     ^
+   |
+help: remove these parentheses
+   |
+LL -         (1 + 4)...1 * 2 => (),
+LL +         1 + 4...1 * 2 => (),
+   |
+
+error: expected a pattern range bound, found an expression
+  --> $DIR/recover-pat-ranges.rs:11:12
+   |
+LL |         ..=1 + 2 => (),
+   |            ^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = 1 + 2;
+LL ~     match -1 {
+LL |         0..=1 => (),
+...
+LL |
+LL ~         ..=VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         ..=const { 1 + 2 } => (),
+   |            +++++++       +
+
+error: expected a pattern range bound, found an expression
+  --> $DIR/recover-pat-ranges.rs:15:10
+   |
+LL |         (-4 + 0).. => (),
+   |          ^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = -4 + 0;
+LL ~     match -1 {
+LL |         0..=1 => (),
+...
+LL |
+LL ~         (VAL).. => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         (const { -4 + 0 }).. => (),
+   |          +++++++        +
+
+error: expected a pattern range bound, found an expression
+  --> $DIR/recover-pat-ranges.rs:18:10
+   |
+LL |         (1 + 4)...1 * 2 => (),
+   |          ^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = 1 + 4;
+LL ~     match -1 {
+LL |         0..=1 => (),
+...
+LL |
+LL ~         (VAL)...1 * 2 => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         (const { 1 + 4 })...1 * 2 => (),
+   |          +++++++       +
+
+error: expected a pattern range bound, found an expression
+  --> $DIR/recover-pat-ranges.rs:18:19
+   |
+LL |         (1 + 4)...1 * 2 => (),
+   |                   ^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = 1 * 2;
+LL ~     match -1 {
+LL |         0..=1 => (),
+...
+LL |
+LL ~         (1 + 4)...VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         (1 + 4)...const { 1 * 2 } => (),
+   |                   +++++++       +
+
+error: expected a pattern range bound, found an expression
+  --> $DIR/recover-pat-ranges.rs:24:9
+   |
+LL |         0.x()..="y".z() => (),
+   |         ^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = 0.x();
+LL ~     match -1 {
+LL |         0..=1 => (),
+...
+LL |
+LL ~         VAL..="y".z() => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         const { 0.x() }..="y".z() => (),
+   |         +++++++       +
+
+error: expected a pattern range bound, found an expression
+  --> $DIR/recover-pat-ranges.rs:24:17
+   |
+LL |         0.x()..="y".z() => (),
+   |                 ^^^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = "y".z();
+LL ~     match -1 {
+LL |         0..=1 => (),
+...
+LL |
+LL ~         0.x()..=VAL => (),
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         0.x()..=const { "y".z() } => (),
+   |                 +++++++         +
+
+warning: `...` range patterns are deprecated
+  --> $DIR/recover-pat-ranges.rs:18:16
+   |
+LL |         (1 + 4)...1 * 2 => (),
+   |                ^^^ help: use `..=` for an inclusive range
+   |
+   = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2021/warnings-promoted-to-error.html>
+   = note: `#[warn(ellipsis_inclusive_range_patterns)]` on by default
+
+error: aborting due to 13 previous errors; 1 warning emitted
+
diff --git a/tests/ui/parser/pat-recover-wildcards.rs b/tests/ui/parser/recover/recover-pat-wildcards.rs
index f506e2223d6..f506e2223d6 100644
--- a/tests/ui/parser/pat-recover-wildcards.rs
+++ b/tests/ui/parser/recover/recover-pat-wildcards.rs
diff --git a/tests/ui/parser/pat-recover-wildcards.stderr b/tests/ui/parser/recover/recover-pat-wildcards.stderr
index e36ff237bb0..30307726a97 100644
--- a/tests/ui/parser/pat-recover-wildcards.stderr
+++ b/tests/ui/parser/recover/recover-pat-wildcards.stderr
@@ -1,35 +1,35 @@
 error: expected one of `=>`, `if`, or `|`, found `+`
-  --> $DIR/pat-recover-wildcards.rs:5:11
+  --> $DIR/recover-pat-wildcards.rs:5:11
    |
 LL |         _ + 1 => ()
    |           ^ expected one of `=>`, `if`, or `|`
 
 error: expected one of `)`, `,`, or `|`, found `%`
-  --> $DIR/pat-recover-wildcards.rs:11:12
+  --> $DIR/recover-pat-wildcards.rs:11:12
    |
 LL |         (_ % 4) => ()
    |            ^ expected one of `)`, `,`, or `|`
 
 error: expected one of `=>`, `if`, or `|`, found `.`
-  --> $DIR/pat-recover-wildcards.rs:17:10
+  --> $DIR/recover-pat-wildcards.rs:17:10
    |
 LL |         _.x() => ()
    |          ^ expected one of `=>`, `if`, or `|`
 
 error: expected one of `=>`, `if`, or `|`, found `..=`
-  --> $DIR/pat-recover-wildcards.rs:23:10
+  --> $DIR/recover-pat-wildcards.rs:23:10
    |
 LL |         _..=4 => ()
    |          ^^^ expected one of `=>`, `if`, or `|`
 
 error: expected one of `=>`, `if`, or `|`, found reserved identifier `_`
-  --> $DIR/pat-recover-wildcards.rs:29:11
+  --> $DIR/recover-pat-wildcards.rs:29:11
    |
 LL |         .._ => ()
    |           ^ expected one of `=>`, `if`, or `|`
 
 error[E0586]: inclusive range with no end
-  --> $DIR/pat-recover-wildcards.rs:35:10
+  --> $DIR/recover-pat-wildcards.rs:35:10
    |
 LL |         0..._ => ()
    |          ^^^
@@ -42,31 +42,25 @@ LL +         0.._ => ()
    |
 
 error: expected one of `=>`, `if`, or `|`, found reserved identifier `_`
-  --> $DIR/pat-recover-wildcards.rs:35:13
+  --> $DIR/recover-pat-wildcards.rs:35:13
    |
 LL |         0..._ => ()
    |             ^ expected one of `=>`, `if`, or `|`
 
 error: expected one of `)`, `,`, or `|`, found `*`
-  --> $DIR/pat-recover-wildcards.rs:43:12
+  --> $DIR/recover-pat-wildcards.rs:43:12
    |
 LL |         (_ * 0)..5 => ()
    |            ^ expected one of `)`, `,`, or `|`
 
 error: expected one of `=>`, `if`, or `|`, found `(`
-  --> $DIR/pat-recover-wildcards.rs:49:11
+  --> $DIR/recover-pat-wildcards.rs:49:11
    |
 LL |         ..(_) => ()
    |           ^ expected one of `=>`, `if`, or `|`
 
-error: expected a pattern range bound, found an expression
-  --> $DIR/pat-recover-wildcards.rs:55:14
-   |
-LL |         4..=(2 + _) => ()
-   |              ^^^^^ arbitrary expressions are not allowed in patterns
-
 error: range pattern bounds cannot have parentheses
-  --> $DIR/pat-recover-wildcards.rs:55:13
+  --> $DIR/recover-pat-wildcards.rs:55:13
    |
 LL |         4..=(2 + _) => ()
    |             ^     ^
@@ -77,6 +71,23 @@ LL -         4..=(2 + _) => ()
 LL +         4..=2 + _ => ()
    |
 
+error: expected a pattern range bound, found an expression
+  --> $DIR/recover-pat-wildcards.rs:55:14
+   |
+LL |         4..=(2 + _) => ()
+   |              ^^^^^ arbitrary expressions are not allowed in patterns
+   |
+help: consider extracting the expression into a `const`
+   |
+LL +     const VAL: /* Type */ = 2 + _;
+LL ~     match 9 {
+LL ~         4..=(VAL) => ()
+   |
+help: consider wrapping the expression in an inline `const` (requires `#![feature(inline_const_pat)]`)
+   |
+LL |         4..=(const { 2 + _ }) => ()
+   |              +++++++       +
+
 error: aborting due to 11 previous errors
 
 For more information about this error, try `rustc --explain E0586`.
diff --git a/tests/ui/parser/triple-colon-delegation.fixed b/tests/ui/parser/triple-colon-delegation.fixed
new file mode 100644
index 00000000000..fbb614b57da
--- /dev/null
+++ b/tests/ui/parser/triple-colon-delegation.fixed
@@ -0,0 +1,44 @@
+//@ run-rustfix
+
+#![feature(fn_delegation)]
+#![allow(incomplete_features, unused)]
+
+trait Trait {
+    fn foo(&self) {}
+}
+
+struct F;
+impl Trait for F {}
+
+pub mod to_reuse {
+    pub fn bar() {}
+}
+
+mod fn_to_other {
+    use super::*;
+
+    reuse Trait::foo; //~ ERROR path separator must be a double colon
+    reuse to_reuse::bar; //~ ERROR path separator must be a double colon
+}
+
+impl Trait for u8 {}
+
+struct S(u8);
+
+mod to_import {
+    pub fn check(arg: &u8) -> &u8 { arg }
+}
+
+impl Trait for S {
+    reuse Trait::* { //~ ERROR path separator must be a double colon
+        use to_import::check;
+
+        let _arr = Some(self.0).map(|x| [x * 2; 3]);
+        check(&self.0)
+    }
+}
+
+fn main() {
+    let s = S(0);
+    s.foo();
+}
diff --git a/tests/ui/parser/triple-colon-delegation.rs b/tests/ui/parser/triple-colon-delegation.rs
new file mode 100644
index 00000000000..9fbaa4477ae
--- /dev/null
+++ b/tests/ui/parser/triple-colon-delegation.rs
@@ -0,0 +1,44 @@
+//@ run-rustfix
+
+#![feature(fn_delegation)]
+#![allow(incomplete_features, unused)]
+
+trait Trait {
+    fn foo(&self) {}
+}
+
+struct F;
+impl Trait for F {}
+
+pub mod to_reuse {
+    pub fn bar() {}
+}
+
+mod fn_to_other {
+    use super::*;
+
+    reuse Trait:::foo; //~ ERROR path separator must be a double colon
+    reuse to_reuse:::bar; //~ ERROR path separator must be a double colon
+}
+
+impl Trait for u8 {}
+
+struct S(u8);
+
+mod to_import {
+    pub fn check(arg: &u8) -> &u8 { arg }
+}
+
+impl Trait for S {
+    reuse Trait:::* { //~ ERROR path separator must be a double colon
+        use to_import::check;
+
+        let _arr = Some(self.0).map(|x| [x * 2; 3]);
+        check(&self.0)
+    }
+}
+
+fn main() {
+    let s = S(0);
+    s.foo();
+}
diff --git a/tests/ui/parser/triple-colon-delegation.stderr b/tests/ui/parser/triple-colon-delegation.stderr
new file mode 100644
index 00000000000..d748c7d92b5
--- /dev/null
+++ b/tests/ui/parser/triple-colon-delegation.stderr
@@ -0,0 +1,38 @@
+error: path separator must be a double colon
+  --> $DIR/triple-colon-delegation.rs:20:18
+   |
+LL |     reuse Trait:::foo;
+   |                  ^
+   |
+help: use a double colon instead
+   |
+LL -     reuse Trait:::foo;
+LL +     reuse Trait::foo;
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon-delegation.rs:21:21
+   |
+LL |     reuse to_reuse:::bar;
+   |                     ^
+   |
+help: use a double colon instead
+   |
+LL -     reuse to_reuse:::bar;
+LL +     reuse to_reuse::bar;
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon-delegation.rs:33:18
+   |
+LL |     reuse Trait:::* {
+   |                  ^
+   |
+help: use a double colon instead
+   |
+LL -     reuse Trait:::* {
+LL +     reuse Trait::* {
+   |
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/parser/triple-colon.fixed b/tests/ui/parser/triple-colon.fixed
new file mode 100644
index 00000000000..168e4c1f618
--- /dev/null
+++ b/tests/ui/parser/triple-colon.fixed
@@ -0,0 +1,23 @@
+//@ run-rustfix
+
+#![allow(unused)]
+
+use ::std::{cell as _}; //~ ERROR path separator must be a double colon
+use std::cell::*; //~ ERROR path separator must be a double colon
+use std::cell::Cell; //~ ERROR path separator must be a double colon
+use std::{cell as _}; //~ ERROR path separator must be a double colon
+
+mod foo{
+    use ::{}; //~ ERROR path separator must be a double colon
+    use ::*; //~ ERROR path separator must be a double colon
+}
+
+fn main() {
+    let c: ::std::cell::Cell::<u8> = Cell::<u8>::new(0);
+    //~^ ERROR path separator must be a double colon
+    //~| ERROR path separator must be a double colon
+    //~| ERROR path separator must be a double colon
+    //~| ERROR path separator must be a double colon
+    //~| ERROR path separator must be a double colon
+    //~| ERROR path separator must be a double colon
+}
diff --git a/tests/ui/parser/triple-colon.rs b/tests/ui/parser/triple-colon.rs
new file mode 100644
index 00000000000..1a70012685f
--- /dev/null
+++ b/tests/ui/parser/triple-colon.rs
@@ -0,0 +1,23 @@
+//@ run-rustfix
+
+#![allow(unused)]
+
+use :::std::{cell as _}; //~ ERROR path separator must be a double colon
+use std::cell:::*; //~ ERROR path separator must be a double colon
+use std::cell:::Cell; //~ ERROR path separator must be a double colon
+use std:::{cell as _}; //~ ERROR path separator must be a double colon
+
+mod foo{
+    use :::{}; //~ ERROR path separator must be a double colon
+    use :::*; //~ ERROR path separator must be a double colon
+}
+
+fn main() {
+    let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+    //~^ ERROR path separator must be a double colon
+    //~| ERROR path separator must be a double colon
+    //~| ERROR path separator must be a double colon
+    //~| ERROR path separator must be a double colon
+    //~| ERROR path separator must be a double colon
+    //~| ERROR path separator must be a double colon
+}
diff --git a/tests/ui/parser/triple-colon.stderr b/tests/ui/parser/triple-colon.stderr
new file mode 100644
index 00000000000..8d57fd7ebc9
--- /dev/null
+++ b/tests/ui/parser/triple-colon.stderr
@@ -0,0 +1,146 @@
+error: path separator must be a double colon
+  --> $DIR/triple-colon.rs:5:7
+   |
+LL | use :::std::{cell as _};
+   |       ^
+   |
+help: use a double colon instead
+   |
+LL - use :::std::{cell as _};
+LL + use ::std::{cell as _};
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon.rs:6:16
+   |
+LL | use std::cell:::*;
+   |                ^
+   |
+help: use a double colon instead
+   |
+LL - use std::cell:::*;
+LL + use std::cell::*;
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon.rs:7:16
+   |
+LL | use std::cell:::Cell;
+   |                ^
+   |
+help: use a double colon instead
+   |
+LL - use std::cell:::Cell;
+LL + use std::cell::Cell;
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon.rs:8:10
+   |
+LL | use std:::{cell as _};
+   |          ^
+   |
+help: use a double colon instead
+   |
+LL - use std:::{cell as _};
+LL + use std::{cell as _};
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon.rs:11:11
+   |
+LL |     use :::{};
+   |           ^
+   |
+help: use a double colon instead
+   |
+LL -     use :::{};
+LL +     use ::{};
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon.rs:12:11
+   |
+LL |     use :::*;
+   |           ^
+   |
+help: use a double colon instead
+   |
+LL -     use :::*;
+LL +     use ::*;
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon.rs:16:14
+   |
+LL |     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+   |              ^
+   |
+help: use a double colon instead
+   |
+LL -     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+LL +     let c: ::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon.rs:16:20
+   |
+LL |     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+   |                    ^
+   |
+help: use a double colon instead
+   |
+LL -     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+LL +     let c: :::std::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon.rs:16:27
+   |
+LL |     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+   |                           ^
+   |
+help: use a double colon instead
+   |
+LL -     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+LL +     let c: :::std:::cell::Cell:::<u8> = Cell:::<u8>:::new(0);
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon.rs:16:34
+   |
+LL |     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+   |                                  ^
+   |
+help: use a double colon instead
+   |
+LL -     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+LL +     let c: :::std:::cell:::Cell::<u8> = Cell:::<u8>:::new(0);
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon.rs:16:48
+   |
+LL |     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+   |                                                ^
+   |
+help: use a double colon instead
+   |
+LL -     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+LL +     let c: :::std:::cell:::Cell:::<u8> = Cell::<u8>:::new(0);
+   |
+
+error: path separator must be a double colon
+  --> $DIR/triple-colon.rs:16:55
+   |
+LL |     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+   |                                                       ^
+   |
+help: use a double colon instead
+   |
+LL -     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>:::new(0);
+LL +     let c: :::std:::cell:::Cell:::<u8> = Cell:::<u8>::new(0);
+   |
+
+error: aborting due to 12 previous errors
+
diff --git a/tests/ui/print-calling-conventions.stdout b/tests/ui/print-calling-conventions.stdout
index da67a57f420..4415b3c858e 100644
--- a/tests/ui/print-calling-conventions.stdout
+++ b/tests/ui/print-calling-conventions.stdout
@@ -1,5 +1,6 @@
 C
 C-cmse-nonsecure-call
+C-cmse-nonsecure-entry
 C-unwind
 Rust
 aapcs
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/never-pattern-is-a-read.rs b/tests/ui/rfcs/rfc-0000-never_patterns/never-pattern-is-a-read.rs
new file mode 100644
index 00000000000..a66c4464417
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/never-pattern-is-a-read.rs
@@ -0,0 +1,16 @@
+// Make sure we consider `!` to be a union read.
+
+#![feature(never_type, never_patterns)]
+//~^ WARN the feature `never_patterns` is incomplete
+
+union U {
+    a: !,
+    b: usize,
+}
+
+fn foo<T>(u: U) -> ! {
+    let U { a: ! } = u;
+    //~^ ERROR access to union field is unsafe
+}
+
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/never-pattern-is-a-read.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/never-pattern-is-a-read.stderr
new file mode 100644
index 00000000000..d7dc7a47e72
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/never-pattern-is-a-read.stderr
@@ -0,0 +1,20 @@
+warning: the feature `never_patterns` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/never-pattern-is-a-read.rs:3:24
+   |
+LL | #![feature(never_type, never_patterns)]
+   |                        ^^^^^^^^^^^^^^
+   |
+   = note: see issue #118155 <https://github.com/rust-lang/rust/issues/118155> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/never-pattern-is-a-read.rs:12:16
+   |
+LL |     let U { a: ! } = u;
+   |                ^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error: aborting due to 1 previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs
index 348bf839b69..ea3cbabf302 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.rs
@@ -39,7 +39,6 @@ impl const Foo for NonConstAdd {
 #[const_trait]
 trait Baz {
     type Qux: Add;
-    //~^ ERROR the trait bound
 }
 
 impl const Baz for NonConstAdd {
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr
index 405212b52c7..c20b53c210f 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/assoc-type.stderr
@@ -12,17 +12,5 @@ error: using `#![feature(effects)]` without enabling next trait solver globally
    = note: the next trait solver must be enabled globally for the effects feature to work correctly
    = help: use `-Znext-solver` to enable
 
-error[E0277]: the trait bound `Add::{synthetic#0}: Compat` is not satisfied
-  --> $DIR/assoc-type.rs:41:15
-   |
-LL |     type Qux: Add;
-   |               ^^^ the trait `Compat` is not implemented for `Add::{synthetic#0}`
-   |
-help: consider further restricting the associated type
-   |
-LL | trait Baz where Add::{synthetic#0}: Compat {
-   |           ++++++++++++++++++++++++++++++++
-
-error: aborting due to 2 previous errors; 1 warning emitted
+error: aborting due to 1 previous error; 1 warning emitted
 
-For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/self/where-for-self.rs b/tests/ui/self/where-for-self.rs
index 9b4e8325664..d31bb1f22c4 100644
--- a/tests/ui/self/where-for-self.rs
+++ b/tests/ui/self/where-for-self.rs
@@ -2,6 +2,8 @@
 // Test that we can quantify lifetimes outside a constraint (i.e., including
 // the self type) in a where clause.
 
+// FIXME(static_mut_refs): this could use an atomic
+#![allow(static_mut_refs)]
 
 static mut COUNT: u32 = 1;
 
diff --git a/tests/ui/simd/simd-bitmask-notpow2.rs b/tests/ui/simd/simd-bitmask-notpow2.rs
index ff43206a3fd..3499bf33ed5 100644
--- a/tests/ui/simd/simd-bitmask-notpow2.rs
+++ b/tests/ui/simd/simd-bitmask-notpow2.rs
@@ -1,7 +1,6 @@
 //@run-pass
-// SEGFAULTS on LLVM 17. This should be merged into `simd-bitmask` once we require LLVM 18.
-//@ min-llvm-version: 18
 // FIXME: broken codegen on big-endian (https://github.com/rust-lang/rust/issues/127205)
+// This should be merged into `simd-bitmask` once that's fixed.
 //@ ignore-endian-big
 #![feature(repr_simd, intrinsics)]
 
diff --git a/tests/ui/static/reference-to-mut-static-safe.e2021.stderr b/tests/ui/static/reference-to-mut-static-safe.e2021.stderr
deleted file mode 100644
index 9fdfc00dfcd..00000000000
--- a/tests/ui/static/reference-to-mut-static-safe.e2021.stderr
+++ /dev/null
@@ -1,26 +0,0 @@
-warning: creating a shared reference to mutable static is discouraged
-  --> $DIR/reference-to-mut-static-safe.rs:9:14
-   |
-LL |     let _x = &X;
-   |              ^^ shared 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 shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
-   = note: `#[warn(static_mut_refs)]` on by default
-help: use `addr_of!` instead to create a raw pointer
-   |
-LL |     let _x = addr_of!(X);
-   |              ~~~~~~~~~ +
-
-error[E0133]: use of mutable static is unsafe and requires unsafe function or block
-  --> $DIR/reference-to-mut-static-safe.rs:9:15
-   |
-LL |     let _x = &X;
-   |               ^ use of mutable static
-   |
-   = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
-
-error: aborting due to 1 previous error; 1 warning emitted
-
-For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/static/reference-to-mut-static-safe.e2024.stderr b/tests/ui/static/reference-to-mut-static-safe.e2024.stderr
deleted file mode 100644
index b3e0c84d1d8..00000000000
--- a/tests/ui/static/reference-to-mut-static-safe.e2024.stderr
+++ /dev/null
@@ -1,24 +0,0 @@
-error[E0796]: creating a shared reference to a mutable static
-  --> $DIR/reference-to-mut-static-safe.rs:9:14
-   |
-LL |     let _x = &X;
-   |              ^^ shared reference to mutable static
-   |
-   = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
-help: use `addr_of!` instead to create a raw pointer
-   |
-LL |     let _x = addr_of!(X);
-   |              ~~~~~~~~~ +
-
-error[E0133]: use of mutable static is unsafe and requires unsafe block
-  --> $DIR/reference-to-mut-static-safe.rs:9:15
-   |
-LL |     let _x = &X;
-   |               ^ use of mutable static
-   |
-   = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
-
-error: aborting due to 2 previous errors
-
-Some errors have detailed explanations: E0133, E0796.
-For more information about an error, try `rustc --explain E0133`.
diff --git a/tests/ui/static/reference-to-mut-static-safe.rs b/tests/ui/static/reference-to-mut-static-safe.rs
deleted file mode 100644
index 98afdadf4d2..00000000000
--- a/tests/ui/static/reference-to-mut-static-safe.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-//@ revisions: e2021 e2024
-
-//@ [e2021] edition:2021
-//@ [e2024] compile-flags: --edition 2024 -Z unstable-options
-
-fn main() {
-    static mut X: i32 = 1;
-
-    let _x = &X;
-    //[e2024]~^ creating a shared reference to a mutable static [E0796]
-    //~^^ use of mutable static is unsafe and requires unsafe
-    //[e2021]~^^^ shared reference to mutable static is discouraged [static_mut_refs]
-}
diff --git a/tests/ui/static/reference-to-mut-static-unsafe-fn.rs b/tests/ui/static/reference-to-mut-static-unsafe-fn.rs
deleted file mode 100644
index d63fd5460d8..00000000000
--- a/tests/ui/static/reference-to-mut-static-unsafe-fn.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-//@ compile-flags: --edition 2024 -Z unstable-options
-
-fn main() {}
-
-unsafe fn _foo() {
-    unsafe {
-        static mut X: i32 = 1;
-        static mut Y: i32 = 1;
-
-        let _y = &X;
-        //~^ ERROR creating a shared reference to a mutable static [E0796]
-
-        let ref _a = X;
-        //~^ ERROR creating a shared reference to a mutable static [E0796]
-
-        let ref mut _a = X;
-        //~^ ERROR creating a mutable reference to a mutable static [E0796]
-
-        let (_b, _c) = (&X, &mut Y);
-        //~^ ERROR creating a shared reference to a mutable static [E0796]
-        //~^^ ERROR creating a mutable reference to a mutable static [E0796]
-
-        foo(&X);
-        //~^ ERROR creating a shared reference to a mutable static [E0796]
-    }
-}
-
-fn foo<'a>(_x: &'a i32) {}
diff --git a/tests/ui/static/reference-to-mut-static-unsafe-fn.stderr b/tests/ui/static/reference-to-mut-static-unsafe-fn.stderr
deleted file mode 100644
index ca9cfbf7ac7..00000000000
--- a/tests/ui/static/reference-to-mut-static-unsafe-fn.stderr
+++ /dev/null
@@ -1,75 +0,0 @@
-error[E0796]: creating a shared reference to a mutable static
-  --> $DIR/reference-to-mut-static-unsafe-fn.rs:10:18
-   |
-LL |         let _y = &X;
-   |                  ^^ shared reference to mutable static
-   |
-   = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
-help: use `addr_of!` instead to create a raw pointer
-   |
-LL |         let _y = addr_of!(X);
-   |                  ~~~~~~~~~ +
-
-error[E0796]: creating a shared reference to a mutable static
-  --> $DIR/reference-to-mut-static-unsafe-fn.rs:13:22
-   |
-LL |         let ref _a = X;
-   |                      ^ shared reference to mutable static
-   |
-   = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
-help: use `addr_of!` instead to create a raw pointer
-   |
-LL |         let ref _a = addr_of!(X);
-   |                      +++++++++ +
-
-error[E0796]: creating a mutable reference to a mutable static
-  --> $DIR/reference-to-mut-static-unsafe-fn.rs:16:26
-   |
-LL |         let ref mut _a = X;
-   |                          ^ mutable reference to mutable static
-   |
-   = 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 |         let ref mut _a = addr_of_mut!(X);
-   |                          +++++++++++++ +
-
-error[E0796]: creating a shared reference to a mutable static
-  --> $DIR/reference-to-mut-static-unsafe-fn.rs:19:25
-   |
-LL |         let (_b, _c) = (&X, &mut Y);
-   |                         ^^ shared reference to mutable static
-   |
-   = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
-help: use `addr_of!` instead to create a raw pointer
-   |
-LL |         let (_b, _c) = (addr_of!(X), &mut Y);
-   |                         ~~~~~~~~~ +
-
-error[E0796]: creating a mutable reference to a mutable static
-  --> $DIR/reference-to-mut-static-unsafe-fn.rs:19:29
-   |
-LL |         let (_b, _c) = (&X, &mut Y);
-   |                             ^^^^^^ mutable reference to mutable static
-   |
-   = 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 |         let (_b, _c) = (&X, addr_of_mut!(Y));
-   |                             ~~~~~~~~~~~~~ +
-
-error[E0796]: creating a shared reference to a mutable static
-  --> $DIR/reference-to-mut-static-unsafe-fn.rs:23:13
-   |
-LL |         foo(&X);
-   |             ^^ shared reference to mutable static
-   |
-   = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
-help: use `addr_of!` instead to create a raw pointer
-   |
-LL |         foo(addr_of!(X));
-   |             ~~~~~~~~~ +
-
-error: aborting due to 6 previous errors
-
-For more information about this error, try `rustc --explain E0796`.
diff --git a/tests/ui/static/reference-to-mut-static.e2021.stderr b/tests/ui/static/reference-to-mut-static.e2021.stderr
deleted file mode 100644
index 667d7602f34..00000000000
--- a/tests/ui/static/reference-to-mut-static.e2021.stderr
+++ /dev/null
@@ -1,91 +0,0 @@
-error: creating a shared reference to mutable static is discouraged
-  --> $DIR/reference-to-mut-static.rs:16:18
-   |
-LL |         let _y = &X;
-   |                  ^^ shared 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 shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
-note: the lint level is defined here
-  --> $DIR/reference-to-mut-static.rs:6:9
-   |
-LL | #![deny(static_mut_refs)]
-   |         ^^^^^^^^^^^^^^^
-help: use `addr_of!` instead to create a raw pointer
-   |
-LL |         let _y = addr_of!(X);
-   |                  ~~~~~~~~~ +
-
-error: creating a mutable reference to mutable static is discouraged
-  --> $DIR/reference-to-mut-static.rs:20:18
-   |
-LL |         let _y = &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 |         let _y = addr_of_mut!(X);
-   |                  ~~~~~~~~~~~~~ +
-
-error: creating a shared reference to mutable static is discouraged
-  --> $DIR/reference-to-mut-static.rs:28:22
-   |
-LL |         let ref _a = X;
-   |                      ^ shared 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 shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
-help: use `addr_of!` instead to create a raw pointer
-   |
-LL |         let ref _a = addr_of!(X);
-   |                      +++++++++ +
-
-error: creating a shared reference to mutable static is discouraged
-  --> $DIR/reference-to-mut-static.rs:32:25
-   |
-LL |         let (_b, _c) = (&X, &Y);
-   |                         ^^ shared 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 shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
-help: use `addr_of!` instead to create a raw pointer
-   |
-LL |         let (_b, _c) = (addr_of!(X), &Y);
-   |                         ~~~~~~~~~ +
-
-error: creating a shared reference to mutable static is discouraged
-  --> $DIR/reference-to-mut-static.rs:32:29
-   |
-LL |         let (_b, _c) = (&X, &Y);
-   |                             ^^ shared 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 shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
-help: use `addr_of!` instead to create a raw pointer
-   |
-LL |         let (_b, _c) = (&X, addr_of!(Y));
-   |                             ~~~~~~~~~ +
-
-error: creating a shared reference to mutable static is discouraged
-  --> $DIR/reference-to-mut-static.rs:38:13
-   |
-LL |         foo(&X);
-   |             ^^ shared 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 shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
-help: use `addr_of!` instead to create a raw pointer
-   |
-LL |         foo(addr_of!(X));
-   |             ~~~~~~~~~ +
-
-error: aborting due to 6 previous errors
-
diff --git a/tests/ui/static/reference-to-mut-static.e2024.stderr b/tests/ui/static/reference-to-mut-static.e2024.stderr
deleted file mode 100644
index e77f4355466..00000000000
--- a/tests/ui/static/reference-to-mut-static.e2024.stderr
+++ /dev/null
@@ -1,75 +0,0 @@
-error[E0796]: creating a shared reference to a mutable static
-  --> $DIR/reference-to-mut-static.rs:16:18
-   |
-LL |         let _y = &X;
-   |                  ^^ shared reference to mutable static
-   |
-   = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
-help: use `addr_of!` instead to create a raw pointer
-   |
-LL |         let _y = addr_of!(X);
-   |                  ~~~~~~~~~ +
-
-error[E0796]: creating a mutable reference to a mutable static
-  --> $DIR/reference-to-mut-static.rs:20:18
-   |
-LL |         let _y = &mut X;
-   |                  ^^^^^^ mutable reference to mutable static
-   |
-   = 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 |         let _y = addr_of_mut!(X);
-   |                  ~~~~~~~~~~~~~ +
-
-error[E0796]: creating a shared reference to a mutable static
-  --> $DIR/reference-to-mut-static.rs:28:22
-   |
-LL |         let ref _a = X;
-   |                      ^ shared reference to mutable static
-   |
-   = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
-help: use `addr_of!` instead to create a raw pointer
-   |
-LL |         let ref _a = addr_of!(X);
-   |                      +++++++++ +
-
-error[E0796]: creating a shared reference to a mutable static
-  --> $DIR/reference-to-mut-static.rs:32:25
-   |
-LL |         let (_b, _c) = (&X, &Y);
-   |                         ^^ shared reference to mutable static
-   |
-   = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
-help: use `addr_of!` instead to create a raw pointer
-   |
-LL |         let (_b, _c) = (addr_of!(X), &Y);
-   |                         ~~~~~~~~~ +
-
-error[E0796]: creating a shared reference to a mutable static
-  --> $DIR/reference-to-mut-static.rs:32:29
-   |
-LL |         let (_b, _c) = (&X, &Y);
-   |                             ^^ shared reference to mutable static
-   |
-   = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
-help: use `addr_of!` instead to create a raw pointer
-   |
-LL |         let (_b, _c) = (&X, addr_of!(Y));
-   |                             ~~~~~~~~~ +
-
-error[E0796]: creating a shared reference to a mutable static
-  --> $DIR/reference-to-mut-static.rs:38:13
-   |
-LL |         foo(&X);
-   |             ^^ shared reference to mutable static
-   |
-   = note: this shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
-help: use `addr_of!` instead to create a raw pointer
-   |
-LL |         foo(addr_of!(X));
-   |             ~~~~~~~~~ +
-
-error: aborting due to 6 previous errors
-
-For more information about this error, try `rustc --explain E0796`.
diff --git a/tests/ui/static/reference-to-mut-static.rs b/tests/ui/static/reference-to-mut-static.rs
deleted file mode 100644
index af2cab7dd87..00000000000
--- a/tests/ui/static/reference-to-mut-static.rs
+++ /dev/null
@@ -1,50 +0,0 @@
-//@ revisions: e2021 e2024
-
-//@ [e2021] edition:2021
-//@ [e2024] compile-flags: --edition 2024 -Z unstable-options
-
-#![deny(static_mut_refs)]
-
-use std::ptr::{addr_of, addr_of_mut};
-
-fn main() {
-    static mut X: i32 = 1;
-
-    static mut Y: i32 = 1;
-
-    unsafe {
-        let _y = &X;
-        //[e2024]~^ ERROR creating a shared reference to a mutable static [E0796]
-        //[e2021]~^^ ERROR shared reference to mutable static is discouraged [static_mut_refs]
-
-        let _y = &mut X;
-        //[e2024]~^ ERROR creating a mutable reference to a mutable static [E0796]
-        //[e2021]~^^ ERROR mutable reference to mutable static is discouraged [static_mut_refs]
-
-        let _z = addr_of_mut!(X);
-
-        let _p = addr_of!(X);
-
-        let ref _a = X;
-        //[e2024]~^ ERROR creating a shared reference to a mutable static [E0796]
-        //[e2021]~^^ ERROR shared reference to mutable static is discouraged [static_mut_refs]
-
-        let (_b, _c) = (&X, &Y);
-        //[e2024]~^ ERROR creating a shared reference to a mutable static [E0796]
-        //[e2021]~^^ ERROR shared reference to mutable static is discouraged [static_mut_refs]
-        //[e2024]~^^^ ERROR creating a shared reference to a mutable static [E0796]
-        //[e2021]~^^^^ ERROR shared reference to mutable static is discouraged [static_mut_refs]
-
-        foo(&X);
-        //[e2024]~^ ERROR creating a shared reference to a mutable static [E0796]
-        //[e2021]~^^ ERROR shared reference to mutable static is discouraged [static_mut_refs]
-
-        static mut Z: &[i32; 3] = &[0, 1, 2];
-
-        let _ = Z.len();
-        let _ = Z[0];
-        let _ = format!("{:?}", Z);
-    }
-}
-
-fn foo<'a>(_x: &'a i32) {}
diff --git a/tests/ui/static/safe-extern-statics-mut.rs b/tests/ui/static/safe-extern-statics-mut.rs
index 05a1bee8891..4dfcd41b73c 100644
--- a/tests/ui/static/safe-extern-statics-mut.rs
+++ b/tests/ui/static/safe-extern-statics-mut.rs
@@ -10,8 +10,6 @@ extern "C" {
 fn main() {
     let b = B; //~ ERROR use of mutable static is unsafe
     let rb = &B; //~ ERROR use of mutable static is unsafe
-    //~^ WARN shared reference to mutable static is discouraged [static_mut_refs]
     let xb = XB; //~ ERROR use of mutable static is unsafe
     let xrb = &XB; //~ ERROR use of mutable static is unsafe
-    //~^ WARN shared reference to mutable static is discouraged [static_mut_refs]
 }
diff --git a/tests/ui/static/safe-extern-statics-mut.stderr b/tests/ui/static/safe-extern-statics-mut.stderr
index 7705a897e27..e390625f20a 100644
--- a/tests/ui/static/safe-extern-statics-mut.stderr
+++ b/tests/ui/static/safe-extern-statics-mut.stderr
@@ -1,32 +1,3 @@
-warning: creating a shared reference to mutable static is discouraged
-  --> $DIR/safe-extern-statics-mut.rs:12:14
-   |
-LL |     let rb = &B;
-   |              ^^ shared 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 shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
-   = note: `#[warn(static_mut_refs)]` on by default
-help: use `addr_of!` instead to create a raw pointer
-   |
-LL |     let rb = addr_of!(B);
-   |              ~~~~~~~~~ +
-
-warning: creating a shared reference to mutable static is discouraged
-  --> $DIR/safe-extern-statics-mut.rs:15:15
-   |
-LL |     let xrb = &XB;
-   |               ^^^ shared 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 shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
-help: use `addr_of!` instead to create a raw pointer
-   |
-LL |     let xrb = addr_of!(XB);
-   |               ~~~~~~~~~  +
-
 error[E0133]: use of mutable static is unsafe and requires unsafe function or block
   --> $DIR/safe-extern-statics-mut.rs:11:13
    |
@@ -44,7 +15,7 @@ LL |     let rb = &B;
    = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
 
 error[E0133]: use of mutable static is unsafe and requires unsafe function or block
-  --> $DIR/safe-extern-statics-mut.rs:14:14
+  --> $DIR/safe-extern-statics-mut.rs:13:14
    |
 LL |     let xb = XB;
    |              ^^ use of mutable static
@@ -52,13 +23,13 @@ LL |     let xb = XB;
    = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
 
 error[E0133]: use of mutable static is unsafe and requires unsafe function or block
-  --> $DIR/safe-extern-statics-mut.rs:15:16
+  --> $DIR/safe-extern-statics-mut.rs:14:16
    |
 LL |     let xrb = &XB;
    |                ^^ use of mutable static
    |
    = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
 
-error: aborting due to 4 previous errors; 2 warnings emitted
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0133`.
diff --git a/tests/ui/statics/issue-15261.stderr b/tests/ui/statics/issue-15261.stderr
index 6035eef5b71..417dbae9db1 100644
--- a/tests/ui/statics/issue-15261.stderr
+++ b/tests/ui/statics/issue-15261.stderr
@@ -4,14 +4,13 @@ warning: creating a shared reference to mutable static is discouraged
 LL | static n: &'static usize = unsafe { &n_mut };
    |                                     ^^^^^^ shared 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 shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
    = note: `#[warn(static_mut_refs)]` on by default
-help: use `addr_of!` instead to create a raw pointer
+help: use `&raw const` instead to create a raw pointer
    |
-LL | static n: &'static usize = unsafe { addr_of!(n_mut) };
-   |                                     ~~~~~~~~~     +
+LL | static n: &'static usize = unsafe { &raw const n_mut };
+   |                                     ~~~~~~~~~~
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/statics/static-mut-xc.rs b/tests/ui/statics/static-mut-xc.rs
index a772d4151f7..c23cc822ce7 100644
--- a/tests/ui/statics/static-mut-xc.rs
+++ b/tests/ui/statics/static-mut-xc.rs
@@ -17,14 +17,19 @@ fn static_bound_set(a: &'static mut isize) {
 
 unsafe fn run() {
     assert_eq!(static_mut_xc::a, 3);
+    //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs]
     static_mut_xc::a = 4;
     assert_eq!(static_mut_xc::a, 4);
+    //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs]
     static_mut_xc::a += 1;
     assert_eq!(static_mut_xc::a, 5);
+    //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs]
     static_mut_xc::a *= 3;
     assert_eq!(static_mut_xc::a, 15);
+    //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs]
     static_mut_xc::a = -3;
     assert_eq!(static_mut_xc::a, -3);
+    //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs]
     static_bound(&static_mut_xc::a);
     //~^ WARN shared reference to mutable static is discouraged [static_mut_refs]
     static_bound_set(&mut static_mut_xc::a);
diff --git a/tests/ui/statics/static-mut-xc.stderr b/tests/ui/statics/static-mut-xc.stderr
index 9751f754332..176deb518fc 100644
--- a/tests/ui/statics/static-mut-xc.stderr
+++ b/tests/ui/statics/static-mut-xc.stderr
@@ -1,31 +1,74 @@
 warning: creating a shared reference to mutable static is discouraged
-  --> $DIR/static-mut-xc.rs:28:18
+  --> $DIR/static-mut-xc.rs:19:16
+   |
+LL |     assert_eq!(static_mut_xc::a, 3);
+   |                ^^^^^^^^^^^^^^^^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+   = note: `#[warn(static_mut_refs)]` on by default
+
+warning: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-xc.rs:22:16
+   |
+LL |     assert_eq!(static_mut_xc::a, 4);
+   |                ^^^^^^^^^^^^^^^^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+
+warning: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-xc.rs:25:16
+   |
+LL |     assert_eq!(static_mut_xc::a, 5);
+   |                ^^^^^^^^^^^^^^^^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+
+warning: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-xc.rs:28:16
+   |
+LL |     assert_eq!(static_mut_xc::a, 15);
+   |                ^^^^^^^^^^^^^^^^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+
+warning: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-xc.rs:31:16
+   |
+LL |     assert_eq!(static_mut_xc::a, -3);
+   |                ^^^^^^^^^^^^^^^^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+
+warning: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-mut-xc.rs:33:18
    |
 LL |     static_bound(&static_mut_xc::a);
    |                  ^^^^^^^^^^^^^^^^^ shared 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 shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
-   = note: `#[warn(static_mut_refs)]` on by default
-help: use `addr_of!` instead to create a raw pointer
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+help: use `&raw const` instead to create a raw pointer
    |
-LL |     static_bound(addr_of!(static_mut_xc::a));
-   |                  ~~~~~~~~~                +
+LL |     static_bound(&raw const static_mut_xc::a);
+   |                  ~~~~~~~~~~
 
 warning: creating a mutable reference to mutable static is discouraged
-  --> $DIR/static-mut-xc.rs:30:22
+  --> $DIR/static-mut-xc.rs:35:22
    |
 LL |     static_bound_set(&mut static_mut_xc::a);
    |                      ^^^^^^^^^^^^^^^^^^^^^ 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
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives
+help: use `&raw mut` instead to create a raw pointer
    |
-LL |     static_bound_set(addr_of_mut!(static_mut_xc::a));
-   |                      ~~~~~~~~~~~~~                +
+LL |     static_bound_set(&raw mut static_mut_xc::a);
+   |                      ~~~~~~~~
 
-warning: 2 warnings emitted
+warning: 7 warnings emitted
 
diff --git a/tests/ui/statics/static-recursive.rs b/tests/ui/statics/static-recursive.rs
index 29b80818b7d..da23b54d1fc 100644
--- a/tests/ui/statics/static-recursive.rs
+++ b/tests/ui/statics/static-recursive.rs
@@ -17,6 +17,7 @@ static L3: StaticDoubleLinked = StaticDoubleLinked { prev: &L2, next: &L1, data:
 pub fn main() {
     unsafe {
         assert_eq!(S, *(S as *const *const u8));
+        //~^ WARN creating a shared reference to mutable static is discouraged [static_mut_refs]
     }
 
     let mut test_vec = Vec::new();
diff --git a/tests/ui/statics/static-recursive.stderr b/tests/ui/statics/static-recursive.stderr
index a7a1a1610af..f2dd5b8a6cf 100644
--- a/tests/ui/statics/static-recursive.stderr
+++ b/tests/ui/statics/static-recursive.stderr
@@ -4,14 +4,22 @@ warning: creating a shared reference to mutable static is discouraged
 LL | static mut S: *const u8 = unsafe { &S as *const *const u8 as *const u8 };
    |                                    ^^ shared 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 shared reference has lifetime `'static`, but if the static ever gets mutated, or a mutable reference is created, then any further use of this shared reference is Undefined Behavior
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
    = note: `#[warn(static_mut_refs)]` on by default
-help: use `addr_of!` instead to create a raw pointer
+help: use `&raw const` instead to create a raw pointer
    |
-LL | static mut S: *const u8 = unsafe { addr_of!(S) as *const *const u8 as *const u8 };
-   |                                    ~~~~~~~~~ +
+LL | static mut S: *const u8 = unsafe { &raw const S as *const *const u8 as *const u8 };
+   |                                    ~~~~~~~~~~
 
-warning: 1 warning emitted
+warning: creating a shared reference to mutable static is discouraged
+  --> $DIR/static-recursive.rs:19:20
+   |
+LL |         assert_eq!(S, *(S as *const *const u8));
+   |                    ^ shared reference to mutable static
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html>
+   = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives
+
+warning: 2 warnings emitted
 
diff --git a/tests/ui/structs-enums/type-sizes.rs b/tests/ui/structs-enums/type-sizes.rs
index 5ca9c8678b7..f49ce33841a 100644
--- a/tests/ui/structs-enums/type-sizes.rs
+++ b/tests/ui/structs-enums/type-sizes.rs
@@ -209,6 +209,23 @@ struct ReorderEndNiche {
     b: MiddleNiche4,
 }
 
+// We want that the niche selection doesn't depend on order of the fields. See issue #125630.
+pub enum NicheFieldOrder1 {
+    A {
+        x: NonZero<u64>,
+        y: [NonZero<u64>; 2],
+    },
+    B([u64; 2]),
+}
+
+pub enum NicheFieldOrder2 {
+    A {
+        y: [NonZero<u64>; 2],
+        x: NonZero<u64>,
+    },
+    B([u64; 2]),
+}
+
 
 // standins for std types which we want to be laid out in a reasonable way
 struct RawVecDummy {
@@ -260,6 +277,9 @@ pub fn main() {
                size_of::<EnumWithMaybeUninhabitedVariant<()>>());
     assert_eq!(size_of::<NicheFilledEnumWithAbsentVariant>(), size_of::<&'static ()>());
 
+    assert_eq!(size_of::<NicheFieldOrder1>(), 24);
+    assert_eq!(size_of::<NicheFieldOrder2>(), 24);
+
     assert_eq!(size_of::<Option<Option<(bool, &())>>>(), size_of::<(bool, &())>());
     assert_eq!(size_of::<Option<Option<(&(), bool)>>>(), size_of::<(bool, &())>());
     assert_eq!(size_of::<Option<Option2<bool, &()>>>(), size_of::<(bool, &())>());
diff --git a/tests/ui/suggestions/let-binding-init-expr-as-ty.rs b/tests/ui/suggestions/let-binding-init-expr-as-ty.rs
index 06ee421fc32..71e5a0c728d 100644
--- a/tests/ui/suggestions/let-binding-init-expr-as-ty.rs
+++ b/tests/ui/suggestions/let-binding-init-expr-as-ty.rs
@@ -1,8 +1,8 @@
 pub fn foo(num: i32) -> i32 {
     let foo: i32::from_be(num);
     //~^ ERROR expected type, found local variable `num`
-    //~| ERROR parenthesized type parameters may only be used with a `Fn` trait
-    //~| ERROR ambiguous associated type
+    //~| ERROR argument types not allowed with return type notation
+    //~| ERROR return type notation not allowed in this position yet
     foo
 }
 
diff --git a/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr b/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr
index b90ae051fb7..83a5441e3c0 100644
--- a/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr
+++ b/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr
@@ -6,29 +6,22 @@ LL |     let foo: i32::from_be(num);
    |            |
    |            help: use `=` if you meant to assign
 
-error[E0214]: parenthesized type parameters may only be used with a `Fn` trait
-  --> $DIR/let-binding-init-expr-as-ty.rs:2:19
+error: argument types not allowed with return type notation
+  --> $DIR/let-binding-init-expr-as-ty.rs:2:26
    |
 LL |     let foo: i32::from_be(num);
-   |                   ^^^^^^^^^^^^ only `Fn` traits may use parentheses
+   |                          ^^^^^ help: remove the input types: `()`
    |
-help: use angle brackets instead
-   |
-LL |     let foo: i32::from_be<num>;
-   |                          ~   ~
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = help: add `#![feature(return_type_notation)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0223]: ambiguous associated type
+error: return type notation not allowed in this position yet
   --> $DIR/let-binding-init-expr-as-ty.rs:2:14
    |
 LL |     let foo: i32::from_be(num);
    |              ^^^^^^^^^^^^^^^^^
-   |
-help: if there were a trait named `Example` with associated type `from_be` implemented for `i32`, you could use the fully-qualified path
-   |
-LL |     let foo: <i32 as Example>::from_be;
-   |              ~~~~~~~~~~~~~~~~~~~~~~~~~
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0214, E0223, E0573.
-For more information about an error, try `rustc --explain E0214`.
+For more information about this error, try `rustc --explain E0573`.
diff --git a/tests/ui/thread-local/thread-local-issue-37508.rs b/tests/ui/thread-local/thread-local-issue-37508.rs
index db430a3229c..34c39453451 100644
--- a/tests/ui/thread-local/thread-local-issue-37508.rs
+++ b/tests/ui/thread-local/thread-local-issue-37508.rs
@@ -4,6 +4,9 @@
 //
 // Regression test for issue #37508
 
+// FIXME(static_mut_refs): Do not allow `static_mut_refs` lint
+#![allow(static_mut_refs)]
+
 #![no_main]
 #![no_std]
 #![feature(thread_local, lang_items)]
diff --git a/tests/ui/traits/coherence-alias-hang.rs b/tests/ui/traits/coherence-alias-hang.rs
index 37b80739589..c2b4d2e42d2 100644
--- a/tests/ui/traits/coherence-alias-hang.rs
+++ b/tests/ui/traits/coherence-alias-hang.rs
@@ -1,4 +1,6 @@
 //@ check-pass
+//@ revisions: current next
+//[next]@ compile-flags: -Znext-solver
 
 // Regression test for nalgebra hang <https://github.com/rust-lang/rust/issues/130056>.
 
diff --git a/tests/ui/traits/impl.rs b/tests/ui/traits/impl.rs
index 348096f37f7..b45935fd86a 100644
--- a/tests/ui/traits/impl.rs
+++ b/tests/ui/traits/impl.rs
@@ -3,6 +3,9 @@
 
 //@ aux-build:traitimpl.rs
 
+// FIXME(static_mut_refs): this could use an atomic
+#![allow(static_mut_refs)]
+
 extern crate traitimpl;
 use traitimpl::Bar;
 
diff --git a/tests/ui/traits/impl.stderr b/tests/ui/traits/impl.stderr
index 98b6fb03d83..9216a33c1d0 100644
--- a/tests/ui/traits/impl.stderr
+++ b/tests/ui/traits/impl.stderr
@@ -1,5 +1,5 @@
 warning: method `t` is never used
-  --> $DIR/impl.rs:12:8
+  --> $DIR/impl.rs:15:8
    |
 LL | trait T {
    |       - method in this trait
diff --git a/tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.stderr b/tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.stderr
index 8d7d8cee08a..150100f2c53 100644
--- a/tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.stderr
+++ b/tests/ui/traits/next-solver/cycles/coinduction/fixpoint-exponential-growth.stderr
@@ -4,6 +4,7 @@ error[E0275]: overflow evaluating the requirement `W<_>: Trait`
 LL |     impls::<W<_>>();
    |             ^^^^
    |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`fixpoint_exponential_growth`)
 note: required by a bound in `impls`
   --> $DIR/fixpoint-exponential-growth.rs:30:13
    |
diff --git a/tests/ui/traits/next-solver/overflow/recursion-limit-zero-issue-115351.rs b/tests/ui/traits/next-solver/overflow/recursion-limit-zero-issue-115351.rs
index 1b80287d9da..86d428cc0f0 100644
--- a/tests/ui/traits/next-solver/overflow/recursion-limit-zero-issue-115351.rs
+++ b/tests/ui/traits/next-solver/overflow/recursion-limit-zero-issue-115351.rs
@@ -1,6 +1,7 @@
+//~ ERROR overflow evaluating the requirement `Self: Trait`
+//~^ ERROR overflow evaluating the requirement `Self well-formed`
 // This is a non-regression test for issue #115351, where a recursion limit of 0 caused an ICE.
 //@ compile-flags: -Znext-solver --crate-type=lib
-//@ check-pass
 
 #![recursion_limit = "0"]
 trait Trait {}
diff --git a/tests/ui/traits/next-solver/overflow/recursion-limit-zero-issue-115351.stderr b/tests/ui/traits/next-solver/overflow/recursion-limit-zero-issue-115351.stderr
new file mode 100644
index 00000000000..2eed7e8f723
--- /dev/null
+++ b/tests/ui/traits/next-solver/overflow/recursion-limit-zero-issue-115351.stderr
@@ -0,0 +1,11 @@
+error[E0275]: overflow evaluating the requirement `Self: Trait`
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "2"]` attribute to your crate (`recursion_limit_zero_issue_115351`)
+
+error[E0275]: overflow evaluating the requirement `Self well-formed`
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "2"]` attribute to your crate (`recursion_limit_zero_issue_115351`)
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/sized-coniductive.rs b/tests/ui/traits/sized-coniductive.rs
new file mode 100644
index 00000000000..5f63b166f98
--- /dev/null
+++ b/tests/ui/traits/sized-coniductive.rs
@@ -0,0 +1,14 @@
+//@ check-pass
+// https://github.com/rust-lang/rust/issues/129541
+
+#[derive(Clone)]
+struct Test {
+    field: std::borrow::Cow<'static, [Self]>,
+}
+
+#[derive(Clone)]
+struct Hello {
+    a: <[Hello] as std::borrow::ToOwned>::Owned,
+}
+
+fn main(){}
diff --git a/tests/ui/transmutability/arrays/huge-len.stderr b/tests/ui/transmutability/arrays/huge-len.stderr
index 1fa16c649d4..2f8a86df0a7 100644
--- a/tests/ui/transmutability/arrays/huge-len.stderr
+++ b/tests/ui/transmutability/arrays/huge-len.stderr
@@ -2,7 +2,7 @@ error[E0277]: `()` cannot be safely transmuted into `ExplicitlyPadded`
   --> $DIR/huge-len.rs:21:41
    |
 LL |     assert::is_maybe_transmutable::<(), ExplicitlyPadded>();
-   |                                         ^^^^^^^^^^^^^^^^ values of the type `ExplicitlyPadded` are too big for the current architecture
+   |                                         ^^^^^^^^^^^^^^^^ values of the type `ExplicitlyPadded` are too big for the target architecture
    |
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/huge-len.rs:8:14
@@ -17,7 +17,7 @@ error[E0277]: `ExplicitlyPadded` cannot be safely transmuted into `()`
   --> $DIR/huge-len.rs:24:55
    |
 LL |     assert::is_maybe_transmutable::<ExplicitlyPadded, ()>();
-   |                                                       ^^ values of the type `ExplicitlyPadded` are too big for the current architecture
+   |                                                       ^^ values of the type `ExplicitlyPadded` are too big for the target architecture
    |
 note: required by a bound in `is_maybe_transmutable`
   --> $DIR/huge-len.rs:8:14
diff --git a/tests/ui/union/union-drop-assign.rs b/tests/ui/union/union-drop-assign.rs
index e9165fddc51..451fb14eddf 100644
--- a/tests/ui/union/union-drop-assign.rs
+++ b/tests/ui/union/union-drop-assign.rs
@@ -3,6 +3,9 @@
 
 // Drop works for union itself.
 
+// FIXME(static_mut_refs): this could use an atomic
+#![allow(static_mut_refs)]
+
 use std::mem::ManuallyDrop;
 
 struct S;
diff --git a/tests/ui/union/union-drop.rs b/tests/ui/union/union-drop.rs
index e467eda2935..6f6d5c14165 100644
--- a/tests/ui/union/union-drop.rs
+++ b/tests/ui/union/union-drop.rs
@@ -2,6 +2,8 @@
 
 #![allow(dead_code)]
 #![allow(unused_variables)]
+// FIXME(static_mut_refs): this could use an atomic
+#![allow(static_mut_refs)]
 
 // Drop works for union itself.
 
diff --git a/tests/ui/unsafe/union-pat-in-param.rs b/tests/ui/unsafe/union-pat-in-param.rs
new file mode 100644
index 00000000000..8454bfb20dc
--- /dev/null
+++ b/tests/ui/unsafe/union-pat-in-param.rs
@@ -0,0 +1,19 @@
+union U {
+    a: &'static i32,
+    b: usize,
+}
+
+fn fun(U { a }: U) {
+    //~^ ERROR access to union field is unsafe
+    dbg!(*a);
+}
+
+fn main() {
+    fun(U { b: 0 });
+
+    let closure = |U { a }| {
+        //~^ ERROR access to union field is unsafe
+        dbg!(*a);
+    };
+    closure(U { b: 0 });
+}
diff --git a/tests/ui/unsafe/union-pat-in-param.stderr b/tests/ui/unsafe/union-pat-in-param.stderr
new file mode 100644
index 00000000000..b9709b7cc9b
--- /dev/null
+++ b/tests/ui/unsafe/union-pat-in-param.stderr
@@ -0,0 +1,19 @@
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-pat-in-param.rs:6:12
+   |
+LL | fn fun(U { a }: U) {
+   |            ^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error[E0133]: access to union field is unsafe and requires unsafe function or block
+  --> $DIR/union-pat-in-param.rs:14:24
+   |
+LL |     let closure = |U { a }| {
+   |                        ^ access to union field
+   |
+   = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0133`.