about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock344
-rw-r--r--Cargo.toml10
-rw-r--r--bootstrap.example.toml17
-rw-r--r--compiler/rustc_abi/Cargo.toml4
-rw-r--r--compiler/rustc_ast/Cargo.toml8
-rw-r--r--compiler/rustc_ast_lowering/Cargo.toml4
-rw-r--r--compiler/rustc_ast_passes/Cargo.toml4
-rw-r--r--compiler/rustc_ast_pretty/Cargo.toml4
-rw-r--r--compiler/rustc_attr_parsing/Cargo.toml3
-rw-r--r--compiler/rustc_attr_parsing/messages.ftl58
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/cfg.rs2
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs120
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/crate_level.rs36
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/inline.rs1
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/link_attrs.rs426
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/mod.rs18
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs1
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs12
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/traits.rs3
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/util.rs6
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs54
-rw-r--r--compiler/rustc_attr_parsing/src/interface.rs45
-rw-r--r--compiler/rustc_attr_parsing/src/lib.rs5
-rw-r--r--compiler/rustc_attr_parsing/src/lints.rs30
-rw-r--r--compiler/rustc_attr_parsing/src/parser.rs33
-rw-r--r--compiler/rustc_attr_parsing/src/session_diagnostics.rs112
-rw-r--r--compiler/rustc_attr_parsing/src/target_checking.rs70
-rw-r--r--compiler/rustc_baked_icu_data/Cargo.toml9
-rw-r--r--compiler/rustc_baked_icu_data/src/data/any.rs2
-rw-r--r--compiler/rustc_baked_icu_data/src/data/list_and_v1.rs.data71
-rw-r--r--compiler/rustc_baked_icu_data/src/data/macros.rs46
-rw-r--r--compiler/rustc_baked_icu_data/src/data/macros/fallback_likelysubtags_v1.data.rs40
-rw-r--r--compiler/rustc_baked_icu_data/src/data/macros/fallback_parents_v1.data.rs28
-rw-r--r--compiler/rustc_baked_icu_data/src/data/macros/fallback_supplement_co_v1.data.rs32
-rw-r--r--compiler/rustc_baked_icu_data/src/data/macros/list_and_v1.data.rs35
-rw-r--r--compiler/rustc_baked_icu_data/src/data/mod.rs57
-rw-r--r--compiler/rustc_baked_icu_data/src/lib.rs39
-rw-r--r--compiler/rustc_borrowck/Cargo.toml4
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/opaque_types.rs7
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/region_errors.rs21
-rw-r--r--compiler/rustc_borrowck/src/handle_placeholders.rs210
-rw-r--r--compiler/rustc_borrowck/src/lib.rs14
-rw-r--r--compiler/rustc_borrowck/src/region_infer/graphviz.rs10
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs199
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs19
-rw-r--r--compiler/rustc_borrowck/src/root_cx.rs4
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs3
-rw-r--r--compiler/rustc_borrowck/src/type_check/constraint_conversion.rs20
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs32
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/trace.rs2
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs157
-rw-r--r--compiler/rustc_builtin_macros/Cargo.toml4
-rw-r--r--compiler/rustc_builtin_macros/src/format_foreign.rs2
-rw-r--r--compiler/rustc_codegen_gcc/.github/workflows/m68k.yml42
-rw-r--r--compiler/rustc_codegen_gcc/Cargo.lock8
-rw-r--r--compiler/rustc_codegen_gcc/Cargo.toml2
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/fmt.rs30
-rw-r--r--compiler/rustc_codegen_gcc/build_system/src/test.rs2
-rw-r--r--compiler/rustc_codegen_gcc/libgccjit.version2
-rw-r--r--compiler/rustc_codegen_gcc/rust-toolchain2
-rw-r--r--compiler/rustc_codegen_gcc/src/back/lto.rs33
-rw-r--r--compiler/rustc_codegen_gcc/src/back/write.rs7
-rw-r--r--compiler/rustc_codegen_gcc/src/intrinsic/simd.rs1
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs12
-rw-r--r--compiler/rustc_codegen_gcc/tests/failing-run-make-tests.txt3
-rw-r--r--compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt4
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/int.rs10
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/int_overflow.rs2
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/structs.rs8
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/volatile.rs8
-rw-r--r--compiler/rustc_codegen_gcc/tests/run/volatile2.rs12
-rw-r--r--compiler/rustc_codegen_llvm/Cargo.toml6
-rw-r--r--compiler/rustc_codegen_llvm/src/abi.rs8
-rw-r--r--compiler/rustc_codegen_llvm/src/allocator.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/asm.rs11
-rw-r--r--compiler/rustc_codegen_llvm/src/back/lto.rs62
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs41
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs49
-rw-r--r--compiler/rustc_codegen_llvm/src/builder/autodiff.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/common.rs10
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs32
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs72
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/mod.rs30
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/mono_item.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/type_.rs12
-rw-r--r--compiler/rustc_codegen_ssa/Cargo.toml8
-rw-r--r--compiler/rustc_codegen_ssa/messages.ftl3
-rw-r--r--compiler/rustc_codegen_ssa/src/back/apple.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs7
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs15
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs12
-rw-r--r--compiler/rustc_codegen_ssa/src/back/symbol_export.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/write.rs94
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs91
-rw-r--r--compiler/rustc_codegen_ssa/src/common.rs3
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs8
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs5
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/write.rs12
-rw-r--r--compiler/rustc_const_eval/Cargo.toml2
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs118
-rw-r--r--compiler/rustc_const_eval/src/interpret/step.rs23
-rw-r--r--compiler/rustc_data_structures/Cargo.toml10
-rw-r--r--compiler/rustc_driver_impl/Cargo.toml2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0458.md4
-rw-r--r--compiler/rustc_error_messages/Cargo.toml7
-rw-r--r--compiler/rustc_error_messages/src/lib.rs25
-rw-r--r--compiler/rustc_errors/Cargo.toml3
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs23
-rw-r--r--compiler/rustc_errors/src/emitter.rs89
-rw-r--r--compiler/rustc_errors/src/lib.rs6
-rw-r--r--compiler/rustc_expand/Cargo.toml4
-rw-r--r--compiler/rustc_expand/src/expand.rs14
-rw-r--r--compiler/rustc_hir/Cargo.toml6
-rw-r--r--compiler/rustc_hir/src/attrs/data_structures.rs127
-rw-r--r--compiler/rustc_hir/src/attrs/encode_cross_crate.rs8
-rw-r--r--compiler/rustc_hir/src/attrs/pretty_printing.rs13
-rw-r--r--compiler/rustc_hir/src/lints.rs1
-rw-r--r--compiler/rustc_hir_analysis/Cargo.toml4
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl4
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs26
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs21
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/lib.rs2
-rw-r--r--compiler/rustc_hir_typeck/Cargo.toml4
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs16
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs30
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs57
-rw-r--r--compiler/rustc_hir_typeck/src/opaque_types.rs215
-rw-r--r--compiler/rustc_hir_typeck/src/upvar.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/writeback.rs64
-rw-r--r--compiler/rustc_incremental/Cargo.toml4
-rw-r--r--compiler/rustc_index/src/bit_set.rs253
-rw-r--r--compiler/rustc_index/src/bit_set/tests.rs56
-rw-r--r--compiler/rustc_infer/Cargo.toml4
-rw-r--r--compiler/rustc_infer/src/infer/context.rs4
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs3
-rw-r--r--compiler/rustc_interface/Cargo.toml2
-rw-r--r--compiler/rustc_interface/src/passes.rs28
-rw-r--r--compiler/rustc_interface/src/tests.rs3
-rw-r--r--compiler/rustc_interface/src/util.rs12
-rw-r--r--compiler/rustc_lexer/Cargo.toml8
-rw-r--r--compiler/rustc_lint/Cargo.toml2
-rw-r--r--compiler/rustc_lint/messages.ftl8
-rw-r--r--compiler/rustc_lint/src/lifetime_syntax.rs8
-rw-r--r--compiler/rustc_lint/src/lints.rs44
-rw-r--r--compiler/rustc_lint/src/nonstandard_style.rs52
-rw-r--r--compiler/rustc_lint/src/transmute.rs98
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp18
-rw-r--r--compiler/rustc_log/Cargo.toml2
-rw-r--r--compiler/rustc_metadata/Cargo.toml4
-rw-r--r--compiler/rustc_metadata/messages.ftl95
-rw-r--r--compiler/rustc_metadata/src/errors.rs217
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs335
-rw-r--r--compiler/rustc_middle/Cargo.toml6
-rw-r--r--compiler/rustc_middle/src/middle/codegen_fn_attrs.rs7
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs11
-rw-r--r--compiler/rustc_middle/src/mir/mono.rs2
-rw-r--r--compiler/rustc_middle/src/mir/query.rs11
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs5
-rw-r--r--compiler/rustc_middle/src/query/mod.rs16
-rw-r--r--compiler/rustc_middle/src/ty/context.rs9
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs7
-rw-r--r--compiler/rustc_middle/src/ty/trait_def.rs7
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs11
-rw-r--r--compiler/rustc_mir_build/Cargo.toml4
-rw-r--r--compiler/rustc_mir_dataflow/Cargo.toml2
-rw-r--r--compiler/rustc_mir_transform/Cargo.toml4
-rw-r--r--compiler/rustc_mir_transform/src/check_enums.rs15
-rw-r--r--compiler/rustc_mir_transform/src/cross_crate_inline.rs2
-rw-r--r--compiler/rustc_monomorphize/Cargo.toml2
-rw-r--r--compiler/rustc_next_trait_solver/Cargo.toml2
-rw-r--r--compiler/rustc_next_trait_solver/src/canonicalizer.rs35
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/effect_goals.rs18
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs2
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs30
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs174
-rw-r--r--compiler/rustc_parse/Cargo.toml8
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs18
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs8
-rw-r--r--compiler/rustc_parse/src/parser/item.rs4
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs62
-rw-r--r--compiler/rustc_parse/src/parser/token_type.rs6
-rw-r--r--compiler/rustc_parse_format/Cargo.toml2
-rw-r--r--compiler/rustc_passes/Cargo.toml2
-rw-r--r--compiler/rustc_passes/messages.ftl4
-rw-r--r--compiler/rustc_passes/src/check_attr.rs167
-rw-r--r--compiler/rustc_passes/src/dead.rs2
-rw-r--r--compiler/rustc_passes/src/errors.rs12
-rw-r--r--compiler/rustc_passes/src/reachable.rs4
-rw-r--r--compiler/rustc_pattern_analysis/Cargo.toml2
-rw-r--r--compiler/rustc_pattern_analysis/src/rustc/print.rs22
-rw-r--r--compiler/rustc_privacy/Cargo.toml2
-rw-r--r--compiler/rustc_proc_macro/Cargo.toml2
-rw-r--r--compiler/rustc_public/Cargo.toml2
-rw-r--r--compiler/rustc_query_impl/Cargo.toml2
-rw-r--r--compiler/rustc_query_system/Cargo.toml2
-rw-r--r--compiler/rustc_resolve/Cargo.toml8
-rw-r--r--compiler/rustc_resolve/src/rustdoc.rs9
-rw-r--r--compiler/rustc_sanitizers/Cargo.toml4
-rw-r--r--compiler/rustc_serialize/Cargo.toml2
-rw-r--r--compiler/rustc_session/Cargo.toml4
-rw-r--r--compiler/rustc_session/src/config/native_libs.rs3
-rw-r--r--compiler/rustc_session/src/cstore.rs24
-rw-r--r--compiler/rustc_session/src/session.rs17
-rw-r--r--compiler/rustc_session/src/utils.rs64
-rw-r--r--compiler/rustc_span/Cargo.toml2
-rw-r--r--compiler/rustc_span/src/source_map.rs10
-rw-r--r--compiler/rustc_span/src/symbol.rs12
-rw-r--r--compiler/rustc_symbol_mangling/Cargo.toml2
-rw-r--r--compiler/rustc_target/Cargo.toml11
-rw-r--r--compiler/rustc_target/src/callconv/mod.rs8
-rw-r--r--compiler/rustc_target/src/spec/mod.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_musl.rs40
-rw-r--r--compiler/rustc_target/src/spec/targets/riscv64a23_unknown_linux_gnu.rs27
-rw-r--r--compiler/rustc_target/src/target_features.rs43
-rw-r--r--compiler/rustc_thread_pool/src/lib.rs15
-rw-r--r--compiler/rustc_trait_selection/Cargo.toml6
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs16
-rw-r--r--compiler/rustc_trait_selection/src/opaque_types.rs54
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs9
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs16
-rw-r--r--compiler/rustc_traits/Cargo.toml2
-rw-r--r--compiler/rustc_transmute/Cargo.toml4
-rw-r--r--compiler/rustc_ty_utils/Cargo.toml4
-rw-r--r--compiler/rustc_type_ir/Cargo.toml6
-rw-r--r--compiler/rustc_type_ir/src/infer_ctxt.rs4
-rw-r--r--library/alloc/src/boxed.rs5
-rw-r--r--library/alloc/src/boxed/convert.rs7
-rw-r--r--library/alloc/src/collections/btree/map.rs76
-rw-r--r--library/alloc/src/collections/btree/map/entry.rs4
-rw-r--r--library/alloc/src/ffi/c_str.rs21
-rw-r--r--library/alloc/src/lib.rs3
-rw-r--r--library/alloc/src/raw_vec/mod.rs2
-rw-r--r--library/alloc/src/string.rs87
-rw-r--r--library/alloc/src/sync.rs5
-rw-r--r--library/alloc/src/wtf8/mod.rs562
-rw-r--r--library/alloc/src/wtf8/tests.rs (renamed from library/std/src/sys_common/wtf8/tests.rs)209
-rw-r--r--library/alloctests/lib.rs12
-rw-r--r--library/alloctests/tests/lib.rs1
-rw-r--r--library/compiler-builtins/compiler-builtins/README.md10
-rw-r--r--library/compiler-builtins/compiler-builtins/build.rs55
-rw-r--r--library/core/src/array/mod.rs10
-rw-r--r--library/core/src/char/convert.rs17
-rw-r--r--library/core/src/char/decode.rs7
-rw-r--r--library/core/src/char/methods.rs47
-rw-r--r--library/core/src/convert/mod.rs6
-rw-r--r--library/core/src/error.rs33
-rw-r--r--library/core/src/fmt/mod.rs22
-rw-r--r--library/core/src/hint.rs56
-rw-r--r--library/core/src/lib.rs2
-rw-r--r--library/core/src/net/parser.rs15
-rw-r--r--library/core/src/num/dec2flt/mod.rs17
-rw-r--r--library/core/src/num/error.rs25
-rw-r--r--library/core/src/num/f128.rs23
-rw-r--r--library/core/src/num/f16.rs20
-rw-r--r--library/core/src/num/f32.rs20
-rw-r--r--library/core/src/num/f64.rs26
-rw-r--r--library/core/src/num/niche_types.rs15
-rw-r--r--library/core/src/option.rs36
-rw-r--r--library/core/src/panic/location.rs4
-rw-r--r--library/core/src/ptr/metadata.rs3
-rw-r--r--library/core/src/ptr/mod.rs1
-rw-r--r--library/core/src/str/error.rs14
-rw-r--r--library/core/src/str/mod.rs2
-rw-r--r--library/core/src/time.rs17
-rw-r--r--library/core/src/wtf8.rs597
-rw-r--r--library/coretests/tests/lib.rs2
-rw-r--r--library/coretests/tests/wtf8.rs1
-rw-r--r--library/std/src/collections/hash/map.rs7
-rw-r--r--library/std/src/env.rs10
-rw-r--r--library/std/src/fs.rs3
-rw-r--r--library/std/src/io/buffered/bufwriter.rs12
-rw-r--r--library/std/src/io/buffered/mod.rs7
-rw-r--r--library/std/src/io/error.rs9
-rw-r--r--library/std/src/lib.rs3
-rw-r--r--library/std/src/os/windows/ffi.rs38
-rw-r--r--library/std/src/os/windows/io/socket.rs2
-rw-r--r--library/std/src/path.rs10
-rw-r--r--library/std/src/sync/lazy_lock.rs9
-rw-r--r--library/std/src/sync/mpmc/utils.rs8
-rw-r--r--library/std/src/sync/mpsc.rs44
-rw-r--r--library/std/src/sync/poison.rs18
-rw-r--r--library/std/src/sys/alloc/wasm.rs17
-rw-r--r--library/std/src/sys/fd/unix.rs6
-rw-r--r--library/std/src/sys/fs/mod.rs13
-rw-r--r--library/std/src/sys/net/connection/sgx.rs7
-rw-r--r--library/std/src/sys/os_str/wtf8.rs8
-rw-r--r--library/std/src/sys/pal/hermit/os.rs8
-rw-r--r--library/std/src/sys/pal/sgx/mod.rs3
-rw-r--r--library/std/src/sys/pal/sgx/os.rs10
-rw-r--r--library/std/src/sys/pal/solid/os.rs8
-rw-r--r--library/std/src/sys/pal/teeos/os.rs8
-rw-r--r--library/std/src/sys/pal/uefi/os.rs3
-rw-r--r--library/std/src/sys/pal/unix/os.rs8
-rw-r--r--library/std/src/sys/pal/unsupported/os.rs8
-rw-r--r--library/std/src/sys/pal/wasi/os.rs8
-rw-r--r--library/std/src/sys/pal/windows/os.rs8
-rw-r--r--library/std/src/sys/pal/xous/os.rs8
-rw-r--r--library/std/src/sys/pal/zkvm/os.rs8
-rw-r--r--library/std/src/sys_common/mod.rs1
-rw-r--r--library/std/src/sys_common/wtf8.rs1083
-rw-r--r--library/std/src/time.rs7
-rw-r--r--library/std/tests/sync/lazy_lock.rs84
-rw-r--r--src/bootstrap/bootstrap.py14
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs133
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs434
-rw-r--r--src/bootstrap/src/core/build_steps/doc.rs4
-rw-r--r--src/bootstrap/src/core/build_steps/install.rs85
-rw-r--r--src/bootstrap/src/core/build_steps/llvm.rs15
-rw-r--r--src/bootstrap/src/core/build_steps/run.rs47
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs68
-rw-r--r--src/bootstrap/src/core/build_steps/vendor.rs1
-rw-r--r--src/bootstrap/src/core/builder/cargo.rs14
-rw-r--r--src/bootstrap/src/core/builder/mod.rs46
-rw-r--r--src/bootstrap/src/core/builder/tests.rs372
-rw-r--r--src/bootstrap/src/core/config/config.rs116
-rw-r--r--src/bootstrap/src/core/config/mod.rs27
-rw-r--r--src/bootstrap/src/core/config/tests.rs10
-rw-r--r--src/bootstrap/src/core/config/toml/build.rs4
-rw-r--r--src/bootstrap/src/core/config/toml/rust.rs8
-rw-r--r--src/bootstrap/src/core/config/toml/target.rs8
-rw-r--r--src/bootstrap/src/core/sanity.rs6
-rw-r--r--src/bootstrap/src/lib.rs14
-rw-r--r--src/bootstrap/src/utils/build_stamp.rs6
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs15
-rw-r--r--src/bootstrap/src/utils/exec.rs9
-rw-r--r--src/bootstrap/src/utils/helpers.rs2
-rw-r--r--src/bootstrap/src/utils/tests/mod.rs4
-rw-r--r--src/build_helper/src/npm.rs2
-rw-r--r--src/ci/citool/src/analysis.rs2
-rw-r--r--src/ci/citool/src/test_dashboard.rs2
-rw-r--r--src/ci/citool/src/utils.rs2
-rw-r--r--src/ci/docker/host-x86_64/dist-aarch64-windows-gnullvm/Dockerfile17
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-windows-gnullvm/Dockerfile17
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile5
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile8
-rw-r--r--src/ci/github-actions/jobs.yml8
-rwxr-xr-xsrc/ci/scripts/free-disk-space-linux.sh9
m---------src/doc/nomicon0
m---------src/doc/reference0
m---------src/doc/rust-by-example0
-rw-r--r--src/doc/rustc-dev-guide/.github/workflows/rustc-pull.yml4
-rw-r--r--src/doc/rustc-dev-guide/rust-version2
-rw-r--r--src/doc/rustc-dev-guide/src/SUMMARY.md1
-rw-r--r--src/doc/rustc-dev-guide/src/about-this-guide.md1
-rw-r--r--src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md6
-rw-r--r--src/doc/rustc-dev-guide/src/diagnostics/error-codes.md2
-rw-r--r--src/doc/rustc-dev-guide/src/getting-started.md21
-rw-r--r--src/doc/rustc-dev-guide/src/git.md4
-rw-r--r--src/doc/rustc-dev-guide/src/img/coverage-branch-counting-01.pngbin11282 -> 4979 bytes
-rw-r--r--src/doc/rustc-dev-guide/src/img/dataflow-graphviz-example.pngbin81892 -> 51755 bytes
-rw-r--r--src/doc/rustc-dev-guide/src/img/github-cli.pngbin26790 -> 14969 bytes
-rw-r--r--src/doc/rustc-dev-guide/src/img/github-whitespace-changes.pngbin29217 -> 18174 bytes
-rw-r--r--src/doc/rustc-dev-guide/src/img/llvm-cov-show-01.pngbin416748 -> 206904 bytes
-rw-r--r--src/doc/rustc-dev-guide/src/img/other-peoples-commits.pngbin301512 -> 192607 bytes
-rw-r--r--src/doc/rustc-dev-guide/src/img/rustbot-submodules.pngbin26028 -> 15442 bytes
-rw-r--r--src/doc/rustc-dev-guide/src/img/submodule-conflicts.pngbin20216 -> 10907 bytes
-rw-r--r--src/doc/rustc-dev-guide/src/img/wpa-initial-memory.pngbin312637 -> 232624 bytes
-rw-r--r--src/doc/rustc-dev-guide/src/img/wpa-stack.pngbin145576 -> 63959 bytes
-rw-r--r--src/doc/rustc-dev-guide/src/macro-expansion.md56
-rw-r--r--src/doc/rustc-dev-guide/src/offload/installation.md29
-rw-r--r--src/doc/rustc-dev-guide/src/offload/usage.md112
-rw-r--r--src/doc/rustc-dev-guide/src/queries/example-0.pngbin106577 -> 55122 bytes
-rw-r--r--src/doc/rustc-dev-guide/src/tests/ci.md47
-rw-r--r--src/doc/rustc-dev-guide/src/tests/directives.md1
-rw-r--r--src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md8
-rw-r--r--src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/rust-for-linux.md10
-rw-r--r--src/doc/rustc-dev-guide/src/tests/ui.md1
-rw-r--r--src/doc/rustc/src/SUMMARY.md2
-rw-r--r--src/doc/rustc/src/command-line-arguments/print-options.md2
-rw-r--r--src/doc/rustc/src/images/image1.pngbin164896 -> 112780 bytes
-rw-r--r--src/doc/rustc/src/images/image2.pngbin155307 -> 107858 bytes
-rw-r--r--src/doc/rustc/src/images/image3.pngbin19936 -> 15559 bytes
-rw-r--r--src/doc/rustc/src/images/llvm-cov-show-01.pngbin416748 -> 206904 bytes
-rw-r--r--src/doc/rustc/src/platform-support.md8
-rw-r--r--src/doc/rustc/src/platform-support/aarch64_be-unknown-linux-musl.md49
-rw-r--r--src/doc/rustc/src/platform-support/riscv64a23-unknown-linux-gnu.md41
-rw-r--r--src/doc/rustdoc/src/images/collapsed-long-item.pngbin17017 -> 11156 bytes
-rw-r--r--src/doc/rustdoc/src/images/collapsed-trait-impls.pngbin44225 -> 31081 bytes
-rw-r--r--src/doc/rustdoc/src/unstable-features.md4
-rw-r--r--src/etc/installer/gfx/rust-logo.pngbin3909 -> 3261 bytes
m---------src/gcc0
-rw-r--r--src/librustdoc/Cargo.toml4
-rw-r--r--src/librustdoc/clean/inline.rs34
-rw-r--r--src/librustdoc/config.rs11
-rw-r--r--src/librustdoc/core.rs13
-rw-r--r--src/librustdoc/formats/renderer.rs18
-rw-r--r--src/librustdoc/html/highlight.rs295
-rw-r--r--src/librustdoc/html/macro_expansion.rs156
-rw-r--r--src/librustdoc/html/mod.rs1
-rw-r--r--src/librustdoc/html/render/context.rs28
-rw-r--r--src/librustdoc/html/render/mod.rs37
-rw-r--r--src/librustdoc/html/render/print_item.rs124
-rw-r--r--src/librustdoc/html/render/span_map.rs2
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css51
-rw-r--r--src/librustdoc/html/static/images/favicon-32x32.pngbin1125 -> 690 bytes
-rw-r--r--src/librustdoc/html/templates/item_union.html3
-rw-r--r--src/librustdoc/json/mod.rs20
-rw-r--r--src/librustdoc/lib.rs51
-rw-r--r--src/librustdoc/passes/lint/html_tags.rs476
-rw-r--r--src/librustdoc/passes/lint/html_tags/tests.rs73
-rw-r--r--src/librustdoc/scrape_examples.rs4
m---------src/llvm-project0
-rw-r--r--src/tools/build-manifest/Cargo.toml2
-rw-r--r--src/tools/bump-stage0/Cargo.toml2
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/Cargo.toml7
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_inline.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs12
-rw-r--r--src/tools/clippy/tests/ui/ptr_arg.stderr4
-rw-r--r--src/tools/clippy/tests/ui/transmute.rs3
-rw-r--r--src/tools/clippy/tests/ui/transmute.stderr46
-rw-r--r--src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed3
-rw-r--r--src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs3
-rw-r--r--src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr32
-rw-r--r--src/tools/compiletest/Cargo.toml2
-rw-r--r--src/tools/compiletest/src/common.rs10
-rw-r--r--src/tools/compiletest/src/directives.rs9
-rw-r--r--src/tools/compiletest/src/directives/directive_names.rs1
-rw-r--r--src/tools/compiletest/src/executor.rs22
-rw-r--r--src/tools/compiletest/src/lib.rs105
-rw-r--r--src/tools/compiletest/src/runtest.rs13
-rw-r--r--src/tools/compiletest/src/runtest/debuginfo.rs29
-rw-r--r--src/tools/compiletest/src/runtest/run_make.rs2
-rw-r--r--src/tools/coverage-dump/Cargo.toml2
-rw-r--r--src/tools/llvm-bitcode-linker/Cargo.toml4
-rw-r--r--src/tools/miri/src/bin/miri.rs2
-rw-r--r--src/tools/miri/src/helpers.rs3
-rw-r--r--src/tools/miri/src/shims/native_lib/mod.rs11
-rw-r--r--src/tools/miri/tests/fail/branchless-select-i128-pointer.rs2
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.rs2
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.rs34
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.stack.stderr25
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.tree.stderr34
-rw-r--r--src/tools/miri/tests/fail/provenance/provenance_transmute.rs2
-rw-r--r--src/tools/miri/tests/fail/validity/dangling_ref1.rs3
-rw-r--r--src/tools/miri/tests/panic/transmute_fat2.rs2
-rw-r--r--src/tools/miri/tests/pass/binops.rs1
-rw-r--r--src/tools/miri/tests/pass/too-large-primval-write-problem.rs2
-rw-r--r--src/tools/opt-dist/src/exec.rs6
-rw-r--r--src/tools/opt-dist/src/main.rs10
-rw-r--r--src/tools/rustfmt/Cargo.toml2
-rw-r--r--src/tools/rustfmt/tests/source/frontmatter_compact.rs8
-rw-r--r--src/tools/rustfmt/tests/source/frontmatter_escaped.rs13
-rw-r--r--src/tools/rustfmt/tests/source/frontmatter_spaced.rs16
-rw-r--r--src/tools/rustfmt/tests/target/frontmatter_compact.rs8
-rw-r--r--src/tools/rustfmt/tests/target/frontmatter_escaped.rs13
-rw-r--r--src/tools/rustfmt/tests/target/frontmatter_spaced.rs16
-rw-r--r--src/tools/tidy/src/deps.rs13
-rw-r--r--src/tools/tidy/src/gcc_submodule.rs6
-rw-r--r--src/tools/tidy/src/unit_tests.rs1
-rw-r--r--src/tools/wasm-component-ld/Cargo.toml2
-rw-r--r--tests/assembly-llvm/reg-struct-return.rs143
-rw-r--r--tests/assembly-llvm/targets/targets-elf.rs6
-rw-r--r--tests/codegen-llvm/addr-of-mutate.rs6
-rw-r--r--tests/codegen-llvm/function-arguments.rs4
-rw-r--r--tests/codegen-llvm/loongarch-abi/loongarch64-lp64d-abi.rs4
-rw-r--r--tests/crashes/120175.rs3
-rw-r--r--tests/crashes/124352.rs4
-rw-r--r--tests/crashes/137580.rs4
-rw-r--r--tests/mir-opt/building/async_await.rs2
-rw-r--r--tests/mir-opt/building/dump_mir_cycle.rs2
-rw-r--r--tests/mir-opt/building/enum_cast.rs1
-rw-r--r--tests/mir-opt/building/eq_never_type.rs1
-rw-r--r--tests/mir-opt/building/index_array_and_slice.rs47
-rw-r--r--tests/mir-opt/building/issue_101867.main.built.after.mir4
-rw-r--r--tests/mir-opt/building/issue_101867.rs1
-rw-r--r--tests/mir-opt/building/issue_110508.rs1
-rw-r--r--tests/mir-opt/building/issue_110508.{impl#0}-BAR.built.after.mir4
-rw-r--r--tests/mir-opt/building/issue_110508.{impl#0}-SELF_BAR.built.after.mir4
-rw-r--r--tests/mir-opt/building/issue_49232.rs1
-rw-r--r--tests/mir-opt/building/logical_or_in_conditional.rs2
-rw-r--r--tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir8
-rw-r--r--tests/mir-opt/building/receiver_ptr_mutability.rs1
-rw-r--r--tests/mir-opt/building/shifts.rs2
-rw-r--r--tests/mir-opt/building/storage_live_dead_in_statics.rs1
-rw-r--r--tests/mir-opt/building/uniform_array_move_out.rs1
-rw-r--r--tests/mir-opt/building/user_type_annotations.let_else.built.after.mir4
-rw-r--r--tests/mir-opt/building/user_type_annotations.let_else_bindless.built.after.mir4
-rw-r--r--tests/mir-opt/building/user_type_annotations.let_init.built.after.mir4
-rw-r--r--tests/mir-opt/building/user_type_annotations.let_init_bindless.built.after.mir4
-rw-r--r--tests/mir-opt/building/user_type_annotations.let_uninit.built.after.mir2
-rw-r--r--tests/mir-opt/building/user_type_annotations.let_uninit_bindless.built.after.mir2
-rw-r--r--tests/mir-opt/building/user_type_annotations.match_assoc_const.built.after.mir4
-rw-r--r--tests/mir-opt/building/user_type_annotations.match_assoc_const_range.built.after.mir8
-rw-r--r--tests/mir-opt/building/user_type_annotations.rs1
-rw-r--r--tests/run-make/rustdoc-default-output/output-default.stdout3
-rw-r--r--tests/rustdoc-gui/macro-expansion.goml126
-rw-r--r--tests/rustdoc-gui/sidebar-source-code.goml2
-rw-r--r--tests/rustdoc-gui/src/macro_expansion/Cargo.lock7
-rw-r--r--tests/rustdoc-gui/src/macro_expansion/Cargo.toml7
-rw-r--r--tests/rustdoc-gui/src/macro_expansion/lib.rs56
-rw-r--r--tests/rustdoc-gui/src/macro_expansion/other.rs6
-rw-r--r--tests/rustdoc-ui/lints/invalid-html-tags.rs94
-rw-r--r--tests/rustdoc-ui/lints/invalid-html-tags.stderr71
-rw-r--r--tests/rustdoc/attribute-rendering.rs3
-rw-r--r--tests/rustdoc/attributes.rs71
-rw-r--r--tests/rustdoc/enum/enum-variant-non_exhaustive.type-alias-code.html4
-rw-r--r--tests/rustdoc/enum/enum-variant-non_exhaustive.type-code.html4
-rw-r--r--tests/rustdoc/macro/macro_expansion.rs28
-rw-r--r--tests/rustdoc/type-alias/repr.rs3
-rw-r--r--tests/ui/abi/c-zst.powerpc-linux.stderr2
-rw-r--r--tests/ui/abi/c-zst.s390x-linux.stderr2
-rw-r--r--tests/ui/abi/c-zst.sparc64-linux.stderr2
-rw-r--r--tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr2
-rw-r--r--tests/ui/abi/debug.generic.stderr4
-rw-r--r--tests/ui/abi/debug.loongarch64.stderr4
-rw-r--r--tests/ui/abi/debug.riscv64.stderr4
-rw-r--r--tests/ui/associated-inherent-types/issue-111404-1.stderr6
-rw-r--r--tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr1
-rw-r--r--tests/ui/attributes/attr-on-mac-call.rs73
-rw-r--r--tests/ui/attributes/attr-on-mac-call.stderr205
-rw-r--r--tests/ui/attributes/crate-name-empty.stderr4
-rw-r--r--tests/ui/attributes/crate-name-macro-call.rs2
-rw-r--r--tests/ui/attributes/crate-name-macro-call.stderr8
-rw-r--r--tests/ui/attributes/crate-name-mismatch.stderr4
-rw-r--r--tests/ui/attributes/crate-only-as-outer.rs10
-rw-r--r--tests/ui/attributes/crate-only-as-outer.stderr26
-rw-r--r--tests/ui/attributes/malformed-attrs.rs3
-rw-r--r--tests/ui/attributes/malformed-attrs.stderr195
-rw-r--r--tests/ui/attributes/malformed-never-type-options.rs8
-rw-r--r--tests/ui/attributes/malformed-never-type-options.stderr19
-rw-r--r--tests/ui/binop/binops.rs1
-rw-r--r--tests/ui/c-variadic/issue-86053-1.stderr2
-rw-r--r--tests/ui/check-cfg/target_feature.stderr2
-rw-r--r--tests/ui/closures/issue-78720.stderr2
-rw-r--r--tests/ui/closures/issue-90871.stderr1
-rw-r--r--tests/ui/codegen/indirect-nocapture.rs15
-rw-r--r--tests/ui/coercion/fake-sized-ptr-cast.rs16
-rw-r--r--tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr5
-rw-r--r--tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr2
-rw-r--r--tests/ui/const-generics/type-dependent/issue-71348.full.stderr4
-rw-r--r--tests/ui/consts/issue-89088.stderr1
-rw-r--r--tests/ui/consts/ptr_comparisons.rs222
-rw-r--r--tests/ui/derives/deriving-meta-unknown-trait.stderr2
-rw-r--r--tests/ui/diagnostic-flags/colored-session-opt-error.rs4
-rw-r--r--tests/ui/did_you_mean/println-typo.stderr1
-rw-r--r--tests/ui/error-codes/E0458.rs2
-rw-r--r--tests/ui/error-codes/E0458.stderr29
-rw-r--r--tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs68
-rw-r--r--tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr623
-rw-r--r--tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.next.stderr24
-rw-r--r--tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.old.stderr2
-rw-r--r--tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.rs1
-rw-r--r--tests/ui/higher-ranked/higher-ranked-lifetime-error.stderr2
-rw-r--r--tests/ui/higher-ranked/trait-bounds/due-to-where-clause.stderr2
-rw-r--r--tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr14
-rw-r--r--tests/ui/impl-trait/auto-trait-selection.next.stderr14
-rw-r--r--tests/ui/impl-trait/call_method_without_import.no_import.stderr1
-rw-r--r--tests/ui/impl-trait/impl-generic-mismatch.stderr1
-rw-r--r--tests/ui/impl-trait/recursive-in-exhaustiveness.current.stderr2
-rw-r--r--tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr87
-rw-r--r--tests/ui/impl-trait/recursive-in-exhaustiveness.rs13
-rw-r--r--tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr4
-rw-r--r--tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr12
-rw-r--r--tests/ui/impl-trait/two_tait_defining_each_other2.rs3
-rw-r--r--tests/ui/imports/suggest-remove-issue-121315.stderr5
-rw-r--r--tests/ui/invalid-compile-flags/print-crate-name-request-malformed-crate-name.rs2
-rw-r--r--tests/ui/invalid-compile-flags/print-crate-name-request-malformed-crate-name.stderr8
-rw-r--r--tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-1.stderr5
-rw-r--r--tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-2.rs2
-rw-r--r--tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-2.stderr8
-rw-r--r--tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name.rs2
-rw-r--r--tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name.stderr8
-rw-r--r--tests/ui/issues/issue-17546.stderr4
-rw-r--r--tests/ui/issues/issue-27033.stderr1
-rw-r--r--tests/ui/issues/issue-29466.rs3
-rw-r--r--tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/example-from-issue48686.stderr4
-rw-r--r--tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/missing-lifetime-kind.stderr16
-rw-r--r--tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/not-tied-to-crate.stderr8
-rw-r--r--tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/static.stderr16
-rw-r--r--tests/ui/lifetimes/mismatched-lifetime-syntaxes.rs6
-rw-r--r--tests/ui/lifetimes/mismatched-lifetime-syntaxes.stderr153
-rw-r--r--tests/ui/limits/huge-enum.rs3
-rw-r--r--tests/ui/limits/huge-enum.stderr2
-rw-r--r--tests/ui/link-native-libs/issue-43925.rs4
-rw-r--r--tests/ui/link-native-libs/issue-43925.stderr14
-rw-r--r--tests/ui/link-native-libs/issue-43926.rs2
-rw-r--r--tests/ui/link-native-libs/issue-43926.stderr26
-rw-r--r--tests/ui/link-native-libs/link-attr-validation-early.rs6
-rw-r--r--tests/ui/link-native-libs/link-attr-validation-early.stderr62
-rw-r--r--tests/ui/link-native-libs/link-attr-validation-late.rs40
-rw-r--r--tests/ui/link-native-libs/link-attr-validation-late.stderr467
-rw-r--r--tests/ui/link-native-libs/modifiers-override-4.rs12
-rw-r--r--tests/ui/link-native-libs/modifiers-override-4.stderr67
-rw-r--r--tests/ui/link-native-libs/modifiers-override.rs5
-rw-r--r--tests/ui/link-native-libs/modifiers-override.stderr24
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.rs13
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.stderr26
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.rs13
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.stderr26
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.rs13
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.stderr26
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.rs11
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.stderr4
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.rs11
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.stderr2
-rw-r--r--tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs2
-rw-r--r--tests/ui/lint/inert-attr-macro.rs11
-rw-r--r--tests/ui/lint/inert-attr-macro.stderr38
-rw-r--r--tests/ui/lint/int_to_ptr-unsized.rs23
-rw-r--r--tests/ui/lint/int_to_ptr-unsized.stderr27
-rw-r--r--tests/ui/lint/int_to_ptr.fixed47
-rw-r--r--tests/ui/lint/int_to_ptr.rs47
-rw-r--r--tests/ui/lint/int_to_ptr.stderr207
-rw-r--r--tests/ui/lint/linker-warning.stderr6
-rw-r--r--tests/ui/lint/lint-misplaced-attr.stderr7
-rw-r--r--tests/ui/lint/unused/concat-in-crate-deprecated-issue-137687.rs6
-rw-r--r--tests/ui/lint/unused/concat-in-crate-name-issue-137687.rs9
-rw-r--r--tests/ui/lint/unused/concat-in-crate-name-issue-137687.stderr31
-rw-r--r--tests/ui/lint/unused/unused-attr-duplicate.rs8
-rw-r--r--tests/ui/lint/unused/unused-attr-duplicate.stderr130
-rw-r--r--tests/ui/lint/unused/unused-attr-macro-rules.stderr6
-rw-r--r--tests/ui/lint/unused/unused_attributes-must_use.fixed3
-rw-r--r--tests/ui/lint/unused/unused_attributes-must_use.rs4
-rw-r--r--tests/ui/lint/unused/unused_attributes-must_use.stderr49
-rw-r--r--tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr2
-rw-r--r--tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.stderr5
-rw-r--r--tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.stderr3
-rw-r--r--tests/ui/macros/format-foreign-dollar-without-spec.rs5
-rw-r--r--tests/ui/macros/format-foreign-dollar-without-spec.stderr16
-rw-r--r--tests/ui/macros/macro-name-typo.stderr1
-rw-r--r--tests/ui/macros/macro-path-prelude-fail-3.stderr1
-rw-r--r--tests/ui/macros/missing-writer-issue-139830.stderr2
-rw-r--r--tests/ui/malformed/malformed-regressions.rs6
-rw-r--r--tests/ui/malformed/malformed-regressions.stderr65
-rw-r--r--tests/ui/methods/method-call-lifetime-args-unresolved.stderr1
-rw-r--r--tests/ui/methods/rigid-alias-bound-is-not-inherent-2.rs17
-rw-r--r--tests/ui/methods/rigid-alias-bound-is-not-inherent-2.stderr17
-rw-r--r--tests/ui/methods/rigid-alias-bound-is-not-inherent-3.rs26
-rw-r--r--tests/ui/methods/rigid-alias-bound-is-not-inherent-3.stderr30
-rw-r--r--tests/ui/methods/rigid-alias-bound-is-not-inherent.current.stderr30
-rw-r--r--tests/ui/methods/rigid-alias-bound-is-not-inherent.next.stderr30
-rw-r--r--tests/ui/methods/rigid-alias-bound-is-not-inherent.rs46
-rw-r--r--tests/ui/mir/validate/ice-zst-as-discr-145786.rs14
-rw-r--r--tests/ui/mir/validate/ice-zst-as-discr-145786.stderr12
-rw-r--r--tests/ui/mismatched_types/hr-projection-mismatch.current.stderr2
-rw-r--r--tests/ui/nll/ice-106874.stderr35
-rw-r--r--tests/ui/nll/missing-universe-cause-issue-114907.stderr6
-rw-r--r--tests/ui/or-patterns/exhaustiveness-non-exhaustive.rs4
-rw-r--r--tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr12
-rw-r--r--tests/ui/panics/issue-47429-short-backtraces.rs3
-rw-r--r--tests/ui/panics/issue-47429-short-backtraces.run.stderr2
-rw-r--r--tests/ui/panics/runtime-switch.rs3
-rw-r--r--tests/ui/panics/runtime-switch.run.stderr2
-rw-r--r--tests/ui/parallel-rustc/cache-after-waiting-issue-111528.rs14
-rw-r--r--tests/ui/parallel-rustc/cache-after-waiting-issue-111528.stderr2
-rw-r--r--tests/ui/parallel-rustc/cycle_crash-issue-135870.rs8
-rw-r--r--tests/ui/parallel-rustc/cycle_crash-issue-135870.stderr (renamed from tests/ui/parallel-rustc/cycle_crash.stderr)4
-rw-r--r--tests/ui/parallel-rustc/cycle_crash.rs5
-rw-r--r--tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205-2.rs4
-rw-r--r--tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205.rs3
-rw-r--r--tests/ui/parallel-rustc/hello_world.rs3
-rw-r--r--tests/ui/parallel-rustc/read-stolen-value-issue-111520.rs11
-rw-r--r--tests/ui/parallel-rustc/ty-variance-issue-124423.rs58
-rw-r--r--tests/ui/parallel-rustc/ty-variance-issue-124423.stderr287
-rw-r--r--tests/ui/parallel-rustc/ty-variance-issue-127971.rs25
-rw-r--r--tests/ui/parallel-rustc/ty-variance-issue-127971.stderr113
-rw-r--r--tests/ui/parallel-rustc/undefined-function-issue-120760.rs71
-rw-r--r--tests/ui/parallel-rustc/undefined-function-issue-120760.stderr35
-rw-r--r--tests/ui/parallel-rustc/unexpected-type-issue-120601.rs28
-rw-r--r--tests/ui/parallel-rustc/unexpected-type-issue-120601.stderr52
-rw-r--r--tests/ui/parser/bad-lit-suffixes.rs1
-rw-r--r--tests/ui/parser/bad-lit-suffixes.stderr43
-rw-r--r--tests/ui/parser/misspelled-keywords/ref.stderr1
-rw-r--r--tests/ui/parser/recover/recover-pat-exprs.stderr1
-rw-r--r--tests/ui/pattern/deref-patterns/implicit-const-deref.stderr1
-rw-r--r--tests/ui/pattern/issue-115599.stderr1
-rw-r--r--tests/ui/privacy/suggest-box-new.stderr2
-rw-r--r--tests/ui/proc-macro/parent-source-spans.stderr3
-rw-r--r--tests/ui/proc-macro/resolve-error.stderr2
-rw-r--r--tests/ui/resolve/issue-102946.rs1
-rw-r--r--tests/ui/resolve/levenshtein.stderr1
-rw-r--r--tests/ui/resolve/path-attr-in-const-block.rs1
-rw-r--r--tests/ui/resolve/path-attr-in-const-block.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2091-track-caller/file-is-nul-terminated.rs6
-rw-r--r--tests/ui/sanitize-attr/invalid-sanitize.rs9
-rw-r--r--tests/ui/sanitize-attr/invalid-sanitize.stderr115
-rw-r--r--tests/ui/self/elision/ignore-non-reference-lifetimes.stderr8
-rw-r--r--tests/ui/self/self_lifetime-async.stderr8
-rw-r--r--tests/ui/self/self_lifetime.stderr8
-rw-r--r--tests/ui/suggestions/attribute-typos.stderr1
-rw-r--r--tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr1
-rw-r--r--tests/ui/suggestions/enum-method-probe.stderr2
-rw-r--r--tests/ui/suggestions/import-trait-for-method-call.stderr1
-rw-r--r--tests/ui/suggestions/multi-suggestion.ascii.stderr2
-rw-r--r--tests/ui/suggestions/multi-suggestion.unicode.stderr4
-rw-r--r--tests/ui/suggestions/suggest-tryinto-edition-change.stderr1
-rw-r--r--tests/ui/suggestions/use-parentheses-to-call-closure-issue-145404.fixed13
-rw-r--r--tests/ui/suggestions/use-parentheses-to-call-closure-issue-145404.rs13
-rw-r--r--tests/ui/suggestions/use-parentheses-to-call-closure-issue-145404.stderr23
-rw-r--r--tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr9
-rw-r--r--tests/ui/traits/const-traits/constructor-const-fn.rs15
-rw-r--r--tests/ui/traits/const-traits/reservation-impl-ice.rs13
-rw-r--r--tests/ui/traits/const-traits/reservation-impl-ice.stderr25
-rw-r--r--tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.next.stderr8
-rw-r--r--tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.rs2
-rw-r--r--tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-3.next.stderr10
-rw-r--r--tests/ui/traits/next-solver/opaques/different-bound-vars.current.stderr14
-rw-r--r--tests/ui/traits/next-solver/opaques/different-bound-vars.rs20
-rw-r--r--tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.is_send.stderr17
-rw-r--r--tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.not_send.stderr17
-rw-r--r--tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.rs2
-rw-r--r--tests/ui/traits/next-solver/opaques/non-defining-use-hir-typeck.rs28
-rw-r--r--tests/ui/traits/next-solver/opaques/universal-args-non-defining.rs16
-rw-r--r--tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr23
-rw-r--r--tests/ui/type-alias-impl-trait/constrain_in_projection2.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/generic_nondefining_use.current.stderr (renamed from tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr)6
-rw-r--r--tests/ui/type-alias-impl-trait/generic_nondefining_use.next.stderr44
-rw-r--r--tests/ui/type-alias-impl-trait/generic_nondefining_use.rs14
-rw-r--r--tests/ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs6
-rw-r--r--tests/ui/type-alias-impl-trait/normalize-args-before-defining-use-check.rs33
-rw-r--r--tests/ui/type/issue-7607-1.stderr1
-rw-r--r--tests/ui/typeck/issue-83693.stderr1
-rw-r--r--tests/ui/ufcs/ufcs-partially-resolved.stderr8
-rw-r--r--tests/ui/wasm/wasm-import-module.rs6
-rw-r--r--tests/ui/wasm/wasm-import-module.stderr76
725 files changed, 13169 insertions, 7131 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 71ae559bd12..8b9c243879c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -266,9 +266,9 @@ dependencies = [
 
 [[package]]
 name = "bitflags"
-version = "2.9.2"
+version = "2.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a65b545ab31d687cff52899d4890855fec459eb6afe0da6417b8a18da87aa29"
+checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d"
 
 [[package]]
 name = "blake3"
@@ -315,7 +315,7 @@ dependencies = [
  "serde_json",
  "sha2",
  "tar",
- "toml 0.5.11",
+ "toml 0.7.8",
  "xz2",
 ]
 
@@ -336,7 +336,7 @@ dependencies = [
  "curl",
  "indexmap",
  "serde",
- "toml 0.5.11",
+ "toml 0.7.8",
 ]
 
 [[package]]
@@ -1129,16 +1129,16 @@ version = "6.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d"
 dependencies = [
- "dirs-sys 0.5.0",
+ "dirs-sys",
 ]
 
 [[package]]
 name = "dirs"
-version = "5.0.1"
+version = "6.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
+checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e"
 dependencies = [
- "dirs-sys 0.4.1",
+ "dirs-sys",
 ]
 
 [[package]]
@@ -1153,18 +1153,6 @@ dependencies = [
 
 [[package]]
 name = "dirs-sys"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
-dependencies = [
- "libc",
- "option-ext",
- "redox_users 0.4.6",
- "windows-sys 0.48.0",
-]
-
-[[package]]
-name = "dirs-sys"
 version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab"
@@ -1686,76 +1674,59 @@ checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47"
 dependencies = [
  "displaydoc",
  "potential_utf",
- "yoke 0.8.0",
+ "yoke",
  "zerofrom",
- "zerovec 0.11.4",
+ "zerovec",
 ]
 
 [[package]]
 name = "icu_list"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbfeda1d7775b6548edd4e8b7562304a559a91ed56ab56e18961a053f367c365"
-dependencies = [
- "displaydoc",
- "icu_list_data",
- "icu_locid_transform",
- "icu_provider 1.5.0",
- "regex-automata 0.2.0",
- "writeable 0.5.5",
-]
-
-[[package]]
-name = "icu_list_data"
-version = "1.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52b1a7fbdbf3958f1be8354cb59ac73f165b7b7082d447ff2090355c9a069120"
-
-[[package]]
-name = "icu_locale_core"
 version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a"
+checksum = "e26f94ec776bb8b28cedc7dcf91033b822c5cb4c1783cf7a3f796fc168aa0c8b"
 dependencies = [
  "displaydoc",
- "litemap 0.8.0",
- "tinystr 0.8.1",
- "writeable 0.6.1",
- "zerovec 0.11.4",
+ "icu_provider",
+ "regex-automata 0.4.9",
+ "serde",
+ "writeable",
+ "zerovec",
 ]
 
 [[package]]
-name = "icu_locid"
-version = "1.5.0"
+name = "icu_locale"
+version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637"
+checksum = "6ae5921528335e91da1b6c695dbf1ec37df5ac13faa3f91e5640be93aa2fbefd"
 dependencies = [
  "displaydoc",
- "litemap 0.7.5",
- "tinystr 0.7.6",
- "writeable 0.5.5",
- "zerovec 0.10.4",
+ "icu_collections",
+ "icu_locale_core",
+ "icu_locale_data",
+ "icu_provider",
+ "potential_utf",
+ "tinystr",
+ "zerovec",
 ]
 
 [[package]]
-name = "icu_locid_transform"
-version = "1.5.0"
+name = "icu_locale_core"
+version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e"
+checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a"
 dependencies = [
  "displaydoc",
- "icu_locid",
- "icu_locid_transform_data",
- "icu_provider 1.5.0",
- "tinystr 0.7.6",
- "zerovec 0.10.4",
+ "litemap",
+ "tinystr",
+ "writeable",
+ "zerovec",
 ]
 
 [[package]]
-name = "icu_locid_transform_data"
-version = "1.5.1"
+name = "icu_locale_data"
+version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d"
+checksum = "4fdef0c124749d06a743c69e938350816554eb63ac979166590e2b4ee4252765"
 
 [[package]]
 name = "icu_normalizer"
@@ -1767,9 +1738,9 @@ dependencies = [
  "icu_collections",
  "icu_normalizer_data",
  "icu_properties",
- "icu_provider 2.0.0",
+ "icu_provider",
  "smallvec",
- "zerovec 0.11.4",
+ "zerovec",
 ]
 
 [[package]]
@@ -1788,10 +1759,10 @@ dependencies = [
  "icu_collections",
  "icu_locale_core",
  "icu_properties_data",
- "icu_provider 2.0.0",
+ "icu_provider",
  "potential_utf",
  "zerotrie",
- "zerovec 0.11.4",
+ "zerovec",
 ]
 
 [[package]]
@@ -1802,23 +1773,6 @@ checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632"
 
 [[package]]
 name = "icu_provider"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9"
-dependencies = [
- "displaydoc",
- "icu_locid",
- "icu_provider_macros",
- "stable_deref_trait",
- "tinystr 0.7.6",
- "writeable 0.5.5",
- "yoke 0.7.5",
- "zerofrom",
- "zerovec 0.10.4",
-]
-
-[[package]]
-name = "icu_provider"
 version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af"
@@ -1826,36 +1780,12 @@ dependencies = [
  "displaydoc",
  "icu_locale_core",
  "stable_deref_trait",
- "tinystr 0.8.1",
- "writeable 0.6.1",
- "yoke 0.8.0",
+ "tinystr",
+ "writeable",
+ "yoke",
  "zerofrom",
  "zerotrie",
- "zerovec 0.11.4",
-]
-
-[[package]]
-name = "icu_provider_adapters"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d6324dfd08348a8e0374a447ebd334044d766b1839bb8d5ccf2482a99a77c0bc"
-dependencies = [
- "icu_locid",
- "icu_locid_transform",
- "icu_provider 1.5.0",
- "tinystr 0.7.6",
- "zerovec 0.10.4",
-]
-
-[[package]]
-name = "icu_provider_macros"
-version = "1.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.106",
+ "zerovec",
 ]
 
 [[package]]
@@ -2257,12 +2187,6 @@ checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12"
 
 [[package]]
 name = "litemap"
-version = "0.7.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856"
-
-[[package]]
-name = "litemap"
 version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
@@ -2971,7 +2895,8 @@ version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585"
 dependencies = [
- "zerovec 0.11.4",
+ "serde",
+ "zerovec",
 ]
 
 [[package]]
@@ -3219,15 +3144,6 @@ dependencies = [
 
 [[package]]
 name = "regex-automata"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e9368763f5a9b804326f3af749e16f9abf378d227bcdee7634b13d8f17793782"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "regex-automata"
 version = "0.4.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
@@ -3492,6 +3408,7 @@ dependencies = [
  "rustc_parse",
  "rustc_session",
  "rustc_span",
+ "rustc_target",
  "thin-vec",
 ]
 
@@ -3500,10 +3417,9 @@ name = "rustc_baked_icu_data"
 version = "0.0.0"
 dependencies = [
  "icu_list",
- "icu_locid",
- "icu_locid_transform",
- "icu_provider 1.5.0",
- "zerovec 0.10.4",
+ "icu_locale",
+ "icu_provider",
+ "zerovec",
 ]
 
 [[package]]
@@ -3776,8 +3692,7 @@ dependencies = [
  "fluent-bundle",
  "fluent-syntax",
  "icu_list",
- "icu_locid",
- "icu_provider_adapters",
+ "icu_locale",
  "intl-memoizer",
  "rustc_ast",
  "rustc_ast_pretty",
@@ -3803,7 +3718,6 @@ dependencies = [
  "rustc_error_messages",
  "rustc_fluent_macro",
  "rustc_hashes",
- "rustc_hir_id",
  "rustc_index",
  "rustc_lexer",
  "rustc_lint_defs",
@@ -5512,22 +5426,12 @@ dependencies = [
 
 [[package]]
 name = "tinystr"
-version = "0.7.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f"
-dependencies = [
- "displaydoc",
- "zerovec 0.10.4",
-]
-
-[[package]]
-name = "tinystr"
 version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b"
 dependencies = [
  "displaydoc",
- "zerovec 0.11.4",
+ "zerovec",
 ]
 
 [[package]]
@@ -5547,15 +5451,6 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
 
 [[package]]
 name = "toml"
-version = "0.5.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "toml"
 version = "0.7.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257"
@@ -5801,7 +5696,7 @@ version = "0.9.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dce1bf08044d4b7a94028c93786f8566047edc11110595914de93362559bc658"
 dependencies = [
- "tinystr 0.8.1",
+ "tinystr",
 ]
 
 [[package]]
@@ -5811,7 +5706,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d5957eb82e346d7add14182a3315a7e298f04e1ba4baac36f7f0dbfedba5fc25"
 dependencies = [
  "proc-macro-hack",
- "tinystr 0.8.1",
+ "tinystr",
  "unic-langid-impl",
  "unic-langid-macros-impl",
 ]
@@ -6010,9 +5905,9 @@ dependencies = [
 
 [[package]]
 name = "wasi-preview1-component-adapter-provider"
-version = "34.0.2"
+version = "36.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33696c5f1ff1e083de9f36c3da471abd736362bc173e093f8b0b1ed5a387e39b"
+checksum = "20689c88791776219f78c2529700d15e6a9bd57a27858c62e9ef8487956b571c"
 
 [[package]]
 name = "wasm-bindgen"
@@ -6074,9 +5969,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-component-ld"
-version = "0.5.15"
+version = "0.5.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d95124e34fee1316222e03b9bbf41af186ecbae2c8b79f8debe6e21b3ff60c5"
+checksum = "14cd35d6cae91109a0ffd207b573cf3c741cab7e921dd376ea7aaf2c52a3408c"
 dependencies = [
  "anyhow",
  "clap",
@@ -6084,7 +5979,7 @@ dependencies = [
  "libc",
  "tempfile",
  "wasi-preview1-component-adapter-provider",
- "wasmparser 0.234.0",
+ "wasmparser 0.237.0",
  "wat",
  "windows-sys 0.59.0",
  "winsplit",
@@ -6111,34 +6006,24 @@ dependencies = [
 
 [[package]]
 name = "wasm-encoder"
-version = "0.234.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "170a0157eef517a179f2d20ed7c68df9c3f7f6c1c047782d488bf5a464174684"
-dependencies = [
- "leb128fmt",
- "wasmparser 0.234.0",
-]
-
-[[package]]
-name = "wasm-encoder"
-version = "0.236.1"
+version = "0.237.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "724fccfd4f3c24b7e589d333fc0429c68042897a7e8a5f8694f31792471841e7"
+checksum = "efe92d1321afa53ffc88a57c497bb7330c3cf84c98ffdba4a4caf6a0684fad3c"
 dependencies = [
  "leb128fmt",
- "wasmparser 0.236.1",
+ "wasmparser 0.237.0",
 ]
 
 [[package]]
 name = "wasm-metadata"
-version = "0.234.0"
+version = "0.237.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a42fe3f5cbfb56fc65311ef827930d06189160038e81db62188f66b4bf468e3a"
+checksum = "4cc0b0a0c4f35ca6efa7a797671372915d4e9659dba2d59edc6fafc931d19997"
 dependencies = [
  "anyhow",
  "indexmap",
- "wasm-encoder 0.234.0",
- "wasmparser 0.234.0",
+ "wasm-encoder 0.237.0",
+ "wasmparser 0.237.0",
 ]
 
 [[package]]
@@ -6153,46 +6038,45 @@ dependencies = [
 
 [[package]]
 name = "wasmparser"
-version = "0.234.0"
+version = "0.236.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be22e5a8f600afce671dd53c8d2dd26b4b7aa810fd18ae27dfc49737f3e02fc5"
+checksum = "a9b1e81f3eb254cf7404a82cee6926a4a3ccc5aad80cc3d43608a070c67aa1d7"
 dependencies = [
  "bitflags",
- "hashbrown",
  "indexmap",
- "semver",
- "serde",
 ]
 
 [[package]]
 name = "wasmparser"
-version = "0.236.1"
+version = "0.237.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9b1e81f3eb254cf7404a82cee6926a4a3ccc5aad80cc3d43608a070c67aa1d7"
+checksum = "7d2a40ca0d2bdf4b0bf36c13a737d0b2c58e4c8aaefe1c57f336dd75369ca250"
 dependencies = [
  "bitflags",
+ "hashbrown",
  "indexmap",
  "semver",
+ "serde",
 ]
 
 [[package]]
 name = "wast"
-version = "236.0.1"
+version = "237.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3bec4b4db9c6808d394632fd4b0cd4654c32c540bd3237f55ee6a40fff6e51f"
+checksum = "fcf66f545acbd55082485cb9a6daab54579cb8628a027162253e8e9f5963c767"
 dependencies = [
  "bumpalo",
  "leb128fmt",
  "memchr",
  "unicode-width 0.2.1",
- "wasm-encoder 0.236.1",
+ "wasm-encoder 0.237.0",
 ]
 
 [[package]]
 name = "wat"
-version = "1.236.1"
+version = "1.237.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64475e2f77d6071ce90624098fc236285ddafa8c3ea1fb386f2c4154b6c2bbdb"
+checksum = "27975186f549e4b8d6878b627be732863883c72f7bf4dcf8f96e5f8242f73da9"
 dependencies = [
  "wast",
 ]
@@ -6681,9 +6565,9 @@ dependencies = [
 
 [[package]]
 name = "wit-component"
-version = "0.234.0"
+version = "0.237.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a8888169acf4c6c4db535beb405b570eedac13215d6821ca9bd03190f7f8b8c"
+checksum = "bfb7674f76c10e82fe00b256a9d4ffb2b8d037d42ab8e9a83ebb3be35c9d0bf6"
 dependencies = [
  "anyhow",
  "bitflags",
@@ -6692,17 +6576,17 @@ dependencies = [
  "serde",
  "serde_derive",
  "serde_json",
- "wasm-encoder 0.234.0",
+ "wasm-encoder 0.237.0",
  "wasm-metadata",
- "wasmparser 0.234.0",
+ "wasmparser 0.237.0",
  "wit-parser",
 ]
 
 [[package]]
 name = "wit-parser"
-version = "0.234.0"
+version = "0.237.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "465492df47d8dcc015a3b7f241aed8ea03688fee7c5e04162285c5b1a3539c8b"
+checksum = "ce2596a5bc7c24cc965b56ad6ff9e32394c4e401764f89620a888519c6e849ab"
 dependencies = [
  "anyhow",
  "id-arena",
@@ -6713,17 +6597,11 @@ dependencies = [
  "serde_derive",
  "serde_json",
  "unicode-xid",
- "wasmparser 0.234.0",
+ "wasmparser 0.237.0",
 ]
 
 [[package]]
 name = "writeable"
-version = "0.5.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51"
-
-[[package]]
-name = "writeable"
 version = "0.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb"
@@ -6762,42 +6640,18 @@ dependencies = [
 
 [[package]]
 name = "yoke"
-version = "0.7.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40"
-dependencies = [
- "serde",
- "stable_deref_trait",
- "yoke-derive 0.7.5",
- "zerofrom",
-]
-
-[[package]]
-name = "yoke"
 version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc"
 dependencies = [
  "serde",
  "stable_deref_trait",
- "yoke-derive 0.8.0",
+ "yoke-derive",
  "zerofrom",
 ]
 
 [[package]]
 name = "yoke-derive"
-version = "0.7.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.106",
- "synstructure",
-]
-
-[[package]]
-name = "yoke-derive"
 version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6"
@@ -6856,19 +6710,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595"
 dependencies = [
  "displaydoc",
- "yoke 0.8.0",
- "zerofrom",
-]
-
-[[package]]
-name = "zerovec"
-version = "0.10.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079"
-dependencies = [
- "yoke 0.7.5",
+ "yoke",
  "zerofrom",
- "zerovec-derive 0.10.3",
 ]
 
 [[package]]
@@ -6877,20 +6720,9 @@ version = "0.11.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b"
 dependencies = [
- "yoke 0.8.0",
+ "yoke",
  "zerofrom",
- "zerovec-derive 0.11.1",
-]
-
-[[package]]
-name = "zerovec-derive"
-version = "0.10.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn 2.0.106",
+ "zerovec-derive",
 ]
 
 [[package]]
diff --git a/Cargo.toml b/Cargo.toml
index 67c7a9d67ed..5003e107cc8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -59,6 +59,16 @@ exclude = [
   "obj",
 ]
 
+[workspace.dependencies]
+# tidy-alphabetical-start
+bitflags = "2.9.3"
+itertools = "0.12.1"
+memchr = "2.7.5"
+rustc-literal-escaper = "0.0.5"
+thin-vec = "0.2.14"
+tracing = "0.1.37"
+# tidy-alphabetical-end
+
 [profile.release.package.rustc_thread_pool]
 # The rustc fork of Rayon has deadlock detection code which intermittently
 # causes overflows in the CI (see https://github.com/rust-lang/rust/issues/90227)
diff --git a/bootstrap.example.toml b/bootstrap.example.toml
index 4c18d5f8675..16fd9241a17 100644
--- a/bootstrap.example.toml
+++ b/bootstrap.example.toml
@@ -407,8 +407,11 @@
 #build.profiler = false
 
 # Use the optimized LLVM C intrinsics for `compiler_builtins`, rather than Rust intrinsics.
-# Requires the LLVM submodule to be managed by bootstrap (i.e. not external) so that `compiler-rt`
-# sources are available.
+# Choosing true requires the LLVM submodule to be managed by bootstrap (i.e. not external)
+# so that `compiler-rt` sources are available.
+#
+# Setting this to a path removes the requirement for a C toolchain, but requires setting the
+# path to an existing library containing the builtins library from LLVM's compiler-rt.
 #
 # Setting this to `false` generates slower code, but removes the requirement for a C toolchain in
 # order to run `x check`.
@@ -1041,13 +1044,15 @@
 #runner = <none> (string)
 
 # Use the optimized LLVM C intrinsics for `compiler_builtins`, rather than Rust intrinsics
-# on this target.
-# Requires the LLVM submodule to be managed by bootstrap (i.e. not external) so that `compiler-rt`
-# sources are available.
+# on this target. Choosing true requires the LLVM submodule to be managed by bootstrap
+# (i.e. not external) so that `compiler-rt` sources are available.
+#
+# Setting this to a path removes the requirement for a C toolchain, but requires setting the
+# path to an existing library containing the builtins library from LLVM's compiler-rt.
 #
 # Setting this to `false` generates slower code, but removes the requirement for a C toolchain in
 # order to run `x check`.
-#optimized-compiler-builtins = build.optimized-compiler-builtins (bool)
+#optimized-compiler-builtins = build.optimized-compiler-builtins (bool or path)
 
 # Link the compiler and LLVM against `jemalloc` instead of the default libc allocator.
 # This overrides the global `rust.jemalloc` option. See that option for more info.
diff --git a/compiler/rustc_abi/Cargo.toml b/compiler/rustc_abi/Cargo.toml
index 83d96d8d04d..3de6d186b8a 100644
--- a/compiler/rustc_abi/Cargo.toml
+++ b/compiler/rustc_abi/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
-bitflags = "2.4.1"
+bitflags.workspace = true
 rand = { version = "0.9.0", default-features = false, optional = true }
 rand_xoshiro = { version = "0.7.0", optional = true }
 rustc_data_structures = { path = "../rustc_data_structures", optional = true }
@@ -15,7 +15,7 @@ rustc_index = { path = "../rustc_index", default-features = false }
 rustc_macros = { path = "../rustc_macros", optional = true }
 rustc_serialize = { path = "../rustc_serialize", optional = true }
 rustc_span = { path = "../rustc_span", optional = true }
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
 
 [features]
diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml
index 155e14a3796..0b8ab7c391c 100644
--- a/compiler/rustc_ast/Cargo.toml
+++ b/compiler/rustc_ast/Cargo.toml
@@ -5,9 +5,9 @@ edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
-bitflags = "2.4.1"
-memchr = "2.7.4"
-rustc-literal-escaper = "0.0.5"
+bitflags.workspace = true
+memchr.workspace = true
+rustc-literal-escaper.workspace = true
 rustc_ast_ir = { path = "../rustc_ast_ir" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_index = { path = "../rustc_index" }
@@ -15,6 +15,6 @@ rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_span = { path = "../rustc_span" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.12"
+thin-vec.workspace = true
 tracing = "0.1"
 # tidy-alphabetical-end
diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml
index 6ac258155fe..317742a3bb8 100644
--- a/compiler/rustc_ast_lowering/Cargo.toml
+++ b/compiler/rustc_ast_lowering/Cargo.toml
@@ -24,6 +24,6 @@ rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.12"
-tracing = "0.1"
+thin-vec.workspace = true
+tracing.workspace = true
 # tidy-alphabetical-end
diff --git a/compiler/rustc_ast_passes/Cargo.toml b/compiler/rustc_ast_passes/Cargo.toml
index 3e04f8b11ec..6d2bcbed22b 100644
--- a/compiler/rustc_ast_passes/Cargo.toml
+++ b/compiler/rustc_ast_passes/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
-itertools = "0.12"
+itertools.workspace = true
 rustc_abi = { path = "../rustc_abi" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
@@ -18,5 +18,5 @@ rustc_macros = { path = "../rustc_macros" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
-thin-vec = "0.2.12"
+thin-vec.workspace = true
 # tidy-alphabetical-end
diff --git a/compiler/rustc_ast_pretty/Cargo.toml b/compiler/rustc_ast_pretty/Cargo.toml
index b704040be96..0c7e55305b4 100644
--- a/compiler/rustc_ast_pretty/Cargo.toml
+++ b/compiler/rustc_ast_pretty/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
-itertools = "0.12"
+itertools.workspace = true
 rustc_ast = { path = "../rustc_ast" }
 rustc_lexer = { path = "../rustc_lexer" }
 rustc_span = { path = "../rustc_span" }
@@ -13,5 +13,5 @@ rustc_span = { path = "../rustc_span" }
 
 [dev-dependencies]
 # tidy-alphabetical-start
-thin-vec = "0.2.12"
+thin-vec.workspace = true
 # tidy-alphabetical-end
diff --git a/compiler/rustc_attr_parsing/Cargo.toml b/compiler/rustc_attr_parsing/Cargo.toml
index fd8f7ffb2ed..8bfde43fd33 100644
--- a/compiler/rustc_attr_parsing/Cargo.toml
+++ b/compiler/rustc_attr_parsing/Cargo.toml
@@ -17,5 +17,6 @@ rustc_macros = { path = "../rustc_macros" }
 rustc_parse = { path = "../rustc_parse" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
-thin-vec = "0.2.12"
+rustc_target = { path = "../rustc_target" }
+thin-vec.workspace = true
 # tidy-alphabetical-end
diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl
index 40e9d597530..b8a748563d5 100644
--- a/compiler/rustc_attr_parsing/messages.ftl
+++ b/compiler/rustc_attr_parsing/messages.ftl
@@ -86,6 +86,12 @@ attr_parsing_invalid_repr_hint_no_value =
 attr_parsing_invalid_since =
     'since' must be a Rust version number, such as "1.31.0"
 
+attr_parsing_invalid_style = {$is_used_as_inner ->
+        [false] crate-level attribute should be an inner attribute: add an exclamation mark: `#![{$name}]`
+        *[other] the `#![{$name}]` attribute can only be used at the crate root
+    }
+    .note = This attribute does not have an `!`, which means it is applied to this {$target}
+
 attr_parsing_link_ordinal_out_of_range = ordinal value in `link_ordinal` is too large: `{$ordinal}`
     .note = the value may not exceed `u16::MAX`
 
@@ -189,3 +195,55 @@ attr_parsing_invalid_meta_item = expected a literal (`1u8`, `1.0f32`, `"string"`
 
 attr_parsing_suffixed_literal_in_attribute = suffixed literals are not allowed in attributes
     .help = instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)
+
+attr_parsing_as_needed_compatibility =
+    linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds
+
+attr_parsing_bundle_needs_static =
+    linking modifier `bundle` is only compatible with `static` linking kind
+
+attr_parsing_empty_link_name =
+    link name must not be empty
+    .label = empty link name
+
+attr_parsing_import_name_type_raw =
+    import name type can only be used with link kind `raw-dylib`
+
+attr_parsing_import_name_type_x86 =
+    import name type is only supported on x86
+
+attr_parsing_incompatible_wasm_link =
+    `wasm_import_module` is incompatible with other arguments in `#[link]` attributes
+
+attr_parsing_invalid_link_modifier =
+    invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
+
+attr_parsing_link_arg_unstable =
+    link kind `link-arg` is unstable
+
+attr_parsing_link_cfg_unstable =
+    link cfg is unstable
+
+attr_parsing_link_framework_apple =
+    link kind `framework` is only supported on Apple targets
+
+attr_parsing_link_requires_name =
+    `#[link]` attribute requires a `name = "string"` argument
+    .label = missing `name` argument
+
+attr_parsing_multiple_modifiers =
+    multiple `{$modifier}` modifiers in a single `modifiers` argument
+
+attr_parsing_multiple_renamings =
+    multiple renamings were specified for library `{$lib_name}`
+attr_parsing_raw_dylib_no_nul =
+    link name must not contain NUL characters if link kind is `raw-dylib`
+
+attr_parsing_raw_dylib_elf_unstable =
+    link kind `raw-dylib` is unstable on ELF platforms
+
+attr_parsing_raw_dylib_only_windows =
+    link kind `raw-dylib` is only supported on Windows targets
+
+attr_parsing_whole_archive_needs_static =
+    linking modifier `whole-archive` is only compatible with `static` linking kind
diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs
index 695ee666476..70855611079 100644
--- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs
@@ -36,7 +36,7 @@ pub fn parse_cfg_attr<'c, S: Stage>(
     parse_cfg_entry(cx, single)
 }
 
-fn parse_cfg_entry<S: Stage>(
+pub(crate) fn parse_cfg_entry<S: Stage>(
     cx: &mut AcceptContext<'_, '_, S>,
     item: &MetaItemOrLitParser<'_>,
 ) -> Option<CfgEntry> {
diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
index 91053811a0b..ffdacff7152 100644
--- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs
@@ -1,4 +1,4 @@
-use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, UsedBy};
+use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, SanitizerSet, UsedBy};
 use rustc_session::parse::feature_err;
 
 use super::prelude::*;
@@ -127,6 +127,7 @@ impl<S: Stage> SingleAttributeParser<S> for ExportNameParser {
         Warn(Target::Field),
         Warn(Target::Arm),
         Warn(Target::MacroDef),
+        Warn(Target::MacroCall),
     ]);
     const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
 
@@ -174,6 +175,7 @@ impl<S: Stage> AttributeParser<S> for NakedParser {
         Allow(Target::Method(MethodKind::Inherent)),
         Allow(Target::Method(MethodKind::Trait { body: true })),
         Allow(Target::Method(MethodKind::TraitImpl)),
+        Warn(Target::MacroCall),
     ]);
 
     fn finalize(self, cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
@@ -278,6 +280,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for TrackCallerParser {
         Warn(Target::MacroDef),
         Warn(Target::Arm),
         Warn(Target::Field),
+        Warn(Target::MacroCall),
     ]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::TrackCaller;
 }
@@ -365,7 +368,8 @@ impl<S: Stage> AttributeParser<S> for UsedParser {
             }
         },
     )];
-    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Static)]);
+    const ALLOWED_TARGETS: AllowedTargets =
+        AllowedTargets::AllowList(&[Allow(Target::Static), Warn(Target::MacroCall)]);
 
     fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
         // Ratcheting behaviour, if both `linker` and `compiler` are specified, use `linker`
@@ -450,6 +454,7 @@ impl<S: Stage> CombineAttributeParser<S> for TargetFeatureParser {
         Warn(Target::Field),
         Warn(Target::Arm),
         Warn(Target::MacroDef),
+        Warn(Target::MacroCall),
     ]);
 }
 
@@ -464,6 +469,12 @@ impl<S: Stage> CombineAttributeParser<S> for ForceTargetFeatureParser {
         was_forced: true,
     };
     const TEMPLATE: AttributeTemplate = template!(List: &["enable = \"feat1, feat2\""]);
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+        Allow(Target::Fn),
+        Allow(Target::Method(MethodKind::Inherent)),
+        Allow(Target::Method(MethodKind::Trait { body: true })),
+        Allow(Target::Method(MethodKind::TraitImpl)),
+    ]);
 
     fn extend<'c>(
         cx: &'c mut AcceptContext<'_, '_, S>,
@@ -471,11 +482,106 @@ impl<S: Stage> CombineAttributeParser<S> for ForceTargetFeatureParser {
     ) -> impl IntoIterator<Item = Self::Item> + 'c {
         parse_tf_attribute(cx, args)
     }
+}
 
-    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
-        Allow(Target::Fn),
-        Allow(Target::Method(MethodKind::Inherent)),
-        Allow(Target::Method(MethodKind::Trait { body: true })),
-        Allow(Target::Method(MethodKind::TraitImpl)),
+pub(crate) struct SanitizeParser;
+
+impl<S: Stage> SingleAttributeParser<S> for SanitizeParser {
+    const PATH: &[Symbol] = &[sym::sanitize];
+
+    // FIXME: still checked in check_attrs.rs
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
+
+    const TEMPLATE: AttributeTemplate = template!(List: &[
+        r#"address = "on|off""#,
+        r#"kernel_address = "on|off""#,
+        r#"cfi = "on|off""#,
+        r#"hwaddress = "on|off""#,
+        r#"kcfi = "on|off""#,
+        r#"memory = "on|off""#,
+        r#"memtag = "on|off""#,
+        r#"shadow_call_stack = "on|off""#,
+        r#"thread = "on|off""#
     ]);
+
+    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
+    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
+
+    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
+        let Some(list) = args.list() else {
+            cx.expected_list(cx.attr_span);
+            return None;
+        };
+
+        let mut on_set = SanitizerSet::empty();
+        let mut off_set = SanitizerSet::empty();
+
+        for item in list.mixed() {
+            let Some(item) = item.meta_item() else {
+                cx.expected_name_value(item.span(), None);
+                continue;
+            };
+
+            let path = item.path().word_sym();
+            let Some(value) = item.args().name_value() else {
+                cx.expected_name_value(item.span(), path);
+                continue;
+            };
+
+            let mut apply = |s: SanitizerSet| {
+                let is_on = match value.value_as_str() {
+                    Some(sym::on) => true,
+                    Some(sym::off) => false,
+                    Some(_) => {
+                        cx.expected_specific_argument_strings(
+                            value.value_span,
+                            &[sym::on, sym::off],
+                        );
+                        return;
+                    }
+                    None => {
+                        cx.expected_string_literal(value.value_span, Some(value.value_as_lit()));
+                        return;
+                    }
+                };
+
+                if is_on {
+                    on_set |= s;
+                } else {
+                    off_set |= s;
+                }
+            };
+
+            match path {
+                Some(sym::address) | Some(sym::kernel_address) => {
+                    apply(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS)
+                }
+                Some(sym::cfi) => apply(SanitizerSet::CFI),
+                Some(sym::kcfi) => apply(SanitizerSet::KCFI),
+                Some(sym::memory) => apply(SanitizerSet::MEMORY),
+                Some(sym::memtag) => apply(SanitizerSet::MEMTAG),
+                Some(sym::shadow_call_stack) => apply(SanitizerSet::SHADOWCALLSTACK),
+                Some(sym::thread) => apply(SanitizerSet::THREAD),
+                Some(sym::hwaddress) => apply(SanitizerSet::HWADDRESS),
+                _ => {
+                    cx.expected_specific_argument_strings(
+                        item.path().span(),
+                        &[
+                            sym::address,
+                            sym::cfi,
+                            sym::kcfi,
+                            sym::memory,
+                            sym::memtag,
+                            sym::shadow_call_stack,
+                            sym::thread,
+                            sym::hwaddress,
+                        ],
+                    );
+                    continue;
+                }
+            }
+        }
+
+        Some(AttributeKind::Sanitize { on_set, off_set, span: cx.attr_span })
+    }
 }
diff --git a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs
new file mode 100644
index 00000000000..2fed09b85e8
--- /dev/null
+++ b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs
@@ -0,0 +1,36 @@
+use rustc_feature::AttributeType;
+
+use super::prelude::*;
+
+pub(crate) struct CrateNameParser;
+
+impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
+    const PATH: &[Symbol] = &[sym::crate_name];
+    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
+    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
+    const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
+    const TYPE: AttributeType = AttributeType::CrateLevel;
+
+    // FIXME: crate name is allowed on all targets and ignored,
+    //        even though it should only be valid on crates of course
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
+
+    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
+        let ArgParser::NameValue(n) = args else {
+            cx.expected_name_value(cx.attr_span, None);
+            return None;
+        };
+
+        let Some(name) = n.value_as_str() else {
+            cx.expected_string_literal(n.value_span, Some(n.value_as_lit()));
+            return None;
+        };
+
+        Some(AttributeKind::CrateName {
+            name,
+            name_span: n.value_span,
+            attr_span: cx.attr_span,
+            style: cx.attr_style,
+        })
+    }
+}
diff --git a/compiler/rustc_attr_parsing/src/attributes/inline.rs b/compiler/rustc_attr_parsing/src/attributes/inline.rs
index 39d5ff85d9f..a73430c9d00 100644
--- a/compiler/rustc_attr_parsing/src/attributes/inline.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/inline.rs
@@ -25,6 +25,7 @@ impl<S: Stage> SingleAttributeParser<S> for InlineParser {
         Warn(Target::MacroDef),
         Warn(Target::Arm),
         Warn(Target::AssocConst),
+        Warn(Target::MacroCall),
     ]);
     const TEMPLATE: AttributeTemplate = template!(
         Word,
diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
index 66b02697c77..d4942e56f42 100644
--- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
@@ -1,9 +1,21 @@
+use rustc_feature::Features;
 use rustc_hir::attrs::AttributeKind::{LinkName, LinkOrdinal, LinkSection};
-use rustc_hir::attrs::Linkage;
+use rustc_hir::attrs::*;
+use rustc_session::Session;
+use rustc_session::parse::feature_err;
+use rustc_span::kw;
+use rustc_target::spec::BinaryFormat;
 
 use super::prelude::*;
 use super::util::parse_single_integer;
-use crate::session_diagnostics::{LinkOrdinalOutOfRange, NullOnLinkSection};
+use crate::attributes::cfg::parse_cfg_entry;
+use crate::fluent_generated;
+use crate::session_diagnostics::{
+    AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, ImportNameTypeRaw, ImportNameTypeX86,
+    IncompatibleWasmLink, InvalidLinkModifier, LinkFrameworkApple, LinkOrdinalOutOfRange,
+    LinkRequiresName, MultipleModifiers, NullOnLinkSection, RawDylibNoNul, RawDylibOnlyWindows,
+    WholeArchiveNeedsStatic,
+};
 
 pub(crate) struct LinkNameParser;
 
@@ -34,6 +46,409 @@ impl<S: Stage> SingleAttributeParser<S> for LinkNameParser {
     }
 }
 
+pub(crate) struct LinkParser;
+
+impl<S: Stage> CombineAttributeParser<S> for LinkParser {
+    type Item = LinkEntry;
+    const PATH: &[Symbol] = &[sym::link];
+    const CONVERT: ConvertFn<Self::Item> = AttributeKind::Link;
+    const TEMPLATE: AttributeTemplate = template!(List: &[
+            r#"name = "...""#,
+            r#"name = "...", kind = "dylib|static|...""#,
+            r#"name = "...", wasm_import_module = "...""#,
+            r#"name = "...", import_name_type = "decorated|noprefix|undecorated""#,
+            r#"name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated""#,
+        ], "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute");
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs`
+
+    fn extend<'c>(
+        cx: &'c mut AcceptContext<'_, '_, S>,
+        args: &'c ArgParser<'_>,
+    ) -> impl IntoIterator<Item = Self::Item> + 'c {
+        let mut result = None;
+        let Some(items) = args.list() else {
+            cx.expected_list(cx.attr_span);
+            return result;
+        };
+
+        let sess = cx.sess();
+        let features = cx.features();
+
+        let mut name = None;
+        let mut kind = None;
+        let mut modifiers = None;
+        let mut cfg = None;
+        let mut wasm_import_module = None;
+        let mut import_name_type = None;
+        for item in items.mixed() {
+            let Some(item) = item.meta_item() else {
+                cx.unexpected_literal(item.span());
+                continue;
+            };
+
+            let cont = match item.path().word().map(|ident| ident.name) {
+                Some(sym::name) => Self::parse_link_name(item, &mut name, cx),
+                Some(sym::kind) => Self::parse_link_kind(item, &mut kind, cx, sess, features),
+                Some(sym::modifiers) => Self::parse_link_modifiers(item, &mut modifiers, cx),
+                Some(sym::cfg) => Self::parse_link_cfg(item, &mut cfg, cx, sess, features),
+                Some(sym::wasm_import_module) => {
+                    Self::parse_link_wasm_import_module(item, &mut wasm_import_module, cx)
+                }
+                Some(sym::import_name_type) => {
+                    Self::parse_link_import_name_type(item, &mut import_name_type, cx)
+                }
+                _ => {
+                    cx.expected_specific_argument_strings(
+                        item.span(),
+                        &[
+                            sym::name,
+                            sym::kind,
+                            sym::modifiers,
+                            sym::cfg,
+                            sym::wasm_import_module,
+                            sym::import_name_type,
+                        ],
+                    );
+                    true
+                }
+            };
+            if !cont {
+                return result;
+            }
+        }
+
+        // Do this outside the above loop so we don't depend on modifiers coming after kinds
+        let mut verbatim = None;
+        if let Some((modifiers, span)) = modifiers {
+            for modifier in modifiers.as_str().split(',') {
+                let (modifier, value): (Symbol, bool) = match modifier.strip_prefix(&['+', '-']) {
+                    Some(m) => (Symbol::intern(m), modifier.starts_with('+')),
+                    None => {
+                        cx.emit_err(InvalidLinkModifier { span });
+                        continue;
+                    }
+                };
+
+                macro report_unstable_modifier($feature: ident) {
+                    if !features.$feature() {
+                        // FIXME: make this translatable
+                        #[expect(rustc::untranslatable_diagnostic)]
+                        feature_err(
+                            sess,
+                            sym::$feature,
+                            span,
+                            format!("linking modifier `{modifier}` is unstable"),
+                        )
+                        .emit();
+                    }
+                }
+                let assign_modifier = |dst: &mut Option<bool>| {
+                    if dst.is_some() {
+                        cx.emit_err(MultipleModifiers { span, modifier });
+                    } else {
+                        *dst = Some(value);
+                    }
+                };
+                match (modifier, &mut kind) {
+                    (sym::bundle, Some(NativeLibKind::Static { bundle, .. })) => {
+                        assign_modifier(bundle)
+                    }
+                    (sym::bundle, _) => {
+                        cx.emit_err(BundleNeedsStatic { span });
+                    }
+
+                    (sym::verbatim, _) => assign_modifier(&mut verbatim),
+
+                    (
+                        sym::whole_dash_archive,
+                        Some(NativeLibKind::Static { whole_archive, .. }),
+                    ) => assign_modifier(whole_archive),
+                    (sym::whole_dash_archive, _) => {
+                        cx.emit_err(WholeArchiveNeedsStatic { span });
+                    }
+
+                    (sym::as_dash_needed, Some(NativeLibKind::Dylib { as_needed }))
+                    | (sym::as_dash_needed, Some(NativeLibKind::Framework { as_needed })) => {
+                        report_unstable_modifier!(native_link_modifiers_as_needed);
+                        assign_modifier(as_needed)
+                    }
+                    (sym::as_dash_needed, _) => {
+                        cx.emit_err(AsNeededCompatibility { span });
+                    }
+
+                    _ => {
+                        cx.expected_specific_argument_strings(
+                            span,
+                            &[
+                                sym::bundle,
+                                sym::verbatim,
+                                sym::whole_dash_archive,
+                                sym::as_dash_needed,
+                            ],
+                        );
+                    }
+                }
+            }
+        }
+
+        if let Some((_, span)) = wasm_import_module {
+            if name.is_some() || kind.is_some() || modifiers.is_some() || cfg.is_some() {
+                cx.emit_err(IncompatibleWasmLink { span });
+            }
+        }
+
+        if wasm_import_module.is_some() {
+            (name, kind) = (wasm_import_module, Some(NativeLibKind::WasmImportModule));
+        }
+        let Some((name, name_span)) = name else {
+            cx.emit_err(LinkRequiresName { span: cx.attr_span });
+            return result;
+        };
+
+        // Do this outside of the loop so that `import_name_type` can be specified before `kind`.
+        if let Some((_, span)) = import_name_type {
+            if kind != Some(NativeLibKind::RawDylib) {
+                cx.emit_err(ImportNameTypeRaw { span });
+            }
+        }
+
+        if let Some(NativeLibKind::RawDylib) = kind
+            && name.as_str().contains('\0')
+        {
+            cx.emit_err(RawDylibNoNul { span: name_span });
+        }
+
+        result = Some(LinkEntry {
+            span: cx.attr_span,
+            kind: kind.unwrap_or(NativeLibKind::Unspecified),
+            name,
+            cfg,
+            verbatim,
+            import_name_type,
+        });
+        result
+    }
+}
+
+impl LinkParser {
+    fn parse_link_name<S: Stage>(
+        item: &MetaItemParser<'_>,
+        name: &mut Option<(Symbol, Span)>,
+        cx: &mut AcceptContext<'_, '_, S>,
+    ) -> bool {
+        if name.is_some() {
+            cx.duplicate_key(item.span(), sym::name);
+            return true;
+        }
+        let Some(nv) = item.args().name_value() else {
+            cx.expected_name_value(item.span(), Some(sym::name));
+            return false;
+        };
+        let Some(link_name) = nv.value_as_str() else {
+            cx.expected_name_value(item.span(), Some(sym::name));
+            return false;
+        };
+
+        if link_name.is_empty() {
+            cx.emit_err(EmptyLinkName { span: nv.value_span });
+        }
+        *name = Some((link_name, nv.value_span));
+        true
+    }
+
+    fn parse_link_kind<S: Stage>(
+        item: &MetaItemParser<'_>,
+        kind: &mut Option<NativeLibKind>,
+        cx: &mut AcceptContext<'_, '_, S>,
+        sess: &Session,
+        features: &Features,
+    ) -> bool {
+        if kind.is_some() {
+            cx.duplicate_key(item.span(), sym::kind);
+            return true;
+        }
+        let Some(nv) = item.args().name_value() else {
+            cx.expected_name_value(item.span(), Some(sym::kind));
+            return true;
+        };
+        let Some(link_kind) = nv.value_as_str() else {
+            cx.expected_name_value(item.span(), Some(sym::kind));
+            return true;
+        };
+
+        let link_kind = match link_kind {
+            kw::Static => NativeLibKind::Static { bundle: None, whole_archive: None },
+            sym::dylib => NativeLibKind::Dylib { as_needed: None },
+            sym::framework => {
+                if !sess.target.is_like_darwin {
+                    cx.emit_err(LinkFrameworkApple { span: nv.value_span });
+                }
+                NativeLibKind::Framework { as_needed: None }
+            }
+            sym::raw_dash_dylib => {
+                if sess.target.is_like_windows {
+                    // raw-dylib is stable and working on Windows
+                } else if sess.target.binary_format == BinaryFormat::Elf && features.raw_dylib_elf()
+                {
+                    // raw-dylib is unstable on ELF, but the user opted in
+                } else if sess.target.binary_format == BinaryFormat::Elf && sess.is_nightly_build()
+                {
+                    feature_err(
+                        sess,
+                        sym::raw_dylib_elf,
+                        nv.value_span,
+                        fluent_generated::attr_parsing_raw_dylib_elf_unstable,
+                    )
+                    .emit();
+                } else {
+                    cx.emit_err(RawDylibOnlyWindows { span: nv.value_span });
+                }
+
+                NativeLibKind::RawDylib
+            }
+            sym::link_dash_arg => {
+                if !features.link_arg_attribute() {
+                    feature_err(
+                        sess,
+                        sym::link_arg_attribute,
+                        nv.value_span,
+                        fluent_generated::attr_parsing_link_arg_unstable,
+                    )
+                    .emit();
+                }
+                NativeLibKind::LinkArg
+            }
+            _kind => {
+                cx.expected_specific_argument_strings(
+                    nv.value_span,
+                    &[
+                        kw::Static,
+                        sym::dylib,
+                        sym::framework,
+                        sym::raw_dash_dylib,
+                        sym::link_dash_arg,
+                    ],
+                );
+                return true;
+            }
+        };
+        *kind = Some(link_kind);
+        true
+    }
+
+    fn parse_link_modifiers<S: Stage>(
+        item: &MetaItemParser<'_>,
+        modifiers: &mut Option<(Symbol, Span)>,
+        cx: &mut AcceptContext<'_, '_, S>,
+    ) -> bool {
+        if modifiers.is_some() {
+            cx.duplicate_key(item.span(), sym::modifiers);
+            return true;
+        }
+        let Some(nv) = item.args().name_value() else {
+            cx.expected_name_value(item.span(), Some(sym::modifiers));
+            return true;
+        };
+        let Some(link_modifiers) = nv.value_as_str() else {
+            cx.expected_name_value(item.span(), Some(sym::modifiers));
+            return true;
+        };
+        *modifiers = Some((link_modifiers, nv.value_span));
+        true
+    }
+
+    fn parse_link_cfg<S: Stage>(
+        item: &MetaItemParser<'_>,
+        cfg: &mut Option<CfgEntry>,
+        cx: &mut AcceptContext<'_, '_, S>,
+        sess: &Session,
+        features: &Features,
+    ) -> bool {
+        if cfg.is_some() {
+            cx.duplicate_key(item.span(), sym::cfg);
+            return true;
+        }
+        let Some(link_cfg) = item.args().list() else {
+            cx.expected_list(item.span());
+            return true;
+        };
+        let Some(link_cfg) = link_cfg.single() else {
+            cx.expected_single_argument(item.span());
+            return true;
+        };
+        if !features.link_cfg() {
+            feature_err(
+                sess,
+                sym::link_cfg,
+                item.span(),
+                fluent_generated::attr_parsing_link_cfg_unstable,
+            )
+            .emit();
+        }
+        *cfg = parse_cfg_entry(cx, link_cfg);
+        true
+    }
+
+    fn parse_link_wasm_import_module<S: Stage>(
+        item: &MetaItemParser<'_>,
+        wasm_import_module: &mut Option<(Symbol, Span)>,
+        cx: &mut AcceptContext<'_, '_, S>,
+    ) -> bool {
+        if wasm_import_module.is_some() {
+            cx.duplicate_key(item.span(), sym::wasm_import_module);
+            return true;
+        }
+        let Some(nv) = item.args().name_value() else {
+            cx.expected_name_value(item.span(), Some(sym::wasm_import_module));
+            return true;
+        };
+        let Some(link_wasm_import_module) = nv.value_as_str() else {
+            cx.expected_name_value(item.span(), Some(sym::wasm_import_module));
+            return true;
+        };
+        *wasm_import_module = Some((link_wasm_import_module, item.span()));
+        true
+    }
+
+    fn parse_link_import_name_type<S: Stage>(
+        item: &MetaItemParser<'_>,
+        import_name_type: &mut Option<(PeImportNameType, Span)>,
+        cx: &mut AcceptContext<'_, '_, S>,
+    ) -> bool {
+        if import_name_type.is_some() {
+            cx.duplicate_key(item.span(), sym::import_name_type);
+            return true;
+        }
+        let Some(nv) = item.args().name_value() else {
+            cx.expected_name_value(item.span(), Some(sym::import_name_type));
+            return true;
+        };
+        let Some(link_import_name_type) = nv.value_as_str() else {
+            cx.expected_name_value(item.span(), Some(sym::import_name_type));
+            return true;
+        };
+        if cx.sess().target.arch != "x86" {
+            cx.emit_err(ImportNameTypeX86 { span: item.span() });
+            return true;
+        }
+
+        let link_import_name_type = match link_import_name_type {
+            sym::decorated => PeImportNameType::Decorated,
+            sym::noprefix => PeImportNameType::NoPrefix,
+            sym::undecorated => PeImportNameType::Undecorated,
+            _ => {
+                cx.expected_specific_argument_strings(
+                    item.span(),
+                    &[sym::decorated, sym::noprefix, sym::undecorated],
+                );
+                return true;
+            }
+        };
+        *import_name_type = Some((link_import_name_type, item.span()));
+        true
+    }
+}
+
 pub(crate) struct LinkSectionParser;
 
 impl<S: Stage> SingleAttributeParser<S> for LinkSectionParser {
@@ -110,8 +525,11 @@ impl<S: Stage> SingleAttributeParser<S> for LinkOrdinalParser {
     const PATH: &[Symbol] = &[sym::link_ordinal];
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
-    const ALLOWED_TARGETS: AllowedTargets =
-        AllowedTargets::AllowList(&[Allow(Target::ForeignFn), Allow(Target::ForeignStatic)]);
+    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
+        Allow(Target::ForeignFn),
+        Allow(Target::ForeignStatic),
+        Warn(Target::MacroCall),
+    ]);
     const TEMPLATE: AttributeTemplate = template!(
         List: &["ordinal"],
         "https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_ordinal-attribute"
diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs
index b98678041d7..043bc925eac 100644
--- a/compiler/rustc_attr_parsing/src/attributes/mod.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs
@@ -12,11 +12,15 @@
 //! - [`CombineAttributeParser`](crate::attributes::CombineAttributeParser): makes it easy to implement an attribute which should combine the
 //! contents of attributes, if an attribute appear multiple times in a list
 //!
+//! By default, attributes are allowed anywhere. When adding an attribute that should only be used
+//! at the crate root, consider setting the `TYPE` in the parser trait to
+//! [`AttributeType::CrateLevel`](rustc_feature::AttributeType::CrateLevel).
+//!
 //! Attributes should be added to `crate::context::ATTRIBUTE_PARSERS` to be parsed.
 
 use std::marker::PhantomData;
 
-use rustc_feature::{AttributeTemplate, template};
+use rustc_feature::{AttributeTemplate, AttributeType, template};
 use rustc_hir::attrs::AttributeKind;
 use rustc_span::{Span, Symbol};
 use thin_vec::ThinVec;
@@ -35,6 +39,7 @@ pub(crate) mod cfg;
 pub(crate) mod cfg_old;
 pub(crate) mod codegen_attrs;
 pub(crate) mod confusables;
+pub(crate) mod crate_level;
 pub(crate) mod deprecation;
 pub(crate) mod dummy;
 pub(crate) mod inline;
@@ -87,6 +92,8 @@ pub(crate) trait AttributeParser<S: Stage>: Default + 'static {
 
     const ALLOWED_TARGETS: AllowedTargets;
 
+    const TYPE: AttributeType = AttributeType::Normal;
+
     /// The parser has gotten a chance to accept the attributes on an item,
     /// here it can produce an attribute.
     ///
@@ -128,6 +135,8 @@ pub(crate) trait SingleAttributeParser<S: Stage>: 'static {
     /// The template this attribute parser should implement. Used for diagnostics.
     const TEMPLATE: AttributeTemplate;
 
+    const TYPE: AttributeType = AttributeType::Normal;
+
     /// Converts a single syntactical attribute to a single semantic attribute, or [`AttributeKind`]
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind>;
 }
@@ -174,6 +183,8 @@ impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S>
     )];
     const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
 
+    const TYPE: AttributeType = T::TYPE;
+
     fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
         Some(self.1?.0)
     }
@@ -258,6 +269,7 @@ pub(crate) trait NoArgsAttributeParser<S: Stage>: 'static {
     const PATH: &[Symbol];
     const ON_DUPLICATE: OnDuplicate<S>;
     const ALLOWED_TARGETS: AllowedTargets;
+    const TYPE: AttributeType = AttributeType::Normal;
 
     /// Create the [`AttributeKind`] given attribute's [`Span`].
     const CREATE: fn(Span) -> AttributeKind;
@@ -277,6 +289,7 @@ impl<T: NoArgsAttributeParser<S>, S: Stage> SingleAttributeParser<S> for Without
     const ON_DUPLICATE: OnDuplicate<S> = T::ON_DUPLICATE;
     const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
     const TEMPLATE: AttributeTemplate = template!(Word);
+    const TYPE: AttributeType = T::TYPE;
 
     fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
         if let Err(span) = args.no_args() {
@@ -310,6 +323,8 @@ pub(crate) trait CombineAttributeParser<S: Stage>: 'static {
     /// The template this attribute parser should implement. Used for diagnostics.
     const TEMPLATE: AttributeTemplate;
 
+    const TYPE: AttributeType = AttributeType::Normal;
+
     /// Converts a single syntactical attribute to a number of elements of the semantic attribute, or [`AttributeKind`]
     fn extend<'c>(
         cx: &'c mut AcceptContext<'_, '_, S>,
@@ -345,6 +360,7 @@ impl<T: CombineAttributeParser<S>, S: Stage> AttributeParser<S> for Combine<T, S
             group.items.extend(T::extend(cx, args))
         })];
     const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
+    const TYPE: AttributeType = T::TYPE;
 
     fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
         if let Some(first_span) = self.first_span {
diff --git a/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs b/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs
index 4e6aec95e66..fc41c073fd2 100644
--- a/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs
@@ -19,6 +19,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for NonExhaustiveParser {
         Warn(Target::Field),
         Warn(Target::Arm),
         Warn(Target::MacroDef),
+        Warn(Target::MacroCall),
     ]);
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::NonExhaustive;
 }
diff --git a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs
index 9ac18c04e32..b9929d6f1f8 100644
--- a/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/proc_macro_attrs.rs
@@ -1,11 +1,13 @@
 use super::prelude::*;
 
+const PROC_MACRO_ALLOWED_TARGETS: AllowedTargets =
+    AllowedTargets::AllowList(&[Allow(Target::Fn), Warn(Target::Crate), Warn(Target::MacroCall)]);
+
 pub(crate) struct ProcMacroParser;
 impl<S: Stage> NoArgsAttributeParser<S> for ProcMacroParser {
     const PATH: &[Symbol] = &[sym::proc_macro];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
-    const ALLOWED_TARGETS: AllowedTargets =
-        AllowedTargets::AllowList(&[Allow(Target::Fn), Warn(Target::Crate)]);
+    const ALLOWED_TARGETS: AllowedTargets = PROC_MACRO_ALLOWED_TARGETS;
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::ProcMacro;
 }
 
@@ -13,8 +15,7 @@ pub(crate) struct ProcMacroAttributeParser;
 impl<S: Stage> NoArgsAttributeParser<S> for ProcMacroAttributeParser {
     const PATH: &[Symbol] = &[sym::proc_macro_attribute];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
-    const ALLOWED_TARGETS: AllowedTargets =
-        AllowedTargets::AllowList(&[Allow(Target::Fn), Warn(Target::Crate)]);
+    const ALLOWED_TARGETS: AllowedTargets = PROC_MACRO_ALLOWED_TARGETS;
     const CREATE: fn(Span) -> AttributeKind = AttributeKind::ProcMacroAttribute;
 }
 
@@ -23,8 +24,7 @@ impl<S: Stage> SingleAttributeParser<S> for ProcMacroDeriveParser {
     const PATH: &[Symbol] = &[sym::proc_macro_derive];
     const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
-    const ALLOWED_TARGETS: AllowedTargets =
-        AllowedTargets::AllowList(&[Allow(Target::Fn), Warn(Target::Crate)]);
+    const ALLOWED_TARGETS: AllowedTargets = PROC_MACRO_ALLOWED_TARGETS;
     const TEMPLATE: AttributeTemplate = template!(
         List: &["TraitName", "TraitName, attributes(name1, name2, ...)"],
         "https://doc.rust-lang.org/reference/procedural-macros.html#derive-macros"
diff --git a/compiler/rustc_attr_parsing/src/attributes/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs
index 89ac1b07d16..fbd9a480fbb 100644
--- a/compiler/rustc_attr_parsing/src/attributes/traits.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs
@@ -1,5 +1,7 @@
 use std::mem;
 
+use rustc_feature::AttributeType;
+
 use super::prelude::*;
 use crate::attributes::{
     AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
@@ -154,6 +156,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for CoherenceIsCoreParser {
     const PATH: &[Symbol] = &[sym::rustc_coherence_is_core];
     const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
     const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
+    const TYPE: AttributeType = AttributeType::CrateLevel;
     const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::CoherenceIsCore;
 }
 
diff --git a/compiler/rustc_attr_parsing/src/attributes/util.rs b/compiler/rustc_attr_parsing/src/attributes/util.rs
index ef9701cb7cb..77e8c32e59d 100644
--- a/compiler/rustc_attr_parsing/src/attributes/util.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/util.rs
@@ -1,5 +1,5 @@
 use rustc_ast::LitKind;
-use rustc_ast::attr::{AttributeExt, first_attr_value_str_by_name};
+use rustc_ast::attr::AttributeExt;
 use rustc_feature::is_builtin_attr_name;
 use rustc_hir::RustcVersion;
 use rustc_span::{Symbol, sym};
@@ -27,10 +27,6 @@ pub fn is_builtin_attr(attr: &impl AttributeExt) -> bool {
     attr.is_doc_comment() || attr.ident().is_some_and(|ident| is_builtin_attr_name(ident.name))
 }
 
-pub fn find_crate_name(attrs: &[impl AttributeExt]) -> Option<Symbol> {
-    first_attr_value_str_by_name(attrs, sym::crate_name)
-}
-
 pub fn is_doc_alias_attrs_contain_symbol<'tcx, T: AttributeExt + 'tcx>(
     attrs: impl Iterator<Item = &'tcx T>,
     symbol: Symbol,
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index b9c415e8085..7f5b810f244 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -4,12 +4,12 @@ use std::ops::{Deref, DerefMut};
 use std::sync::LazyLock;
 
 use private::Sealed;
-use rustc_ast::{AttrStyle, MetaItemLit, NodeId};
-use rustc_errors::Diagnostic;
-use rustc_feature::AttributeTemplate;
+use rustc_ast::{AttrStyle, CRATE_NODE_ID, MetaItemLit, NodeId};
+use rustc_errors::{Diag, Diagnostic, Level};
+use rustc_feature::{AttributeTemplate, AttributeType};
 use rustc_hir::attrs::AttributeKind;
 use rustc_hir::lints::{AttributeLint, AttributeLintKind};
-use rustc_hir::{AttrPath, HirId};
+use rustc_hir::{AttrPath, CRATE_HIR_ID, HirId};
 use rustc_session::Session;
 use rustc_span::{ErrorGuaranteed, Span, Symbol};
 
@@ -20,15 +20,17 @@ use crate::attributes::allow_unstable::{
 use crate::attributes::body::CoroutineParser;
 use crate::attributes::codegen_attrs::{
     ColdParser, CoverageParser, ExportNameParser, ForceTargetFeatureParser, NakedParser,
-    NoMangleParser, OptimizeParser, TargetFeatureParser, TrackCallerParser, UsedParser,
+    NoMangleParser, OptimizeParser, SanitizeParser, TargetFeatureParser, TrackCallerParser,
+    UsedParser,
 };
 use crate::attributes::confusables::ConfusablesParser;
+use crate::attributes::crate_level::CrateNameParser;
 use crate::attributes::deprecation::DeprecationParser;
 use crate::attributes::dummy::DummyParser;
 use crate::attributes::inline::{InlineParser, RustcForceInlineParser};
 use crate::attributes::link_attrs::{
     ExportStableParser, FfiConstParser, FfiPureParser, LinkNameParser, LinkOrdinalParser,
-    LinkSectionParser, LinkageParser, StdInternalSymbolParser,
+    LinkParser, LinkSectionParser, LinkageParser, StdInternalSymbolParser,
 };
 use crate::attributes::lint_helpers::{
     AsPtrParser, AutomaticallyDerivedParser, PassByValueParser, PubTransparentParser,
@@ -78,6 +80,7 @@ pub(super) struct GroupTypeInnerAccept<S: Stage> {
     pub(super) template: AttributeTemplate,
     pub(super) accept_fn: AcceptFn<S>,
     pub(super) allowed_targets: AllowedTargets,
+    pub(super) attribute_type: AttributeType,
 }
 
 type AcceptFn<S> =
@@ -127,6 +130,7 @@ macro_rules! attribute_parsers {
                                 })
                             }),
                             allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS,
+                            attribute_type: <$names as crate::attributes::AttributeParser<$stage>>::TYPE,
                         });
                     }
 
@@ -158,6 +162,7 @@ attribute_parsers!(
         Combine<AllowConstFnUnstableParser>,
         Combine<AllowInternalUnstableParser>,
         Combine<ForceTargetFeatureParser>,
+        Combine<LinkParser>,
         Combine<ReprParser>,
         Combine<TargetFeatureParser>,
         Combine<UnstableFeatureBoundParser>,
@@ -165,6 +170,7 @@ attribute_parsers!(
 
         // tidy-alphabetical-start
         Single<CoverageParser>,
+        Single<CrateNameParser>,
         Single<CustomMirParser>,
         Single<DeprecationParser>,
         Single<DummyParser>,
@@ -184,6 +190,7 @@ attribute_parsers!(
         Single<RustcLayoutScalarValidRangeEnd>,
         Single<RustcLayoutScalarValidRangeStart>,
         Single<RustcObjectLifetimeDefaultParser>,
+        Single<SanitizeParser>,
         Single<ShouldPanicParser>,
         Single<SkipDuringMethodDispatchParser>,
         Single<TransparencyParser>,
@@ -246,6 +253,8 @@ pub trait Stage: Sized + 'static + Sealed {
     ) -> ErrorGuaranteed;
 
     fn should_emit(&self) -> ShouldEmit;
+
+    fn id_is_crate_root(id: Self::Id) -> bool;
 }
 
 // allow because it's a sealed trait
@@ -261,16 +270,16 @@ impl Stage for Early {
         sess: &'sess Session,
         diag: impl for<'x> Diagnostic<'x>,
     ) -> ErrorGuaranteed {
-        if self.emit_errors.should_emit() {
-            sess.dcx().emit_err(diag)
-        } else {
-            sess.dcx().create_err(diag).delay_as_bug()
-        }
+        self.should_emit().emit_err(sess.dcx().create_err(diag))
     }
 
     fn should_emit(&self) -> ShouldEmit {
         self.emit_errors
     }
+
+    fn id_is_crate_root(id: Self::Id) -> bool {
+        id == CRATE_NODE_ID
+    }
 }
 
 // allow because it's a sealed trait
@@ -292,6 +301,10 @@ impl Stage for Late {
     fn should_emit(&self) -> ShouldEmit {
         ShouldEmit::ErrorsAndLints
     }
+
+    fn id_is_crate_root(id: Self::Id) -> bool {
+        id == CRATE_HIR_ID
+    }
 }
 
 /// used when parsing attributes for miscellaneous things *before* ast lowering
@@ -312,7 +325,9 @@ pub struct AcceptContext<'f, 'sess, S: Stage> {
     /// The span of the attribute currently being parsed
     pub(crate) attr_span: Span,
 
+    /// Whether it is an inner or outer attribute
     pub(crate) attr_style: AttrStyle,
+
     /// The expected structure of the attribute.
     ///
     /// Used in reporting errors to give a hint to users what the attribute *should* look like.
@@ -331,7 +346,7 @@ impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
     /// must be delayed until after HIR is built. This method will take care of the details of
     /// that.
     pub(crate) fn emit_lint(&mut self, lint: AttributeLintKind, span: Span) {
-        if !self.stage.should_emit().should_emit() {
+        if matches!(self.stage.should_emit(), ShouldEmit::Nothing) {
             return;
         }
         let id = self.target_id;
@@ -649,8 +664,13 @@ pub enum OmitDoc {
     Skip,
 }
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Debug)]
 pub enum ShouldEmit {
+    /// The operations will emit errors, and lints, and errors are fatal.
+    ///
+    /// Only relevant when early parsing, in late parsing equivalent to `ErrorsAndLints`.
+    /// Late parsing is never fatal, and instead tries to emit as many diagnostics as possible.
+    EarlyFatal,
     /// The operation will emit errors and lints.
     /// This is usually what you need.
     ErrorsAndLints,
@@ -660,10 +680,12 @@ pub enum ShouldEmit {
 }
 
 impl ShouldEmit {
-    pub fn should_emit(&self) -> bool {
+    pub(crate) fn emit_err(&self, diag: Diag<'_>) -> ErrorGuaranteed {
         match self {
-            ShouldEmit::ErrorsAndLints => true,
-            ShouldEmit::Nothing => false,
+            ShouldEmit::EarlyFatal if diag.level() == Level::DelayedBug => diag.emit(),
+            ShouldEmit::EarlyFatal => diag.upgrade_to_fatal().emit(),
+            ShouldEmit::ErrorsAndLints => diag.emit(),
+            ShouldEmit::Nothing => diag.delay_as_bug(),
         }
     }
 }
diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs
index f652d39a708..0fe3c209421 100644
--- a/compiler/rustc_attr_parsing/src/interface.rs
+++ b/compiler/rustc_attr_parsing/src/interface.rs
@@ -51,6 +51,27 @@ impl<'sess> AttributeParser<'sess, Early> {
         target_node_id: NodeId,
         features: Option<&'sess Features>,
     ) -> Option<Attribute> {
+        Self::parse_limited_should_emit(
+            sess,
+            attrs,
+            sym,
+            target_span,
+            target_node_id,
+            features,
+            ShouldEmit::Nothing,
+        )
+    }
+
+    /// Usually you want `parse_limited`, which defaults to no errors.
+    pub fn parse_limited_should_emit(
+        sess: &'sess Session,
+        attrs: &[ast::Attribute],
+        sym: Symbol,
+        target_span: Span,
+        target_node_id: NodeId,
+        features: Option<&'sess Features>,
+        should_emit: ShouldEmit,
+    ) -> Option<Attribute> {
         let mut parsed = Self::parse_limited_all(
             sess,
             attrs,
@@ -59,7 +80,7 @@ impl<'sess> AttributeParser<'sess, Early> {
             target_span,
             target_node_id,
             features,
-            ShouldEmit::Nothing,
+            should_emit,
         );
         assert!(parsed.len() <= 1);
         parsed.pop()
@@ -84,9 +105,8 @@ impl<'sess> AttributeParser<'sess, Early> {
             target,
             OmitDoc::Skip,
             std::convert::identity,
-            |_lint| {
-                // FIXME: Can't emit lints here for now
-                // This branch can be hit when an attribute produces a warning during early parsing (such as attributes on macro calls)
+            |lint| {
+                crate::lints::emit_attribute_lint(&lint, sess);
             },
         )
     }
@@ -121,8 +141,8 @@ impl<'sess> AttributeParser<'sess, Early> {
                 cx: &mut parser,
                 target_span,
                 target_id: target_node_id,
-                emit_lint: &mut |_lint| {
-                    panic!("can't emit lints here for now (nothing uses this atm)");
+                emit_lint: &mut |lint| {
+                    crate::lints::emit_attribute_lint(&lint, sess);
                 },
             },
             attr_span: attr.span,
@@ -251,16 +271,9 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
                             };
 
                             (accept.accept_fn)(&mut cx, args);
-
-                            if self.stage.should_emit().should_emit() {
-                                self.check_target(
-                                    path.get_attribute_path(),
-                                    attr.span,
-                                    &accept.allowed_targets,
-                                    target,
-                                    target_id,
-                                    &mut emit_lint,
-                                );
+                            if !matches!(cx.stage.should_emit(), ShouldEmit::Nothing) {
+                                Self::check_type(accept.attribute_type, target, &mut cx);
+                                Self::check_target(&accept.allowed_targets, target, &mut cx);
                             }
                         }
                     } else {
diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs
index 969c24a4f89..f51cc8c4e8b 100644
--- a/compiler/rustc_attr_parsing/src/lib.rs
+++ b/compiler/rustc_attr_parsing/src/lib.rs
@@ -79,6 +79,7 @@
 // tidy-alphabetical-start
 #![allow(internal_features)]
 #![doc(rust_logo)]
+#![feature(decl_macro)]
 #![feature(rustdoc_internals)]
 #![recursion_limit = "256"]
 // tidy-alphabetical-end
@@ -106,9 +107,7 @@ pub mod validate_attr;
 
 pub use attributes::cfg::{CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg_attr};
 pub use attributes::cfg_old::*;
-pub use attributes::util::{
-    find_crate_name, is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version,
-};
+pub use attributes::util::{is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version};
 pub use context::{Early, Late, OmitDoc, ShouldEmit};
 pub use interface::AttributeParser;
 pub use lints::emit_attribute_lint;
diff --git a/compiler/rustc_attr_parsing/src/lints.rs b/compiler/rustc_attr_parsing/src/lints.rs
index 7030f28f23c..b1a971eec32 100644
--- a/compiler/rustc_attr_parsing/src/lints.rs
+++ b/compiler/rustc_attr_parsing/src/lints.rs
@@ -1,13 +1,13 @@
 use std::borrow::Cow;
 
 use rustc_errors::{DiagArgValue, LintEmitter};
+use rustc_hir::Target;
 use rustc_hir::lints::{AttributeLint, AttributeLintKind};
-use rustc_hir::{HirId, Target};
 use rustc_span::sym;
 
 use crate::session_diagnostics;
 
-pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<HirId>, lint_emitter: L) {
+pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<L::Id>, lint_emitter: L) {
     let AttributeLint { id, span, kind } = lint;
 
     match kind {
@@ -41,8 +41,14 @@ pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<HirId>, lint_emi
             .emit_node_span_lint(
                 // This check is here because `deprecated` had its own lint group and removing this would be a breaking change
                 if name.segments[0].name == sym::deprecated
-                    && ![Target::Closure, Target::Expression, Target::Statement, Target::Arm]
-                        .contains(target)
+                    && ![
+                        Target::Closure,
+                        Target::Expression,
+                        Target::Statement,
+                        Target::Arm,
+                        Target::MacroCall,
+                    ]
+                    .contains(target)
                 {
                     rustc_session::lint::builtin::USELESS_DEPRECATED
                 } else {
@@ -51,7 +57,7 @@ pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<HirId>, lint_emi
                 *id,
                 *span,
                 session_diagnostics::InvalidTargetLint {
-                    name,
+                    name: name.clone(),
                     target: target.plural_name(),
                     applied: DiagArgValue::StrListSepByAnd(
                         applied.into_iter().map(|i| Cow::Owned(i.to_string())).collect(),
@@ -60,5 +66,19 @@ pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<HirId>, lint_emi
                     attr_span: *span,
                 },
             ),
+
+        &AttributeLintKind::InvalidStyle { ref name, is_used_as_inner, target, target_span } => {
+            lint_emitter.emit_node_span_lint(
+                rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
+                *id,
+                *span,
+                session_diagnostics::InvalidAttrStyle {
+                    name: name.clone(),
+                    is_used_as_inner,
+                    target_span: (!is_used_as_inner).then_some(target_span),
+                    target,
+                },
+            )
+        }
     }
 }
diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs
index 364f8819d13..6d3cf684296 100644
--- a/compiler/rustc_attr_parsing/src/parser.rs
+++ b/compiler/rustc_attr_parsing/src/parser.rs
@@ -328,15 +328,16 @@ fn expr_to_lit(
         match res {
             Ok(lit) => {
                 if token_lit.suffix.is_some() {
-                    psess
-                        .dcx()
-                        .create_err(SuffixedLiteralInAttribute { span: lit.span })
-                        .emit_unless_delay(!should_emit.should_emit());
+                    should_emit.emit_err(
+                        psess.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }),
+                    );
                     None
                 } else {
-                    if should_emit.should_emit() && !lit.kind.is_unsuffixed() {
+                    if !lit.kind.is_unsuffixed() {
                         // Emit error and continue, we can still parse the attribute as if the suffix isn't there
-                        psess.dcx().emit_err(SuffixedLiteralInAttribute { span: lit.span });
+                        should_emit.emit_err(
+                            psess.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }),
+                        );
                     }
 
                     Some(lit)
@@ -354,6 +355,10 @@ fn expr_to_lit(
             }
         }
     } else {
+        if matches!(should_emit, ShouldEmit::Nothing) {
+            return None;
+        }
+
         // Example cases:
         // - `#[foo = 1+1]`: results in `ast::ExprKind::BinOp`.
         // - `#[foo = include_str!("nonexistent-file.rs")]`:
@@ -361,12 +366,8 @@ fn expr_to_lit(
         //   the error because an earlier error will have already
         //   been reported.
         let msg = "attribute value must be a literal";
-        let mut err = psess.dcx().struct_span_err(span, msg);
-        if let ExprKind::Err(_) = expr.kind {
-            err.downgrade_to_delayed_bug();
-        }
-
-        err.emit_unless_delay(!should_emit.should_emit());
+        let err = psess.dcx().struct_span_err(span, msg);
+        should_emit.emit_err(err);
         None
     }
 }
@@ -397,9 +398,11 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
             }
         };
 
-        if self.should_emit.should_emit() && !lit.kind.is_unsuffixed() {
+        if !lit.kind.is_unsuffixed() {
             // Emit error and continue, we can still parse the attribute as if the suffix isn't there
-            self.parser.dcx().emit_err(SuffixedLiteralInAttribute { span: lit.span });
+            self.should_emit.emit_err(
+                self.parser.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span }),
+            );
         }
 
         Ok(lit)
@@ -539,7 +542,7 @@ impl<'a> MetaItemListParser<'a> {
         ) {
             Ok(s) => Some(s),
             Err(e) => {
-                e.emit_unless_delay(!should_emit.should_emit());
+                should_emit.emit_err(e);
                 None
             }
         }
diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
index 2192e8f8f83..a9dee23bf6a 100644
--- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs
+++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs
@@ -6,7 +6,7 @@ use rustc_errors::{
     Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level,
 };
 use rustc_feature::AttributeTemplate;
-use rustc_hir::AttrPath;
+use rustc_hir::{AttrPath, Target};
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_span::{Span, Symbol};
 
@@ -484,9 +484,9 @@ pub(crate) struct EmptyAttributeList {
 #[diag(attr_parsing_invalid_target_lint)]
 #[warning]
 #[help]
-pub(crate) struct InvalidTargetLint<'a> {
-    pub name: &'a AttrPath,
-    pub target: &'a str,
+pub(crate) struct InvalidTargetLint {
+    pub name: AttrPath,
+    pub target: &'static str,
     pub applied: DiagArgValue,
     pub only: &'static str,
     #[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")]
@@ -826,3 +826,107 @@ pub(crate) struct SuffixedLiteralInAttribute {
     #[primary_span]
     pub span: Span,
 }
+
+#[derive(LintDiagnostic)]
+#[diag(attr_parsing_invalid_style)]
+pub(crate) struct InvalidAttrStyle {
+    pub name: AttrPath,
+    pub is_used_as_inner: bool,
+    #[note]
+    pub target_span: Option<Span>,
+    pub target: Target,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_empty_link_name, code = E0454)]
+pub(crate) struct EmptyLinkName {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_link_framework_apple, code = E0455)]
+pub(crate) struct LinkFrameworkApple {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_incompatible_wasm_link)]
+pub(crate) struct IncompatibleWasmLink {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_link_requires_name, code = E0459)]
+pub(crate) struct LinkRequiresName {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_raw_dylib_no_nul)]
+pub(crate) struct RawDylibNoNul {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_raw_dylib_only_windows, code = E0455)]
+pub(crate) struct RawDylibOnlyWindows {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_invalid_link_modifier)]
+pub(crate) struct InvalidLinkModifier {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_multiple_modifiers)]
+pub(crate) struct MultipleModifiers {
+    #[primary_span]
+    pub span: Span,
+    pub modifier: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_import_name_type_x86)]
+pub(crate) struct ImportNameTypeX86 {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_bundle_needs_static)]
+pub(crate) struct BundleNeedsStatic {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_whole_archive_needs_static)]
+pub(crate) struct WholeArchiveNeedsStatic {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_as_needed_compatibility)]
+pub(crate) struct AsNeededCompatibility {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(attr_parsing_import_name_type_raw)]
+pub(crate) struct ImportNameTypeRaw {
+    #[primary_span]
+    pub span: Span,
+}
diff --git a/compiler/rustc_attr_parsing/src/target_checking.rs b/compiler/rustc_attr_parsing/src/target_checking.rs
index 9568b791b3f..edc496b460c 100644
--- a/compiler/rustc_attr_parsing/src/target_checking.rs
+++ b/compiler/rustc_attr_parsing/src/target_checking.rs
@@ -1,13 +1,13 @@
 use std::borrow::Cow;
 
+use rustc_ast::AttrStyle;
 use rustc_errors::DiagArgValue;
-use rustc_feature::Features;
-use rustc_hir::lints::{AttributeLint, AttributeLintKind};
-use rustc_hir::{AttrPath, MethodKind, Target};
-use rustc_span::Span;
+use rustc_feature::{AttributeType, Features};
+use rustc_hir::lints::AttributeLintKind;
+use rustc_hir::{MethodKind, Target};
 
 use crate::AttributeParser;
-use crate::context::Stage;
+use crate::context::{AcceptContext, Stage};
 use crate::session_diagnostics::InvalidTarget;
 
 #[derive(Debug)]
@@ -68,40 +68,36 @@ pub(crate) enum Policy {
     Error(Target),
 }
 
-impl<S: Stage> AttributeParser<'_, S> {
+impl<'sess, S: Stage> AttributeParser<'sess, S> {
     pub(crate) fn check_target(
-        &self,
-        attr_name: AttrPath,
-        attr_span: Span,
         allowed_targets: &AllowedTargets,
         target: Target,
-        target_id: S::Id,
-        mut emit_lint: impl FnMut(AttributeLint<S::Id>),
+        cx: &mut AcceptContext<'_, 'sess, S>,
     ) {
         match allowed_targets.is_allowed(target) {
             AllowedResult::Allowed => {}
             AllowedResult::Warn => {
                 let allowed_targets = allowed_targets.allowed_targets();
-                let (applied, only) =
-                    allowed_targets_applied(allowed_targets, target, self.features);
-                emit_lint(AttributeLint {
-                    id: target_id,
-                    span: attr_span,
-                    kind: AttributeLintKind::InvalidTarget {
-                        name: attr_name,
+                let (applied, only) = allowed_targets_applied(allowed_targets, target, cx.features);
+                let name = cx.attr_path.clone();
+                let attr_span = cx.attr_span;
+                cx.emit_lint(
+                    AttributeLintKind::InvalidTarget {
+                        name,
                         target,
                         only: if only { "only " } else { "" },
                         applied,
                     },
-                });
+                    attr_span,
+                );
             }
             AllowedResult::Error => {
                 let allowed_targets = allowed_targets.allowed_targets();
-                let (applied, only) =
-                    allowed_targets_applied(allowed_targets, target, self.features);
-                self.dcx().emit_err(InvalidTarget {
-                    span: attr_span,
-                    name: attr_name,
+                let (applied, only) = allowed_targets_applied(allowed_targets, target, cx.features);
+                let name = cx.attr_path.clone();
+                cx.dcx().emit_err(InvalidTarget {
+                    span: cx.attr_span.clone(),
+                    name,
                     target: target.plural_name(),
                     only: if only { "only " } else { "" },
                     applied: DiagArgValue::StrListSepByAnd(
@@ -111,6 +107,32 @@ impl<S: Stage> AttributeParser<'_, S> {
             }
         }
     }
+
+    pub(crate) fn check_type(
+        attribute_type: AttributeType,
+        target: Target,
+        cx: &mut AcceptContext<'_, 'sess, S>,
+    ) {
+        let is_crate_root = S::id_is_crate_root(cx.target_id);
+
+        if is_crate_root {
+            return;
+        }
+
+        if attribute_type != AttributeType::CrateLevel {
+            return;
+        }
+
+        let lint = AttributeLintKind::InvalidStyle {
+            name: cx.attr_path.clone(),
+            is_used_as_inner: cx.attr_style == AttrStyle::Inner,
+            target,
+            target_span: cx.target_span,
+        };
+        let attr_span = cx.attr_span;
+
+        cx.emit_lint(lint, attr_span);
+    }
 }
 
 /// Takes a list of `allowed_targets` for an attribute, and the `target` the attribute was applied to.
diff --git a/compiler/rustc_baked_icu_data/Cargo.toml b/compiler/rustc_baked_icu_data/Cargo.toml
index cb0e145386b..2f1ab7df379 100644
--- a/compiler/rustc_baked_icu_data/Cargo.toml
+++ b/compiler/rustc_baked_icu_data/Cargo.toml
@@ -5,9 +5,8 @@ edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
-icu_list = "1.2"
-icu_locid = "1.2"
-icu_locid_transform = "1.3.2"
-icu_provider = { version = "1.2", features = ["sync"] }
-zerovec = "0.10.0"
+icu_list = { version = "2.0", default-features = false }
+icu_locale = { version = "2.0", default-features = false, features = ["compiled_data"] }
+icu_provider = { version = "2.0", features = ["baked", "sync"] }
+zerovec = "0.11.0"
 # tidy-alphabetical-end
diff --git a/compiler/rustc_baked_icu_data/src/data/any.rs b/compiler/rustc_baked_icu_data/src/data/any.rs
deleted file mode 100644
index 23028876676..00000000000
--- a/compiler/rustc_baked_icu_data/src/data/any.rs
+++ /dev/null
@@ -1,2 +0,0 @@
-// @generated
-impl_any_provider!(BakedDataProvider);
diff --git a/compiler/rustc_baked_icu_data/src/data/list_and_v1.rs.data b/compiler/rustc_baked_icu_data/src/data/list_and_v1.rs.data
new file mode 100644
index 00000000000..1d60e0085fc
--- /dev/null
+++ b/compiler/rustc_baked_icu_data/src/data/list_and_v1.rs.data
@@ -0,0 +1,71 @@
+// @generated
+/// Implement `DataProvider<ListAndV1>` on the given struct using the data
+/// hardcoded in this file. This allows the struct to be used with
+/// `icu`'s `_unstable` constructors.
+///
+/// Using this implementation will embed the following data in the binary's data segment:
+/// * 179B for the lookup data structure (33 data identifiers)
+/// * 4183B[^1] for the actual data (11 unique structs)
+///
+/// [^1]: these numbers can be smaller in practice due to linker deduplication
+///
+/// This macro requires the following crates:
+/// * `icu_list`
+/// * `icu_locale/compiled_data`
+/// * `icu_provider`
+/// * `icu_provider/baked`
+/// * `zerovec`
+#[doc(hidden)]
+#[macro_export]
+macro_rules! __impl_list_and_v1 {
+    ($ provider : ty) => {
+        #[clippy::msrv = "1.82"]
+        const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO;
+        #[clippy::msrv = "1.82"]
+        impl $provider {
+            const DATA_LIST_AND_V1: icu_provider::baked::zerotrie::Data<icu_list::provider::ListAndV1> = {
+                const TRIE: icu_provider::baked::zerotrie::ZeroTrieSimpleAscii<&'static [u8]> = icu_provider::baked::zerotrie::ZeroTrieSimpleAscii { store: b"\xC8efijprtz\x18#.9DOZ\xC2ns\n\x1E\xC3NSW\x01\x02\x80\x85\x8A\x1E\xC3NSW\x01\x02\x81\x81\x81r\x1E\xC3NSW\x01\x02\x80\x86\x86t\x1E\xC3NSW\x01\x02\x82\x82\x82a\x1E\xC3NSW\x01\x02\x83\x83\x83t\x1E\xC3NSW\x01\x02\x80\x82\x82u\x1E\xC3NSW\x01\x02\x80\x87\x87r\x1E\xC3NSW\x01\x02\x80\x88\x88h\xC2\x1E-\t\xC3NSW\x01\x02\x83\x89\x89Han\xC2st\n\x1E\xC3NSW\x01\x02\x83\x89\x89\x1E\xC3NSW\x01\x02\x84\x89\x89" };
+                const VALUES: &'static [<icu_list::provider::ListAndV1 as icu_provider::baked::zerotrie::DynamicDataMarker>::DataStruct] = &[icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), special_case: None }, pair: None }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b" y ") }, 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x02\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\0\0\0\x03\0\0\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\0\0\0\0\0\0\0\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\0\0\0\0\x01\0\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x06\0\0\0\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF`\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\x12\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x02\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\x80\x01\0\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\x05\x05\x05\x06\x06\x0C\x0C\r\r\0\0\0\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\x02\0\x1B\0\0\0\0\0\x12\0\0\0\x12\0\0\x03\x06\x06\r\r\0\0\0\0\0h\0\0\0h\0\0\0\0\0\0\x0E\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\x01\n\0\0\x01\x19\0\0\0\x12\0\0\x02\x0F\x11\0\0\0\0\0D\0\0\0\0\0\0\x02\x11\x11\0\0\0\0\0\xBF\0\0\0\0\0\0\x02\x0F\x11\0\0\0\0\0\xBF\0\0\0\0\0\0\x02\x0F\x10\0\0\0\0\0\xBF\0\0\0\0\0\0\x02\x10\x11\0\0\0\0\0\xDD\0\0\0\0\0\0\x02\x0F\x11\0\0\0\0\0\xDD\0\0\0\0\0\0\x02\x0F\x0F\0\0\0\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\0\0\0\0\0\0\0\0\0\x03\0\0\x04\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\0\0\0\0\0\0\0\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\0\0\0\0\x01\0\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x06\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\0\0\0`\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\x12\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b" e ") }, 3u8) }) }, pair: None }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b" e ") }, 3u8), special_case: None }, pair: None }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE3\x80\x81") }, 3u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE3\x80\x81") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE3\x80\x81") }, 3u8), special_case: None }, pair: None }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE3\x80\x81") }, 3u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE3\x80\x81") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE5\x92\x8C") }, 3u8), special_case: None }, pair: Some(icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE3\x80\x81") }, 3u8), special_case: None }) }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", & ") }, 4u8), special_case: None }, pair: Some(icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b" & ") }, 3u8), special_case: None }) }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b" et ") }, 4u8), special_case: None }, pair: None }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b" \xD0\xB8 ") }, 4u8), special_case: None }, pair: None }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b" ve ") }, 4u8), special_case: None }, pair: None }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE3\x80\x81") }, 3u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE3\x80\x81") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b"\xE5\x92\x8C") }, 3u8), special_case: None }, pair: None }, icu_list::provider::ListFormatterPatterns { start: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, 2u8), middle: unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", ") }, end: icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b", and ") }, 6u8), special_case: None }, pair: Some(icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(unsafe { zerovec::VarZeroCow::from_bytes_unchecked(b" and ") }, 5u8), special_case: None }) }];
+                unsafe { icu_provider::baked::zerotrie::Data::from_trie_and_values_unchecked(TRIE, VALUES) }
+            };
+        }
+        #[clippy::msrv = "1.82"]
+        impl icu_provider::DataProvider<icu_list::provider::ListAndV1> for $provider {
+            fn load(&self, req: icu_provider::DataRequest) -> Result<icu_provider::DataResponse<icu_list::provider::ListAndV1>, icu_provider::DataError> {
+                let mut metadata = icu_provider::DataResponseMetadata::default();
+                let payload = if let Some(payload) = icu_provider::baked::DataStore::get(&Self::DATA_LIST_AND_V1, req.id, req.metadata.attributes_prefix_match) {
+                    payload
+                } else {
+                    const FALLBACKER: icu_locale::fallback::LocaleFallbackerWithConfig<'static> = icu_locale::fallback::LocaleFallbacker::new().for_config(<icu_list::provider::ListAndV1 as icu_provider::DataMarker>::INFO.fallback_config);
+                    let mut fallback_iterator = FALLBACKER.fallback_for(req.id.locale.clone());
+                    loop {
+                        if let Some(payload) = icu_provider::baked::DataStore::get(&Self::DATA_LIST_AND_V1, icu_provider::DataIdentifierBorrowed::for_marker_attributes_and_locale(req.id.marker_attributes, fallback_iterator.get()), req.metadata.attributes_prefix_match) {
+                            metadata.locale = Some(fallback_iterator.take());
+                            break payload;
+                        }
+                        if fallback_iterator.get().is_unknown() {
+                            return Err(icu_provider::DataErrorKind::IdentifierNotFound.with_req(<icu_list::provider::ListAndV1 as icu_provider::DataMarker>::INFO, req));
+                        }
+                        fallback_iterator.step();
+                    }
+                };
+                Ok(icu_provider::DataResponse { payload, metadata })
+            }
+        }
+    };
+    ($ provider : ty , ITER) => {
+        __impl_list_and_v1!($provider);
+        #[clippy::msrv = "1.82"]
+        impl icu_provider::IterableDataProvider<icu_list::provider::ListAndV1> for $provider {
+            fn iter_ids(&self) -> Result<std::collections::BTreeSet<icu_provider::DataIdentifierCow<'static>>, icu_provider::DataError> {
+                Ok(icu_provider::baked::DataStore::iter(&Self::DATA_LIST_AND_V1).collect())
+            }
+        }
+    };
+    ($ provider : ty , DRY) => {};
+    ($ provider : ty , DRY , ITER) => {
+        __impl_list_and_v1!($provider, ITER);
+    };
+}
+#[doc(inline)]
+pub use __impl_list_and_v1 as impl_list_and_v1;
diff --git a/compiler/rustc_baked_icu_data/src/data/macros.rs b/compiler/rustc_baked_icu_data/src/data/macros.rs
deleted file mode 100644
index bee309f9b81..00000000000
--- a/compiler/rustc_baked_icu_data/src/data/macros.rs
+++ /dev/null
@@ -1,46 +0,0 @@
-// @generated
-/// Marks a type as a data provider. You can then use macros like
-/// `impl_core_helloworld_v1` to add implementations.
-///
-/// ```ignore
-/// struct MyProvider;
-/// const _: () = {
-///     include!("path/to/generated/macros.rs");
-///     make_provider!(MyProvider);
-///     impl_core_helloworld_v1!(MyProvider);
-/// }
-/// ```
-#[doc(hidden)]
-#[macro_export]
-macro_rules! __make_provider {
-    ($ name : ty) => {
-        #[clippy::msrv = "1.66"]
-        impl $name {
-            #[doc(hidden)]
-            #[allow(dead_code)]
-            pub const MUST_USE_MAKE_PROVIDER_MACRO: () = ();
-        }
-    };
-}
-#[doc(inline)]
-pub use __make_provider as make_provider;
-#[macro_use]
-#[path = "macros/fallback_likelysubtags_v1.data.rs"]
-mod fallback_likelysubtags_v1;
-#[doc(inline)]
-pub use __impl_fallback_likelysubtags_v1 as impl_fallback_likelysubtags_v1;
-#[macro_use]
-#[path = "macros/fallback_parents_v1.data.rs"]
-mod fallback_parents_v1;
-#[doc(inline)]
-pub use __impl_fallback_parents_v1 as impl_fallback_parents_v1;
-#[macro_use]
-#[path = "macros/fallback_supplement_co_v1.data.rs"]
-mod fallback_supplement_co_v1;
-#[doc(inline)]
-pub use __impl_fallback_supplement_co_v1 as impl_fallback_supplement_co_v1;
-#[macro_use]
-#[path = "macros/list_and_v1.data.rs"]
-mod list_and_v1;
-#[doc(inline)]
-pub use __impl_list_and_v1 as impl_list_and_v1;
diff --git a/compiler/rustc_baked_icu_data/src/data/macros/fallback_likelysubtags_v1.data.rs b/compiler/rustc_baked_icu_data/src/data/macros/fallback_likelysubtags_v1.data.rs
deleted file mode 100644
index 1adb58743f7..00000000000
--- a/compiler/rustc_baked_icu_data/src/data/macros/fallback_likelysubtags_v1.data.rs
+++ /dev/null
@@ -1,40 +0,0 @@
-// @generated
-/// Implement `DataProvider<LocaleFallbackLikelySubtagsV1Marker>` on the given struct using the data
-/// hardcoded in this file. This allows the struct to be used with
-/// `icu`'s `_unstable` constructors.
-#[doc(hidden)]
-#[macro_export]
-macro_rules! __impl_fallback_likelysubtags_v1 {
-    ($ provider : ty) => {
-        #[clippy::msrv = "1.66"]
-        const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO;
-        #[clippy::msrv = "1.66"]
-        impl $provider {
-            #[doc(hidden)]
-            pub const SINGLETON_FALLBACK_LIKELYSUBTAGS_V1: &'static <icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker as icu_provider::DataMarker>::Yokeable = &icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1 {
-                l2s: unsafe {
-                    #[allow(unused_unsafe)]
-                    zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"am\0ar\0as\0be\0bg\0bgcbhobn\0brxchrcv\0doiel\0fa\0gu\0he\0hi\0hy\0ja\0ka\0kk\0km\0kn\0ko\0kokks\0ky\0lo\0maimk\0ml\0mn\0mnimr\0my\0ne\0or\0pa\0ps\0rajru\0sa\0satsd\0si\0sr\0ta\0te\0tg\0th\0ti\0tt\0uk\0ur\0yuezh\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"EthiArabBengCyrlCyrlDevaDevaBengDevaCherCyrlDevaGrekArabGujrHebrDevaArmnJpanGeorCyrlKhmrKndaKoreDevaArabCyrlLaooDevaCyrlMlymCyrlBengDevaMymrDevaOryaGuruArabDevaCyrlDevaOlckArabSinhCyrlTamlTeluCyrlThaiEthiCyrlCyrlArabHantHans") })
-                },
-                lr2s: unsafe {
-                    #[allow(unused_unsafe)]
-                    zerovec::ZeroMap2d::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"az\0ha\0kk\0ky\0mn\0ms\0pa\0sd\0sr\0tg\0uz\0yuezh\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"\x03\0\0\0\x05\0\0\0\t\0\0\0\x0B\0\0\0\x0C\0\0\0\r\0\0\0\x0E\0\0\0\x0F\0\0\0\x13\0\0\0\x14\0\0\0\x16\0\0\0\x17\0\0\0&\0\0\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"IQ\0IR\0RU\0CM\0SD\0AF\0CN\0IR\0MN\0CN\0TR\0CN\0CC\0PK\0IN\0ME\0RO\0RU\0TR\0PK\0AF\0CN\0CN\0AU\0BN\0GB\0GF\0HK\0ID\0MO\0PA\0PF\0PH\0SR\0TH\0TW\0US\0VN\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"ArabArabCyrlArabArabArabArabArabArabArabLatnMongArabArabDevaLatnLatnLatnLatnArabArabCyrlHansHantHantHantHantHantHantHantHantHantHantHantHantHantHantHant") })
-                },
-                l2r: unsafe {
-                    #[allow(unused_unsafe)]
-                    zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"af\0am\0ar\0as\0astaz\0be\0bg\0bgcbhobn\0br\0brxbs\0ca\0cebchrcs\0cv\0cy\0da\0de\0doidsbel\0en\0es\0et\0eu\0fa\0ff\0fi\0filfo\0fr\0ga\0gd\0gl\0gu\0ha\0he\0hi\0hr\0hsbhu\0hy\0ia\0id\0ig\0is\0it\0ja\0jv\0ka\0keakgpkk\0km\0kn\0ko\0kokks\0ky\0lo\0lt\0lv\0maimi\0mk\0ml\0mn\0mnimr\0ms\0my\0ne\0nl\0nn\0no\0or\0pa\0pcmpl\0ps\0pt\0qu\0rajrm\0ro\0ru\0sa\0satsc\0sd\0si\0sk\0sl\0so\0sq\0sr\0su\0sv\0sw\0ta\0te\0tg\0th\0ti\0tk\0to\0tr\0tt\0uk\0ur\0uz\0vi\0wo\0xh\0yo\0yrlyuezh\0zu\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"ZA\0ET\0EG\0IN\0ES\0AZ\0BY\0BG\0IN\0IN\0BD\0FR\0IN\0BA\0ES\0PH\0US\0CZ\0RU\0GB\0DK\0DE\0IN\0DE\0GR\0US\0ES\0EE\0ES\0IR\0SN\0FI\0PH\0FO\0FR\0IE\0GB\0ES\0IN\0NG\0IL\0IN\0HR\0DE\0HU\0AM\x00001ID\0NG\0IS\0IT\0JP\0ID\0GE\0CV\0BR\0KZ\0KH\0IN\0KR\0IN\0IN\0KG\0LA\0LT\0LV\0IN\0NZ\0MK\0IN\0MN\0IN\0IN\0MY\0MM\0NP\0NL\0NO\0NO\0IN\0IN\0NG\0PL\0AF\0BR\0PE\0IN\0CH\0RO\0RU\0IN\0IN\0IT\0PK\0LK\0SK\0SI\0SO\0AL\0RS\0ID\0SE\0TZ\0IN\0IN\0TJ\0TH\0ET\0TM\0TO\0TR\0RU\0UA\0PK\0UZ\0VN\0SN\0ZA\0NG\0BR\0HK\0CN\0ZA\0") })
-                },
-                ls2r: unsafe {
-                    #[allow(unused_unsafe)]
-                    zerovec::ZeroMap2d::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"az\0en\0ff\0kk\0ky\0mn\0pa\0sd\0tg\0uz\0yuezh\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"\x01\0\0\0\x02\0\0\0\x03\0\0\0\x04\0\0\0\x06\0\0\0\x07\0\0\0\x08\0\0\0\x0B\0\0\0\x0C\0\0\0\r\0\0\0\x0E\0\0\0\x11\0\0\0") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"ArabShawAdlmArabArabLatnMongArabDevaKhojSindArabArabHansBopoHanbHant") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"IR\0GB\0GN\0CN\0CN\0TR\0CN\0PK\0IN\0IN\0IN\0PK\0AF\0CN\0TW\0TW\0TW\0") })
-                },
-            };
-        }
-        #[clippy::msrv = "1.66"]
-        impl icu_provider::DataProvider<icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker> for $provider {
-            fn load(&self, req: icu_provider::DataRequest) -> Result<icu_provider::DataResponse<icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker>, icu_provider::DataError> {
-                if req.locale.is_empty() { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(Self::SINGLETON_FALLBACK_LIKELYSUBTAGS_V1)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::ExtraneousLocale.with_req(<icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker as icu_provider::KeyedDataMarker>::KEY, req)) }
-            }
-        }
-    };
-}
diff --git a/compiler/rustc_baked_icu_data/src/data/macros/fallback_parents_v1.data.rs b/compiler/rustc_baked_icu_data/src/data/macros/fallback_parents_v1.data.rs
deleted file mode 100644
index 6f8d6590b08..00000000000
--- a/compiler/rustc_baked_icu_data/src/data/macros/fallback_parents_v1.data.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-// @generated
-/// Implement `DataProvider<LocaleFallbackParentsV1Marker>` on the given struct using the data
-/// hardcoded in this file. This allows the struct to be used with
-/// `icu`'s `_unstable` constructors.
-#[doc(hidden)]
-#[macro_export]
-macro_rules! __impl_fallback_parents_v1 {
-    ($ provider : ty) => {
-        #[clippy::msrv = "1.66"]
-        const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO;
-        #[clippy::msrv = "1.66"]
-        impl $provider {
-            #[doc(hidden)]
-            pub const SINGLETON_FALLBACK_PARENTS_V1: &'static <icu_locid_transform::provider::LocaleFallbackParentsV1Marker as icu_provider::DataMarker>::Yokeable = &icu_locid_transform::provider::LocaleFallbackParentsV1 {
-                parents: unsafe {
-                    #[allow(unused_unsafe)]
-                    zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x84\0\0\0\0\0\x06\0\x0B\0\x10\0\x15\0\x1A\0\x1F\0$\0)\0.\x003\08\0=\0B\0G\0L\0Q\0V\0[\0`\0e\0j\0o\0t\0y\0~\0\x83\0\x88\0\x8D\0\x92\0\x97\0\x9C\0\xA1\0\xA6\0\xAB\0\xB0\0\xB5\0\xBA\0\xBF\0\xC4\0\xC9\0\xCE\0\xD3\0\xD8\0\xDD\0\xE2\0\xE7\0\xEC\0\xF1\0\xF6\0\xFB\0\0\x01\x05\x01\n\x01\x0F\x01\x14\x01\x19\x01\x1E\x01#\x01(\x01-\x012\x017\x01<\x01A\x01F\x01K\x01P\x01U\x01Z\x01_\x01d\x01i\x01n\x01s\x01x\x01}\x01\x82\x01\x87\x01\x8C\x01\x91\x01\x96\x01\x9B\x01\xA0\x01\xA5\x01\xAA\x01\xAF\x01\xB4\x01\xB9\x01\xBE\x01\xC3\x01\xC8\x01\xCD\x01\xD2\x01\xD7\x01\xDC\x01\xE1\x01\xE6\x01\xEB\x01\xF0\x01\xF5\x01\xFA\x01\xFF\x01\x04\x02\t\x02\x0E\x02\x13\x02\x18\x02\x1D\x02\"\x02'\x02,\x021\x026\x02;\x02@\x02G\x02I\x02K\x02M\x02R\x02W\x02\\\x02a\x02f\x02k\x02p\x02u\x02z\x02\x7F\x02\x84\x02\x89\x02en-150en-AGen-AIen-ATen-AUen-BBen-BEen-BMen-BSen-BWen-BZen-CCen-CHen-CKen-CMen-CXen-CYen-DEen-DGen-DKen-DMen-ERen-FIen-FJen-FKen-FMen-GBen-GDen-GGen-GHen-GIen-GMen-GYen-HKen-IEen-ILen-IMen-INen-IOen-JEen-JMen-KEen-KIen-KNen-KYen-LCen-LRen-LSen-MGen-MOen-MSen-MTen-MUen-MVen-MWen-MYen-NAen-NFen-NGen-NLen-NRen-NUen-NZen-PGen-PKen-PNen-PWen-RWen-SBen-SCen-SDen-SEen-SGen-SHen-SIen-SLen-SSen-SXen-SZen-TCen-TKen-TOen-TTen-TVen-TZen-UGen-VCen-VGen-VUen-WSen-ZAen-ZMen-ZWes-ARes-BOes-BRes-BZes-CLes-COes-CRes-CUes-DOes-ECes-GTes-HNes-MXes-NIes-PAes-PEes-PRes-PYes-SVes-USes-UYes-VEhi-Latnhtnbnnno-NOpt-AOpt-CHpt-CVpt-FRpt-GQpt-GWpt-LUpt-MOpt-MZpt-STpt-TLzh-Hant-MO") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01150en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001en\0\0\0\0\0\0\x01001es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419es\0\0\0\0\0\0\x01419en\0\0\0\0\0\0\x01IN\0fr\0\0\0\0\0\0\x01HT\0no\0\0\0\0\0\0\0\0\0\0no\0\0\0\0\0\0\0\0\0\0no\0\0\0\0\0\0\0\0\0\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0pt\0\0\0\0\0\0\x01PT\0zh\0\x01Hant\x01HK\0") })
-                },
-            };
-        }
-        #[clippy::msrv = "1.66"]
-        impl icu_provider::DataProvider<icu_locid_transform::provider::LocaleFallbackParentsV1Marker> for $provider {
-            fn load(&self, req: icu_provider::DataRequest) -> Result<icu_provider::DataResponse<icu_locid_transform::provider::LocaleFallbackParentsV1Marker>, icu_provider::DataError> {
-                if req.locale.is_empty() { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(Self::SINGLETON_FALLBACK_PARENTS_V1)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::ExtraneousLocale.with_req(<icu_locid_transform::provider::LocaleFallbackParentsV1Marker as icu_provider::KeyedDataMarker>::KEY, req)) }
-            }
-        }
-    };
-}
diff --git a/compiler/rustc_baked_icu_data/src/data/macros/fallback_supplement_co_v1.data.rs b/compiler/rustc_baked_icu_data/src/data/macros/fallback_supplement_co_v1.data.rs
deleted file mode 100644
index 02eec37ee09..00000000000
--- a/compiler/rustc_baked_icu_data/src/data/macros/fallback_supplement_co_v1.data.rs
+++ /dev/null
@@ -1,32 +0,0 @@
-// @generated
-/// Implement `DataProvider<CollationFallbackSupplementV1Marker>` on the given struct using the data
-/// hardcoded in this file. This allows the struct to be used with
-/// `icu`'s `_unstable` constructors.
-#[doc(hidden)]
-#[macro_export]
-macro_rules! __impl_fallback_supplement_co_v1 {
-    ($ provider : ty) => {
-        #[clippy::msrv = "1.66"]
-        const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO;
-        #[clippy::msrv = "1.66"]
-        impl $provider {
-            #[doc(hidden)]
-            pub const SINGLETON_FALLBACK_SUPPLEMENT_CO_V1: &'static <icu_locid_transform::provider::CollationFallbackSupplementV1Marker as icu_provider::DataMarker>::Yokeable = &icu_locid_transform::provider::LocaleFallbackSupplementV1 {
-                parents: unsafe {
-                    #[allow(unused_unsafe)]
-                    zerovec::ZeroMap::from_parts_unchecked(unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x01\0\0\0\0\0yue") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"zh\0\x01Hant\0\0\0\0") })
-                },
-                unicode_extension_defaults: unsafe {
-                    #[allow(unused_unsafe)]
-                    zerovec::ZeroMap2d::from_parts_unchecked(unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"co") }, unsafe { zerovec::ZeroVec::from_bytes_unchecked(b"\x02\0\0\0") }, unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x02\0\0\0\0\0\x02\0zhzh-Hant") }, unsafe { zerovec::VarZeroVec::from_bytes_unchecked(b"\x02\0\0\0\0\0\x06\0pinyinstroke") })
-                },
-            };
-        }
-        #[clippy::msrv = "1.66"]
-        impl icu_provider::DataProvider<icu_locid_transform::provider::CollationFallbackSupplementV1Marker> for $provider {
-            fn load(&self, req: icu_provider::DataRequest) -> Result<icu_provider::DataResponse<icu_locid_transform::provider::CollationFallbackSupplementV1Marker>, icu_provider::DataError> {
-                if req.locale.is_empty() { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(Self::SINGLETON_FALLBACK_SUPPLEMENT_CO_V1)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::ExtraneousLocale.with_req(<icu_locid_transform::provider::CollationFallbackSupplementV1Marker as icu_provider::KeyedDataMarker>::KEY, req)) }
-            }
-        }
-    };
-}
diff --git a/compiler/rustc_baked_icu_data/src/data/macros/list_and_v1.data.rs b/compiler/rustc_baked_icu_data/src/data/macros/list_and_v1.data.rs
deleted file mode 100644
index 186f706cdb2..00000000000
--- a/compiler/rustc_baked_icu_data/src/data/macros/list_and_v1.data.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-// @generated
-/// Implement `DataProvider<AndListV1Marker>` on the given struct using the data
-/// hardcoded in this file. This allows the struct to be used with
-/// `icu`'s `_unstable` constructors.
-#[doc(hidden)]
-#[macro_export]
-macro_rules! __impl_list_and_v1 {
-    ($ provider : ty) => {
-        #[clippy::msrv = "1.66"]
-        const _: () = <$provider>::MUST_USE_MAKE_PROVIDER_MACRO;
-        #[clippy::msrv = "1.66"]
-        impl icu_provider::DataProvider<icu_list::provider::AndListV1Marker> for $provider {
-            fn load(&self, req: icu_provider::DataRequest) -> Result<icu_provider::DataResponse<icu_list::provider::AndListV1Marker>, icu_provider::DataError> {
-                static EN_001: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]);
-                static EN_IN: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", and ", 6u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]);
-                static IT: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }]);
-                static PT: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]);
-                static FR: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" et ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]);
-                static TR: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" ve ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]);
-                static ES: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" y ", 3u8), special_case: Some(icu_list::provider::SpecialCasePattern { condition: unsafe { icu_list::provider::SerdeDFA::from_dfa_bytes_unchecked(if cfg!(target_endian = "little") { b"rust-regex-automata-dfa-sparse\0\0\xFF\xFE\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B(\x01\0\0\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\x04\0\0\0\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#\0\0\0" } else { b"rust-regex-automata-dfa-sparse\0\0\0\0\xFE\xFF\0\0\0\x02\0\0\0\0\0\0\0\x0E\0\0\0\x01\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01\x02\x02\x02\x03\x04\x04\x05\x06\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x07\x08\t\t\t\n\x0B\x0B\x0C\r\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0E\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x0F\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x12\x12\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x14\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x16\x17\x17\x18\x19\x19\x19\x1A\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\x1B\0\0\x01(\x01\0\0\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x01\x80\0\0\0\0\0\0\x01\0\0\0\0\0\0\0\0\x05\0\x05\x05\x06\x06\x0C\x0C\r\r\0\0S\0\0\0D\0\0\0S\0\0\0D\0\0\0\0\0\0\0\0\x02\0\0\x1B\0\0\x12\0\0\0\x12\0\0\0\0\x03\0\x06\x06\r\r\0\0h\0\0\0h\0\0\0\0\0\0\0\0\x0E\0\0\0\x02\x02\x04\x07\t\t\x0B\x0E\x13\x13\x14\x14\x15\x15\x16\x16\x17\x17\x18\x18\x19\x19\x1A\x1A\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0D\0\0\0\xBF\0\0\0\xCE\0\0\0\xDD\0\0\0\xEC\0\0\0\xDD\0\0\0\xFB\0\0\0\n\x01\0\0\x19\x01\0\0\x12\0\0\0\0\x02\0\x0F\x11\0\0D\0\0\0\0\0\0\0\0\x02\0\x11\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x0F\x10\0\0\xBF\0\0\0\0\0\0\0\0\x02\0\x10\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x11\0\0\xDD\0\0\0\0\0\0\0\0\x02\0\x0F\x0F\0\0\xDD\0\0\0\0\0\0\0\0\0\0\0\x04\0\0\0\0#\0\0\0#\0\0\0#\0\0\0#\0\0\0\0\0\0#\0\0\0\t\0\0\0\x12\0\0\0\x12\0\0\0\0\0\0\0\0\0\0\0#\0\0\0#" }) }, pattern: icu_list::provider::ListJoinerPattern::from_parts(" e ", 3u8) }) }]);
-                static RU: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" и ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]);
-                static UND: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]);
-                static EN: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", and ", 6u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" and ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", & ", 4u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" & ", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }]);
-                static HI_LATN: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", aur ", 6u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" aur ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", aur ", 6u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" aur ", 5u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(", ", 2u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts(" aur ", 5u8), special_case: None }]);
-                static JA: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }]);
-                static ZH_HK: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("及", 3u8), special_case: None }]);
-                static ZH: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }]);
-                static ZH_HANT: <icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable = icu_list::provider::ListFormatterPatternsV1([icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("、", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }, icu_list::provider::ConditionalListJoinerPattern { default: icu_list::provider::ListJoinerPattern::from_parts("和", 3u8), special_case: None }]);
-                static VALUES: [&<icu_list::provider::AndListV1Marker as icu_provider::DataMarker>::Yokeable; 215usize] = [&EN, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_IN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN, &EN_001, &EN_001, &EN_001, &EN_001, &EN_001, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &ES, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &FR, &HI_LATN, &IT, &IT, &IT, &IT, &JA, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &PT, &RU, &RU, &RU, &RU, &RU, &RU, &TR, &TR, &UND, &ZH, &ZH_HK, &ZH, &ZH, &ZH, &ZH_HANT, &ZH_HK, &ZH];
-                static KEYS: [&str; 215usize] = ["en", "en-001", "en-150", "en-AE", "en-AG", "en-AI", "en-AS", "en-AT", "en-AU", "en-BB", "en-BE", "en-BI", "en-BM", "en-BS", "en-BW", "en-BZ", "en-CA", "en-CC", "en-CH", "en-CK", "en-CM", "en-CX", "en-CY", "en-DE", "en-DG", "en-DK", "en-DM", "en-ER", "en-FI", "en-FJ", "en-FK", "en-FM", "en-GB", "en-GD", "en-GG", "en-GH", "en-GI", "en-GM", "en-GU", "en-GY", "en-HK", "en-IE", "en-IL", "en-IM", "en-IN", "en-IO", "en-JE", "en-JM", "en-KE", "en-KI", "en-KN", "en-KY", "en-LC", "en-LR", "en-LS", "en-MG", "en-MH", "en-MO", "en-MP", "en-MS", "en-MT", "en-MU", "en-MV", "en-MW", "en-MY", "en-NA", "en-NF", "en-NG", "en-NL", "en-NR", "en-NU", "en-NZ", "en-PG", "en-PH", "en-PK", "en-PN", "en-PR", "en-PW", "en-RW", "en-SB", "en-SC", "en-SD", "en-SE", "en-SG", "en-SH", "en-SI", "en-SL", "en-SS", "en-SX", "en-SZ", "en-TC", "en-TK", "en-TO", "en-TT", "en-TV", "en-TZ", "en-UG", "en-UM", "en-VC", "en-VG", "en-VI", "en-VU", "en-WS", "en-ZA", "en-ZM", "en-ZW", "es", "es-419", "es-AR", "es-BO", "es-BR", "es-BZ", "es-CL", "es-CO", "es-CR", "es-CU", "es-DO", "es-EA", "es-EC", "es-GQ", "es-GT", "es-HN", "es-IC", "es-MX", "es-NI", "es-PA", "es-PE", "es-PH", "es-PR", "es-PY", "es-SV", "es-US", "es-UY", "es-VE", "fr", "fr-BE", "fr-BF", "fr-BI", "fr-BJ", "fr-BL", "fr-CA", "fr-CD", "fr-CF", "fr-CG", "fr-CH", "fr-CI", "fr-CM", "fr-DJ", "fr-DZ", "fr-GA", "fr-GF", "fr-GN", "fr-GP", "fr-GQ", "fr-HT", "fr-KM", "fr-LU", "fr-MA", "fr-MC", "fr-MF", "fr-MG", "fr-ML", "fr-MQ", "fr-MR", "fr-MU", "fr-NC", "fr-NE", "fr-PF", "fr-PM", "fr-RE", "fr-RW", "fr-SC", "fr-SN", "fr-SY", "fr-TD", "fr-TG", "fr-TN", "fr-VU", "fr-WF", "fr-YT", "hi-Latn", "it", "it-CH", "it-SM", "it-VA", "ja", "pt", "pt-AO", "pt-CH", "pt-CV", "pt-GQ", "pt-GW", "pt-LU", "pt-MO", "pt-MZ", "pt-PT", "pt-ST", "pt-TL", "ru", "ru-BY", "ru-KG", "ru-KZ", "ru-MD", "ru-UA", "tr", "tr-CY", "und", "zh", "zh-HK", "zh-Hans", "zh-Hans-HK", "zh-Hans-MO", "zh-Hant", "zh-MO", "zh-SG"];
-                if let Ok(payload) = KEYS.binary_search_by(|k| req.locale.strict_cmp(k.as_bytes()).reverse()).map(|i| *unsafe { VALUES.get_unchecked(i) }) { Ok(icu_provider::DataResponse { payload: Some(icu_provider::DataPayload::from_static_ref(payload)), metadata: Default::default() }) } else { Err(icu_provider::DataErrorKind::MissingLocale.with_req(<icu_list::provider::AndListV1Marker as icu_provider::KeyedDataMarker>::KEY, req)) }
-            }
-        }
-    };
-}
diff --git a/compiler/rustc_baked_icu_data/src/data/mod.rs b/compiler/rustc_baked_icu_data/src/data/mod.rs
index 465689f0cb8..3146188a8e7 100644
--- a/compiler/rustc_baked_icu_data/src/data/mod.rs
+++ b/compiler/rustc_baked_icu_data/src/data/mod.rs
@@ -1,31 +1,40 @@
 // @generated
-include!("macros.rs");
-macro_rules! impl_data_provider {
-    ($ provider : ty) => {
-        make_provider!($provider);
-        impl_fallback_likelysubtags_v1!($provider);
-        impl_fallback_parents_v1!($provider);
-        impl_fallback_supplement_co_v1!($provider);
-        impl_list_and_v1!($provider);
+include!("list_and_v1.rs.data");
+/// Marks a type as a data provider. You can then use macros like
+/// `impl_core_helloworld_v1` to add implementations.
+///
+/// ```ignore
+/// struct MyProvider;
+/// const _: () = {
+///     include!("path/to/generated/macros.rs");
+///     make_provider!(MyProvider);
+///     impl_core_helloworld_v1!(MyProvider);
+/// }
+/// ```
+#[doc(hidden)]
+#[macro_export]
+macro_rules! __make_provider {
+    ($ name : ty) => {
+        #[clippy::msrv = "1.82"]
+        impl $name {
+            #[allow(dead_code)]
+            pub(crate) const MUST_USE_MAKE_PROVIDER_MACRO: () = ();
+        }
+        icu_provider::marker::impl_data_provider_never_marker!($name);
     };
 }
+#[doc(inline)]
+pub use __make_provider as make_provider;
+/// This macro requires the following crates:
+/// * `icu_list`
+/// * `icu_locale/compiled_data`
+/// * `icu_provider`
+/// * `icu_provider/baked`
+/// * `zerovec`
 #[allow(unused_macros)]
-macro_rules! impl_any_provider {
+macro_rules! impl_data_provider {
     ($ provider : ty) => {
-        #[clippy::msrv = "1.66"]
-        impl icu_provider::AnyProvider for $provider {
-            fn load_any(&self, key: icu_provider::DataKey, req: icu_provider::DataRequest) -> Result<icu_provider::AnyResponse, icu_provider::DataError> {
-                match key.hashed() {
-                    h if h == <icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker as icu_provider::KeyedDataMarker>::KEY.hashed() => icu_provider::DataProvider::<icu_locid_transform::provider::LocaleFallbackLikelySubtagsV1Marker>::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response),
-                    h if h == <icu_locid_transform::provider::LocaleFallbackParentsV1Marker as icu_provider::KeyedDataMarker>::KEY.hashed() => icu_provider::DataProvider::<icu_locid_transform::provider::LocaleFallbackParentsV1Marker>::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response),
-                    h if h == <icu_locid_transform::provider::CollationFallbackSupplementV1Marker as icu_provider::KeyedDataMarker>::KEY.hashed() => icu_provider::DataProvider::<icu_locid_transform::provider::CollationFallbackSupplementV1Marker>::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response),
-                    h if h == <icu_list::provider::AndListV1Marker as icu_provider::KeyedDataMarker>::KEY.hashed() => icu_provider::DataProvider::<icu_list::provider::AndListV1Marker>::load(self, req).map(icu_provider::DataResponse::wrap_into_any_response),
-                    _ => Err(icu_provider::DataErrorKind::MissingDataKey.with_req(key, req)),
-                }
-            }
-        }
+        make_provider!($provider);
+        impl_list_and_v1!($provider);
     };
 }
-#[clippy::msrv = "1.66"]
-pub struct BakedDataProvider;
-impl_data_provider!(BakedDataProvider);
diff --git a/compiler/rustc_baked_icu_data/src/lib.rs b/compiler/rustc_baked_icu_data/src/lib.rs
index f3f6522f575..ea4c8242c62 100644
--- a/compiler/rustc_baked_icu_data/src/lib.rs
+++ b/compiler/rustc_baked_icu_data/src/lib.rs
@@ -14,10 +14,9 @@
 //! To regenerate the data, run this command:
 //!
 //! ```text
-//! icu4x-datagen -W --pretty --fingerprint --use-separate-crates \
-//! --format mod -l en es fr it ja pt ru tr zh zh-Hans zh-Hant \
-//! -k list/and@1 fallback/likelysubtags@1 fallback/parents@1 fallback/supplement/co@1 \
-//! --cldr-tag latest --icuexport-tag latest -o src/data
+//! icu4x-datagen -W --pretty --use-separate-crates \
+//! --format baked --locales @en @es @fr @it @ja @pt @ru @tr @zh @zh-Hans @zh-Hant \
+//! -m ListAndV1 -o src/data
 //! ```
 
 // tidy-alphabetical-start
@@ -29,26 +28,26 @@
 // #![warn(unreachable_pub)] // don't use because this crate is mostly generated code
 // tidy-alphabetical-end
 
-mod data {
-    include!("data/mod.rs");
-    include!("data/any.rs");
-}
+pub struct BakedDataProvider;
 
-pub use data::BakedDataProvider;
+include!("data/mod.rs");
+const _: () = {
+    impl_data_provider!(BakedDataProvider);
+};
 
 pub const fn baked_data_provider() -> BakedDataProvider {
-    data::BakedDataProvider
+    BakedDataProvider
 }
 
 pub mod supported_locales {
-    pub const EN: icu_locid::Locale = icu_locid::locale!("en");
-    pub const ES: icu_locid::Locale = icu_locid::locale!("es");
-    pub const FR: icu_locid::Locale = icu_locid::locale!("fr");
-    pub const IT: icu_locid::Locale = icu_locid::locale!("it");
-    pub const JA: icu_locid::Locale = icu_locid::locale!("ja");
-    pub const PT: icu_locid::Locale = icu_locid::locale!("pt");
-    pub const RU: icu_locid::Locale = icu_locid::locale!("ru");
-    pub const TR: icu_locid::Locale = icu_locid::locale!("tr");
-    pub const ZH_HANS: icu_locid::Locale = icu_locid::locale!("zh-Hans");
-    pub const ZH_HANT: icu_locid::Locale = icu_locid::locale!("zh-Hant");
+    pub const EN: icu_locale::Locale = icu_locale::locale!("en");
+    pub const ES: icu_locale::Locale = icu_locale::locale!("es");
+    pub const FR: icu_locale::Locale = icu_locale::locale!("fr");
+    pub const IT: icu_locale::Locale = icu_locale::locale!("it");
+    pub const JA: icu_locale::Locale = icu_locale::locale!("ja");
+    pub const PT: icu_locale::Locale = icu_locale::locale!("pt");
+    pub const RU: icu_locale::Locale = icu_locale::locale!("ru");
+    pub const TR: icu_locale::Locale = icu_locale::locale!("tr");
+    pub const ZH_HANS: icu_locale::Locale = icu_locale::locale!("zh-Hans");
+    pub const ZH_HANT: icu_locale::Locale = icu_locale::locale!("zh-Hant");
 }
diff --git a/compiler/rustc_borrowck/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml
index 9e7d55180a2..3162e9da1ba 100644
--- a/compiler/rustc_borrowck/Cargo.toml
+++ b/compiler/rustc_borrowck/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2024"
 [dependencies]
 # tidy-alphabetical-start
 either = "1.5.0"
-itertools = "0.12"
+itertools.workspace = true
 polonius-engine = "0.13.0"
 rustc_abi = { path = "../rustc_abi" }
 rustc_data_structures = { path = "../rustc_data_structures" }
@@ -25,5 +25,5 @@ rustc_span = { path = "../rustc_span" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
 rustc_traits = { path = "../rustc_traits" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
index fdca6b56540..fda96dde826 100644
--- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
@@ -565,7 +565,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
         let (blame_constraint, path) = self.regioncx.best_blame_constraint(
             borrow_region,
             NllRegionVariableOrigin::FreeRegion,
-            |r| self.regioncx.provides_universal_region(r, borrow_region, outlived_region),
+            outlived_region,
         );
         let BlameConstraint { category, from_closure, cause, .. } = blame_constraint;
 
diff --git a/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs b/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs
index f77f759035b..99913626418 100644
--- a/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs
@@ -243,10 +243,9 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for FindOpaqueRegion<'_, 'tcx> {
                 let opaque_region_vid = self.regioncx.to_region_vid(opaque_region);
 
                 // Find a path between the borrow region and our opaque capture.
-                if let Some((path, _)) =
-                    self.regioncx.find_constraint_path_between_regions(self.borrow_region, |r| {
-                        r == opaque_region_vid
-                    })
+                if let Some(path) = self
+                    .regioncx
+                    .constraint_path_between_regions(self.borrow_region, opaque_region_vid)
                 {
                     for constraint in path {
                         // If we find a call in this path, then check if it defines the opaque.
diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
index c7d2267e5f7..bec4c934502 100644
--- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs
@@ -61,7 +61,7 @@ impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> {
             | ConstraintCategory::Boring
             | ConstraintCategory::BoringNoLocation
             | ConstraintCategory::Internal
-            | ConstraintCategory::IllegalUniverse => "",
+            | ConstraintCategory::OutlivesUnnameablePlaceholder(..) => "",
         }
     }
 }
@@ -369,11 +369,15 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
                     let error_vid = self.regioncx.region_from_element(longer_fr, &error_element);
 
                     // Find the code to blame for the fact that `longer_fr` outlives `error_fr`.
-                    let (_, cause) = self.regioncx.find_outlives_blame_span(
-                        longer_fr,
-                        NllRegionVariableOrigin::Placeholder(placeholder),
-                        error_vid,
-                    );
+                    let cause = self
+                        .regioncx
+                        .best_blame_constraint(
+                            longer_fr,
+                            NllRegionVariableOrigin::Placeholder(placeholder),
+                            error_vid,
+                        )
+                        .0
+                        .cause;
 
                     let universe = placeholder.universe;
                     let universe_info = self.regioncx.universe_info(universe);
@@ -429,9 +433,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
     ) {
         debug!("report_region_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
 
-        let (blame_constraint, path) = self.regioncx.best_blame_constraint(fr, fr_origin, |r| {
-            self.regioncx.provides_universal_region(r, fr, outlived_fr)
-        });
+        let (blame_constraint, path) =
+            self.regioncx.best_blame_constraint(fr, fr_origin, outlived_fr);
         let BlameConstraint { category, cause, variance_info, .. } = blame_constraint;
 
         debug!("report_region_error: category={:?} {:?} {:?}", category, cause, variance_info);
diff --git a/compiler/rustc_borrowck/src/handle_placeholders.rs b/compiler/rustc_borrowck/src/handle_placeholders.rs
index 4661906fbeb..94379cdebf7 100644
--- a/compiler/rustc_borrowck/src/handle_placeholders.rs
+++ b/compiler/rustc_borrowck/src/handle_placeholders.rs
@@ -1,7 +1,6 @@
 //! Logic for lowering higher-kinded outlives constraints
 //! (with placeholders and universes) and turn them into regular
 //! outlives constraints.
-
 use rustc_data_structures::frozen::Frozen;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::graph::scc;
@@ -10,7 +9,7 @@ use rustc_index::IndexVec;
 use rustc_infer::infer::RegionVariableOrigin;
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::ty::{RegionVid, UniverseIndex};
-use tracing::debug;
+use tracing::{debug, trace};
 
 use crate::constraints::{ConstraintSccIndex, OutlivesConstraintSet};
 use crate::consumers::OutlivesConstraint;
@@ -62,18 +61,71 @@ impl scc::Annotations<RegionVid> for SccAnnotations<'_, '_, RegionTracker> {
     type SccIdx = ConstraintSccIndex;
 }
 
+#[derive(Copy, Debug, Clone, PartialEq, Eq)]
+enum PlaceholderReachability {
+    /// This SCC reaches no placeholders.
+    NoPlaceholders,
+    /// This SCC reaches at least one placeholder.
+    Placeholders {
+        /// The largest-universed placeholder we can reach
+        max_universe: (UniverseIndex, RegionVid),
+
+        /// The placeholder with the smallest ID
+        min_placeholder: RegionVid,
+
+        /// The placeholder with the largest ID
+        max_placeholder: RegionVid,
+    },
+}
+
+impl PlaceholderReachability {
+    /// Merge the reachable placeholders of two graph components.
+    fn merge(self, other: PlaceholderReachability) -> PlaceholderReachability {
+        use PlaceholderReachability::*;
+        match (self, other) {
+            (NoPlaceholders, NoPlaceholders) => NoPlaceholders,
+            (NoPlaceholders, p @ Placeholders { .. })
+            | (p @ Placeholders { .. }, NoPlaceholders) => p,
+            (
+                Placeholders {
+                    min_placeholder: min_pl,
+                    max_placeholder: max_pl,
+                    max_universe: max_u,
+                },
+                Placeholders { min_placeholder, max_placeholder, max_universe },
+            ) => Placeholders {
+                min_placeholder: min_pl.min(min_placeholder),
+                max_placeholder: max_pl.max(max_placeholder),
+                max_universe: max_u.max(max_universe),
+            },
+        }
+    }
+
+    fn max_universe(&self) -> Option<(UniverseIndex, RegionVid)> {
+        match self {
+            Self::NoPlaceholders => None,
+            Self::Placeholders { max_universe, .. } => Some(*max_universe),
+        }
+    }
+
+    /// If we have reached placeholders, determine if they can
+    /// be named from this universe.
+    fn can_be_named_by(&self, from: UniverseIndex) -> bool {
+        self.max_universe()
+            .is_none_or(|(max_placeholder_universe, _)| from.can_name(max_placeholder_universe))
+    }
+}
+
 /// An annotation for region graph SCCs that tracks
 /// the values of its elements. This annotates a single SCC.
 #[derive(Copy, Debug, Clone)]
 pub(crate) struct RegionTracker {
-    /// The largest universe of a placeholder reached from this SCC.
-    /// This includes placeholders within this SCC.
-    max_placeholder_universe_reached: UniverseIndex,
+    reachable_placeholders: PlaceholderReachability,
 
     /// The largest universe nameable from this SCC.
     /// It is the smallest nameable universes of all
-    /// existential regions reachable from it.
-    max_nameable_universe: UniverseIndex,
+    /// existential regions reachable from it. Small Rvids are preferred.
+    max_nameable_universe: (UniverseIndex, RegionVid),
 
     /// The representative Region Variable Id for this SCC.
     pub(crate) representative: Representative,
@@ -81,65 +133,73 @@ pub(crate) struct RegionTracker {
 
 impl RegionTracker {
     pub(crate) fn new(rvid: RegionVid, definition: &RegionDefinition<'_>) -> Self {
-        let placeholder_universe =
+        let reachable_placeholders =
             if matches!(definition.origin, NllRegionVariableOrigin::Placeholder(_)) {
-                definition.universe
+                PlaceholderReachability::Placeholders {
+                    max_universe: (definition.universe, rvid),
+                    min_placeholder: rvid,
+                    max_placeholder: rvid,
+                }
             } else {
-                UniverseIndex::ROOT
+                PlaceholderReachability::NoPlaceholders
             };
 
         Self {
-            max_placeholder_universe_reached: placeholder_universe,
-            max_nameable_universe: definition.universe,
+            reachable_placeholders,
+            max_nameable_universe: (definition.universe, rvid),
             representative: Representative::new(rvid, definition),
         }
     }
 
     /// The largest universe this SCC can name. It's the smallest
-    /// largest nameable uninverse of any reachable region.
+    /// largest nameable universe of any reachable region, or
+    /// `max_nameable(r) = min (max_nameable(r') for r' reachable from r)`
     pub(crate) fn max_nameable_universe(self) -> UniverseIndex {
-        self.max_nameable_universe
+        self.max_nameable_universe.0
     }
 
     pub(crate) fn max_placeholder_universe_reached(self) -> UniverseIndex {
-        self.max_placeholder_universe_reached
-    }
-
-    fn merge_min_max_seen(&mut self, other: &Self) {
-        self.max_placeholder_universe_reached = std::cmp::max(
-            self.max_placeholder_universe_reached,
-            other.max_placeholder_universe_reached,
-        );
-
-        self.max_nameable_universe =
-            std::cmp::min(self.max_nameable_universe, other.max_nameable_universe);
-    }
-
-    /// Returns `true` if during the annotated SCC reaches a placeholder
-    /// with a universe larger than the smallest nameable universe of any
-    /// reachable existential region.
-    pub(crate) fn has_incompatible_universes(&self) -> bool {
-        self.max_nameable_universe().cannot_name(self.max_placeholder_universe_reached)
+        if let Some((universe, _)) = self.reachable_placeholders.max_universe() {
+            universe
+        } else {
+            UniverseIndex::ROOT
+        }
     }
 
     /// Determine if the tracked universes of the two SCCs are compatible.
     pub(crate) fn universe_compatible_with(&self, other: Self) -> bool {
+        // HACK: We first check whether we can name the highest existential universe
+        // of `other`. This only exists to avoid errors in case that scc already
+        // depends on a placeholder it cannot name itself.
         self.max_nameable_universe().can_name(other.max_nameable_universe())
-            || self.max_nameable_universe().can_name(other.max_placeholder_universe_reached)
+            || other.reachable_placeholders.can_be_named_by(self.max_nameable_universe())
+    }
+
+    /// If this SCC reaches a placeholder it can't name, return it.
+    fn unnameable_placeholder(&self) -> Option<(UniverseIndex, RegionVid)> {
+        self.reachable_placeholders.max_universe().filter(|&(placeholder_universe, _)| {
+            !self.max_nameable_universe().can_name(placeholder_universe)
+        })
     }
 }
 
 impl scc::Annotation for RegionTracker {
-    fn merge_scc(mut self, other: Self) -> Self {
-        self.representative = self.representative.merge_scc(other.representative);
-        self.merge_min_max_seen(&other);
-        self
+    fn merge_scc(self, other: Self) -> Self {
+        trace!("{:?} << {:?}", self.representative, other.representative);
+
+        Self {
+            representative: self.representative.min(other.representative),
+            max_nameable_universe: self.max_nameable_universe.min(other.max_nameable_universe),
+            reachable_placeholders: self.reachable_placeholders.merge(other.reachable_placeholders),
+        }
     }
 
-    fn merge_reached(mut self, other: Self) -> Self {
-        // No update to in-component values, only add seen values.
-        self.merge_min_max_seen(&other);
-        self
+    fn merge_reached(self, other: Self) -> Self {
+        Self {
+            max_nameable_universe: self.max_nameable_universe.min(other.max_nameable_universe),
+            reachable_placeholders: self.reachable_placeholders.merge(other.reachable_placeholders),
+            representative: self.representative,
+        }
     }
 }
 
@@ -310,28 +370,52 @@ fn rewrite_placeholder_outlives<'tcx>(
 
         let annotation = annotations[scc];
 
-        // If this SCC participates in a universe violation,
-        // e.g. if it reaches a region with a universe smaller than
-        // the largest region reached, add a requirement that it must
-        // outlive `'static`.
-        if annotation.has_incompatible_universes() {
-            // Optimisation opportunity: this will add more constraints than
-            // needed for correctness, since an SCC upstream of another with
-            // a universe violation will "infect" its downstream SCCs to also
-            // outlive static.
-            let scc_representative_outlives_static = OutlivesConstraint {
-                sup: annotation.representative.rvid(),
-                sub: fr_static,
-                category: ConstraintCategory::IllegalUniverse,
-                locations: Locations::All(rustc_span::DUMMY_SP),
-                span: rustc_span::DUMMY_SP,
-                variance_info: VarianceDiagInfo::None,
-                from_closure: false,
-            };
-            outlives_constraints.push(scc_representative_outlives_static);
-            added_constraints = true;
-            debug!("Added {:?}: 'static!", annotation.representative.rvid());
-        }
+        let Some((max_u, max_u_rvid)) = annotation.unnameable_placeholder() else {
+            continue;
+        };
+
+        debug!(
+            "Placeholder universe {max_u:?} is too large for its SCC, represented by {:?}",
+            annotation.representative
+        );
+
+        // We only add one `r: 'static` constraint per SCC, where `r` is the SCC representative.
+        // That constraint is annotated with some placeholder `unnameable` where
+        // `unnameable` is unnameable from `r` and there is a path in the constraint graph
+        // between them.
+        //
+        // There is one exception; if some other region in this SCC can't name `'r`, then
+        // we pick the region with the smallest universe in the SCC, so that a path can
+        // always start in `'r` to find a motivation that isn't cyclic.
+        let blame_to = if annotation.representative.rvid() == max_u_rvid {
+            // Assertion: the region that lowered our universe is an existential one and we are a placeholder!
+
+            // The SCC's representative is not nameable from some region
+            // that ends up in the SCC.
+            let small_universed_rvid = annotation.max_nameable_universe.1;
+            debug!(
+                "{small_universed_rvid:?} lowered our universe to {:?}",
+                annotation.max_nameable_universe()
+            );
+            small_universed_rvid
+        } else {
+            // `max_u_rvid` is not nameable by the SCC's representative.
+            max_u_rvid
+        };
+
+        // FIXME: if we can extract a useful blame span here, future error
+        // reporting and constraint search can be simplified.
+
+        added_constraints = true;
+        outlives_constraints.push(OutlivesConstraint {
+            sup: annotation.representative.rvid(),
+            sub: fr_static,
+            category: ConstraintCategory::OutlivesUnnameablePlaceholder(blame_to),
+            locations: Locations::All(rustc_span::DUMMY_SP),
+            span: rustc_span::DUMMY_SP,
+            variance_info: VarianceDiagInfo::None,
+            from_closure: false,
+        });
     }
     added_constraints
 }
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index a081e0dee5d..ce78ae203a4 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -300,7 +300,7 @@ fn do_mir_borrowck<'tcx>(
     def: LocalDefId,
 ) -> PropagatedBorrowCheckResults<'tcx> {
     let tcx = root_cx.tcx;
-    let infcx = BorrowckInferCtxt::new(tcx, def);
+    let infcx = BorrowckInferCtxt::new(tcx, def, root_cx.root_def_id());
     let (input_body, promoted) = tcx.mir_promoted(def);
     let input_body: &Body<'_> = &input_body.borrow();
     let input_promoted: &IndexSlice<_, _> = &promoted.borrow();
@@ -590,12 +590,13 @@ fn get_flow_results<'a, 'tcx>(
 
 pub(crate) struct BorrowckInferCtxt<'tcx> {
     pub(crate) infcx: InferCtxt<'tcx>,
-    pub(crate) reg_var_to_origin: RefCell<FxIndexMap<ty::RegionVid, RegionCtxt>>,
+    pub(crate) root_def_id: LocalDefId,
     pub(crate) param_env: ParamEnv<'tcx>,
+    pub(crate) reg_var_to_origin: RefCell<FxIndexMap<ty::RegionVid, RegionCtxt>>,
 }
 
 impl<'tcx> BorrowckInferCtxt<'tcx> {
-    pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self {
+    pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId, root_def_id: LocalDefId) -> Self {
         let typing_mode = if tcx.use_typing_mode_borrowck() {
             TypingMode::borrowck(tcx, def_id)
         } else {
@@ -603,7 +604,12 @@ impl<'tcx> BorrowckInferCtxt<'tcx> {
         };
         let infcx = tcx.infer_ctxt().build(typing_mode);
         let param_env = tcx.param_env(def_id);
-        BorrowckInferCtxt { infcx, reg_var_to_origin: RefCell::new(Default::default()), param_env }
+        BorrowckInferCtxt {
+            infcx,
+            root_def_id,
+            reg_var_to_origin: RefCell::new(Default::default()),
+            param_env,
+        }
     }
 
     pub(crate) fn next_region_var<F>(
diff --git a/compiler/rustc_borrowck/src/region_infer/graphviz.rs b/compiler/rustc_borrowck/src/region_infer/graphviz.rs
index b2f67c43125..526e1850c2e 100644
--- a/compiler/rustc_borrowck/src/region_infer/graphviz.rs
+++ b/compiler/rustc_borrowck/src/region_infer/graphviz.rs
@@ -12,9 +12,13 @@ use rustc_middle::ty::UniverseIndex;
 use super::*;
 
 fn render_outlives_constraint(constraint: &OutlivesConstraint<'_>) -> String {
-    match constraint.locations {
-        Locations::All(_) => "All(...)".to_string(),
-        Locations::Single(loc) => format!("{loc:?}"),
+    if let ConstraintCategory::OutlivesUnnameablePlaceholder(unnameable) = constraint.category {
+        format!("{unnameable:?} unnameable")
+    } else {
+        match constraint.locations {
+            Locations::All(_) => "All(...)".to_string(),
+            Locations::Single(loc) => format!("{loc:?}"),
+        }
     }
 }
 
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs
index 3d95eb4663a..9990f4cb3f2 100644
--- a/compiler/rustc_borrowck/src/region_infer/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/mod.rs
@@ -3,7 +3,7 @@ use std::rc::Rc;
 
 use rustc_data_structures::frozen::Frozen;
 use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
-use rustc_data_structures::graph::scc::{self, Sccs};
+use rustc_data_structures::graph::scc::Sccs;
 use rustc_errors::Diag;
 use rustc_hir::def_id::CRATE_DEF_ID;
 use rustc_index::IndexVec;
@@ -74,18 +74,6 @@ impl Representative {
     }
 }
 
-impl scc::Annotation for Representative {
-    fn merge_scc(self, other: Self) -> Self {
-        // Just pick the smallest one. Note that we order by tag first!
-        std::cmp::min(self, other)
-    }
-
-    // For reachability, we do nothing since the representative doesn't change.
-    fn merge_reached(self, _other: Self) -> Self {
-        self
-    }
-}
-
 pub(crate) type ConstraintSccs = Sccs<RegionVid, ConstraintSccIndex>;
 
 pub struct RegionInferenceContext<'tcx> {
@@ -1285,11 +1273,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         {
             debug!("try_propagate_universal_region_error: fr_minus={:?}", fr_minus);
 
-            let blame_span_category = self.find_outlives_blame_span(
-                longer_fr,
-                NllRegionVariableOrigin::FreeRegion,
-                shorter_fr,
-            );
+            let blame_constraint = self
+                .best_blame_constraint(longer_fr, NllRegionVariableOrigin::FreeRegion, shorter_fr)
+                .0;
 
             // Grow `shorter_fr` until we find some non-local regions. (We
             // always will.)  We'll call them `shorter_fr+` -- they're ever
@@ -1302,8 +1288,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 propagated_outlives_requirements.push(ClosureOutlivesRequirement {
                     subject: ClosureOutlivesSubject::Region(fr_minus),
                     outlived_free_region: fr,
-                    blame_span: blame_span_category.1.span,
-                    category: blame_span_category.0,
+                    blame_span: blame_constraint.cause.span,
+                    category: blame_constraint.category,
                 });
             }
             return RegionRelationCheckResult::Propagated;
@@ -1342,66 +1328,15 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         }
     }
 
-    /// We have a constraint `fr1: fr2` that is not satisfied, where
-    /// `fr2` represents some universal region. Here, `r` is some
-    /// region where we know that `fr1: r` and this function has the
-    /// job of determining whether `r` is "to blame" for the fact that
-    /// `fr1: fr2` is required.
-    ///
-    /// This is true under two conditions:
-    ///
-    /// - `r == fr2`
-    /// - `fr2` is `'static` and `r` is some placeholder in a universe
-    ///   that cannot be named by `fr1`; in that case, we will require
-    ///   that `fr1: 'static` because it is the only way to `fr1: r` to
-    ///   be satisfied. (See `add_incompatible_universe`.)
-    pub(crate) fn provides_universal_region(
+    pub(crate) fn constraint_path_between_regions(
         &self,
-        r: RegionVid,
-        fr1: RegionVid,
-        fr2: RegionVid,
-    ) -> bool {
-        debug!("provides_universal_region(r={:?}, fr1={:?}, fr2={:?})", r, fr1, fr2);
-        let result = {
-            r == fr2 || {
-                fr2 == self.universal_regions().fr_static && self.cannot_name_placeholder(fr1, r)
-            }
-        };
-        debug!("provides_universal_region: result = {:?}", result);
-        result
-    }
-
-    /// If `r2` represents a placeholder region, then this returns
-    /// `true` if `r1` cannot name that placeholder in its
-    /// value; otherwise, returns `false`.
-    pub(crate) fn cannot_name_placeholder(&self, r1: RegionVid, r2: RegionVid) -> bool {
-        match self.definitions[r2].origin {
-            NllRegionVariableOrigin::Placeholder(placeholder) => {
-                let r1_universe = self.definitions[r1].universe;
-                debug!(
-                    "cannot_name_value_of: universe1={r1_universe:?} placeholder={:?}",
-                    placeholder
-                );
-                r1_universe.cannot_name(placeholder.universe)
-            }
-
-            NllRegionVariableOrigin::FreeRegion | NllRegionVariableOrigin::Existential { .. } => {
-                false
-            }
+        from_region: RegionVid,
+        to_region: RegionVid,
+    ) -> Option<Vec<OutlivesConstraint<'tcx>>> {
+        if from_region == to_region {
+            bug!("Tried to find a path between {from_region:?} and itself!");
         }
-    }
-
-    /// Finds a good `ObligationCause` to blame for the fact that `fr1` outlives `fr2`.
-    pub(crate) fn find_outlives_blame_span(
-        &self,
-        fr1: RegionVid,
-        fr1_origin: NllRegionVariableOrigin,
-        fr2: RegionVid,
-    ) -> (ConstraintCategory<'tcx>, ObligationCause<'tcx>) {
-        let BlameConstraint { category, cause, .. } = self
-            .best_blame_constraint(fr1, fr1_origin, |r| self.provides_universal_region(r, fr1, fr2))
-            .0;
-        (category, cause)
+        self.constraint_path_to(from_region, |to| to == to_region, true).map(|o| o.0)
     }
 
     /// Walks the graph of constraints (where `'a: 'b` is considered
@@ -1410,15 +1345,30 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     ///
     /// Returns: a series of constraints as well as the region `R`
     /// that passed the target test.
+    /// If `include_static_outlives_all` is `true`, then the synthetic
+    /// outlives constraints `'static -> a` for every region `a` are
+    /// considered in the search, otherwise they are ignored.
     #[instrument(skip(self, target_test), ret)]
-    pub(crate) fn find_constraint_path_between_regions(
+    pub(crate) fn constraint_path_to(
         &self,
         from_region: RegionVid,
         target_test: impl Fn(RegionVid) -> bool,
+        include_placeholder_static: bool,
     ) -> Option<(Vec<OutlivesConstraint<'tcx>>, RegionVid)> {
-        self.find_constraint_path_between_regions_inner(true, from_region, &target_test).or_else(
-            || self.find_constraint_path_between_regions_inner(false, from_region, &target_test),
+        self.find_constraint_path_between_regions_inner(
+            true,
+            from_region,
+            &target_test,
+            include_placeholder_static,
         )
+        .or_else(|| {
+            self.find_constraint_path_between_regions_inner(
+                false,
+                from_region,
+                &target_test,
+                include_placeholder_static,
+            )
+        })
     }
 
     /// The constraints we get from equating the hidden type of each use of an opaque
@@ -1438,6 +1388,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
         ignore_opaque_type_constraints: bool,
         from_region: RegionVid,
         target_test: impl Fn(RegionVid) -> bool,
+        include_placeholder_static: bool,
     ) -> Option<(Vec<OutlivesConstraint<'tcx>>, RegionVid)> {
         let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions);
         context[from_region] = Trace::StartRegion;
@@ -1452,7 +1403,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
 
         while let Some(r) = deque.pop_front() {
             debug!(
-                "find_constraint_path_between_regions: from_region={:?} r={:?} value={}",
+                "constraint_path_to: from_region={:?} r={:?} value={}",
                 from_region,
                 r,
                 self.region_value_str(r),
@@ -1525,8 +1476,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 // This loop can be hot.
                 for constraint in edges {
                     match constraint.category {
-                        ConstraintCategory::IllegalUniverse => {
-                            debug!("Ignoring illegal universe constraint: {constraint:?}");
+                        ConstraintCategory::OutlivesUnnameablePlaceholder(_)
+                            if !include_placeholder_static =>
+                        {
+                            debug!("Ignoring illegal placeholder constraint: {constraint:?}");
                             continue;
                         }
                         ConstraintCategory::OpaqueType if ignore_opaque_type_constraints => {
@@ -1535,6 +1488,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                         }
                         _ => {}
                     }
+
                     debug_assert_eq!(constraint.sup, r);
                     handle_trace(constraint.sub, Trace::FromGraph(constraint));
                 }
@@ -1549,33 +1503,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     pub(crate) fn find_sub_region_live_at(&self, fr1: RegionVid, location: Location) -> RegionVid {
         trace!(scc = ?self.constraint_sccs.scc(fr1));
         trace!(universe = ?self.max_nameable_universe(self.constraint_sccs.scc(fr1)));
-        self.find_constraint_path_between_regions(fr1, |r| {
-            // First look for some `r` such that `fr1: r` and `r` is live at `location`
+        self.constraint_path_to(fr1, |r| {
             trace!(?r, liveness_constraints=?self.liveness_constraints.pretty_print_live_points(r));
             self.liveness_constraints.is_live_at(r, location)
-        })
-        .or_else(|| {
-            // If we fail to find that, we may find some `r` such that
-            // `fr1: r` and `r` is a placeholder from some universe
-            // `fr1` cannot name. This would force `fr1` to be
-            // `'static`.
-            self.find_constraint_path_between_regions(fr1, |r| self.cannot_name_placeholder(fr1, r))
-        })
-        .or_else(|| {
-            // If we fail to find THAT, it may be that `fr1` is a
-            // placeholder that cannot "fit" into its SCC. In that
-            // case, there should be some `r` where `fr1: r` and `fr1` is a
-            // placeholder that `r` cannot name. We can blame that
-            // edge.
-            //
-            // Remember that if `R1: R2`, then the universe of R1
-            // must be able to name the universe of R2, because R2 will
-            // be at least `'empty(Universe(R2))`, and `R1` must be at
-            // larger than that.
-            self.find_constraint_path_between_regions(fr1, |r| self.cannot_name_placeholder(r, fr1))
-        })
-        .map(|(_path, r)| r)
-        .unwrap()
+        }, true).unwrap().1
     }
 
     /// Get the region outlived by `longer_fr` and live at `element`.
@@ -1619,22 +1550,38 @@ impl<'tcx> RegionInferenceContext<'tcx> {
     /// creating a constraint path that forces `R` to outlive
     /// `from_region`, and then finding the best choices within that
     /// path to blame.
-    #[instrument(level = "debug", skip(self, target_test))]
+    #[instrument(level = "debug", skip(self))]
     pub(crate) fn best_blame_constraint(
         &self,
         from_region: RegionVid,
         from_region_origin: NllRegionVariableOrigin,
-        target_test: impl Fn(RegionVid) -> bool,
+        to_region: RegionVid,
     ) -> (BlameConstraint<'tcx>, Vec<OutlivesConstraint<'tcx>>) {
-        // Find all paths
-        let (path, target_region) = self
-            .find_constraint_path_between_regions(from_region, target_test)
-            .or_else(|| {
-                self.find_constraint_path_between_regions(from_region, |r| {
-                    self.cannot_name_placeholder(from_region, r)
-                })
-            })
-            .unwrap();
+        assert!(from_region != to_region, "Trying to blame a region for itself!");
+
+        let path = self.constraint_path_between_regions(from_region, to_region).unwrap();
+
+        // If we are passing through a constraint added because we reached an unnameable placeholder `'unnameable`,
+        // redirect search towards `'unnameable`.
+        let due_to_placeholder_outlives = path.iter().find_map(|c| {
+            if let ConstraintCategory::OutlivesUnnameablePlaceholder(unnameable) = c.category {
+                Some(unnameable)
+            } else {
+                None
+            }
+        });
+
+        // Edge case: it's possible that `'from_region` is an unnameable placeholder.
+        let path = if let Some(unnameable) = due_to_placeholder_outlives
+            && unnameable != from_region
+        {
+            // We ignore the extra edges due to unnameable placeholders to get
+            // an explanation that was present in the original constraint graph.
+            self.constraint_path_to(from_region, |r| r == unnameable, false).unwrap().0
+        } else {
+            path
+        };
+
         debug!(
             "path={:#?}",
             path.iter()
@@ -1742,7 +1689,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 ConstraintCategory::Cast {
                     unsize_to: Some(unsize_ty),
                     is_implicit_coercion: true,
-                } if target_region == self.universal_regions().fr_static
+                } if to_region == self.universal_regions().fr_static
                     // Mirror the note's condition, to minimize how often this diverts blame.
                     && let ty::Adt(_, args) = unsize_ty.kind()
                     && args.iter().any(|arg| arg.as_type().is_some_and(|ty| ty.is_trait()))
@@ -1780,7 +1727,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
                 // specific, and are not used for relations that would make sense to blame.
                 ConstraintCategory::BoringNoLocation => 6,
                 // Do not blame internal constraints.
-                ConstraintCategory::IllegalUniverse => 7,
+                ConstraintCategory::OutlivesUnnameablePlaceholder(_) => 7,
                 ConstraintCategory::Internal => 8,
             };
 
@@ -1817,6 +1764,14 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             path[best_choice]
         };
 
+        assert!(
+            !matches!(
+                best_constraint.category,
+                ConstraintCategory::OutlivesUnnameablePlaceholder(_)
+            ),
+            "Illegal placeholder constraint blamed; should have redirected to other region relation"
+        );
+
         let blame_constraint = BlameConstraint {
             category: best_constraint.category,
             from_closure: best_constraint.from_closure,
diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs
index 33c4879af98..bee82e17835 100644
--- a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs
+++ b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs
@@ -17,7 +17,7 @@ use rustc_middle::ty::{
 use rustc_mir_dataflow::points::DenseLocationMap;
 use rustc_span::Span;
 use rustc_trait_selection::opaque_types::{
-    InvalidOpaqueTypeArgs, check_opaque_type_parameter_valid,
+    NonDefiningUseReason, opaque_type_has_defining_use_args,
 };
 use rustc_trait_selection::solve::NoSolution;
 use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp;
@@ -42,7 +42,7 @@ use region_ctxt::RegionCtxt;
 /// if there are no `RegionErrors`. If there are region errors, it's likely
 /// that errors here are caused by them and don't need to be handled separately.
 pub(crate) enum DeferredOpaqueTypeError<'tcx> {
-    InvalidOpaqueTypeArgs(InvalidOpaqueTypeArgs<'tcx>),
+    InvalidOpaqueTypeArgs(NonDefiningUseReason<'tcx>),
     LifetimeMismatchOpaqueParam(LifetimeMismatchOpaqueParam<'tcx>),
     UnexpectedHiddenRegion {
         /// The opaque type.
@@ -238,7 +238,7 @@ fn collect_defining_uses<'tcx>(
         let non_nll_opaque_type_key = opaque_type_key.fold_captured_lifetime_args(infcx.tcx, |r| {
             nll_var_to_universal_region(&rcx, r.as_var()).unwrap_or(r)
         });
-        if let Err(err) = check_opaque_type_parameter_valid(
+        if let Err(err) = opaque_type_has_defining_use_args(
             infcx,
             non_nll_opaque_type_key,
             hidden_type.span,
@@ -248,11 +248,10 @@ fn collect_defining_uses<'tcx>(
             // with `TypingMode::Borrowck`.
             if infcx.tcx.use_typing_mode_borrowck() {
                 match err {
-                    InvalidOpaqueTypeArgs::AlreadyReported(guar) => root_cx
-                        .add_concrete_opaque_type(
-                            opaque_type_key.def_id,
-                            OpaqueHiddenType::new_error(infcx.tcx, guar),
-                        ),
+                    NonDefiningUseReason::Tainted(guar) => root_cx.add_concrete_opaque_type(
+                        opaque_type_key.def_id,
+                        OpaqueHiddenType::new_error(infcx.tcx, guar),
+                    ),
                     _ => debug!(?non_nll_opaque_type_key, ?err, "ignoring non-defining use"),
                 }
             } else {
@@ -676,8 +675,8 @@ impl<'tcx> InferCtxt<'tcx> {
         &self,
         opaque_type_key: OpaqueTypeKey<'tcx>,
         instantiated_ty: OpaqueHiddenType<'tcx>,
-    ) -> Result<Ty<'tcx>, InvalidOpaqueTypeArgs<'tcx>> {
-        check_opaque_type_parameter_valid(
+    ) -> Result<Ty<'tcx>, NonDefiningUseReason<'tcx>> {
+        opaque_type_has_defining_use_args(
             self,
             opaque_type_key,
             instantiated_ty.span,
diff --git a/compiler/rustc_borrowck/src/root_cx.rs b/compiler/rustc_borrowck/src/root_cx.rs
index 40c0448cf0b..4e90ae391bb 100644
--- a/compiler/rustc_borrowck/src/root_cx.rs
+++ b/compiler/rustc_borrowck/src/root_cx.rs
@@ -38,6 +38,10 @@ impl<'tcx> BorrowCheckRootCtxt<'tcx> {
         }
     }
 
+    pub(super) fn root_def_id(&self) -> LocalDefId {
+        self.root_def_id
+    }
+
     /// Collect all defining uses of opaque types inside of this typeck root. This
     /// expects the hidden type to be mapped to the definition parameters of the opaque
     /// and errors if we end up with distinct hidden types.
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index a8a48248ffd..2627ed899a9 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -39,7 +39,7 @@ where
     let old_universe = infcx.universe();
 
     let TypeOpOutput { output, constraints: query_constraints, error_info } =
-        op.fully_perform(infcx, locations.span(body))?;
+        op.fully_perform(infcx, infcx.root_def_id, locations.span(body))?;
     if cfg!(debug_assertions) {
         let data = infcx.take_and_reset_region_constraints();
         if !data.is_empty() {
@@ -54,7 +54,6 @@ where
             infcx,
             universal_regions,
             region_bound_pairs,
-            infcx.param_env,
             known_type_outlives_obligations,
             locations,
             locations.span(body),
diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
index 9bb96b94506..703223e2e54 100644
--- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
+++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
@@ -1,10 +1,10 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def_id::LocalDefId;
+use rustc_infer::infer::SubregionOrigin;
 use rustc_infer::infer::canonical::QueryRegionConstraints;
 use rustc_infer::infer::outlives::env::RegionBoundPairs;
 use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
 use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound};
-use rustc_infer::infer::{InferCtxt, SubregionOrigin};
 use rustc_infer::traits::query::type_op::DeeplyNormalize;
 use rustc_middle::bug;
 use rustc_middle::ty::{
@@ -18,10 +18,12 @@ use crate::constraints::OutlivesConstraint;
 use crate::region_infer::TypeTest;
 use crate::type_check::{Locations, MirTypeckRegionConstraints};
 use crate::universal_regions::UniversalRegions;
-use crate::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory};
+use crate::{
+    BorrowckInferCtxt, ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory,
+};
 
 pub(crate) struct ConstraintConversion<'a, 'tcx> {
-    infcx: &'a InferCtxt<'tcx>,
+    infcx: &'a BorrowckInferCtxt<'tcx>,
     universal_regions: &'a UniversalRegions<'tcx>,
     /// Each RBP `GK: 'a` is assumed to be true. These encode
     /// relationships like `T: 'a` that are added via implicit bounds
@@ -34,7 +36,6 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
     /// logic expecting to see (e.g.) `ReStatic`, and if we supplied
     /// our special inference variable there, we would mess that up.
     region_bound_pairs: &'a RegionBoundPairs<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
     known_type_outlives_obligations: &'a [ty::PolyTypeOutlivesPredicate<'tcx>],
     locations: Locations,
     span: Span,
@@ -45,10 +46,9 @@ pub(crate) struct ConstraintConversion<'a, 'tcx> {
 
 impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
     pub(crate) fn new(
-        infcx: &'a InferCtxt<'tcx>,
+        infcx: &'a BorrowckInferCtxt<'tcx>,
         universal_regions: &'a UniversalRegions<'tcx>,
         region_bound_pairs: &'a RegionBoundPairs<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
         known_type_outlives_obligations: &'a [ty::PolyTypeOutlivesPredicate<'tcx>],
         locations: Locations,
         span: Span,
@@ -59,7 +59,6 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
             infcx,
             universal_regions,
             region_bound_pairs,
-            param_env,
             known_type_outlives_obligations,
             locations,
             span,
@@ -286,8 +285,11 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
             ConstraintCategory<'tcx>,
         )>,
     ) -> Ty<'tcx> {
-        match self.param_env.and(DeeplyNormalize { value: ty }).fully_perform(self.infcx, self.span)
-        {
+        match self.infcx.param_env.and(DeeplyNormalize { value: ty }).fully_perform(
+            self.infcx,
+            self.infcx.root_def_id,
+            self.span,
+        ) {
             Ok(TypeOpOutput { output: ty, constraints, .. }) => {
                 // FIXME(higher_ranked_auto): What should we do with the assumptions here?
                 if let Some(QueryRegionConstraints { outlives, assumptions: _ }) = constraints {
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index f642d34ea67..7bf2df91470 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -2,9 +2,9 @@ use rustc_data_structures::frozen::Frozen;
 use rustc_data_structures::transitive_relation::{TransitiveRelation, TransitiveRelationBuilder};
 use rustc_hir::def::DefKind;
 use rustc_infer::infer::canonical::QueryRegionConstraints;
+use rustc_infer::infer::outlives;
 use rustc_infer::infer::outlives::env::RegionBoundPairs;
 use rustc_infer::infer::region_constraints::GenericKind;
-use rustc_infer::infer::{InferCtxt, outlives};
 use rustc_infer::traits::query::type_op::DeeplyNormalize;
 use rustc_middle::mir::ConstraintCategory;
 use rustc_middle::traits::query::OutlivesBound;
@@ -14,6 +14,7 @@ use rustc_trait_selection::traits::query::type_op::{self, TypeOp};
 use tracing::{debug, instrument};
 use type_op::TypeOpOutput;
 
+use crate::BorrowckInferCtxt;
 use crate::type_check::{Locations, MirTypeckRegionConstraints, constraint_conversion};
 use crate::universal_regions::UniversalRegions;
 
@@ -47,14 +48,12 @@ pub(crate) struct CreateResult<'tcx> {
 }
 
 pub(crate) fn create<'tcx>(
-    infcx: &InferCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    infcx: &BorrowckInferCtxt<'tcx>,
     universal_regions: UniversalRegions<'tcx>,
     constraints: &mut MirTypeckRegionConstraints<'tcx>,
 ) -> CreateResult<'tcx> {
     UniversalRegionRelationsBuilder {
         infcx,
-        param_env,
         constraints,
         universal_regions,
         region_bound_pairs: Default::default(),
@@ -177,8 +176,7 @@ impl UniversalRegionRelations<'_> {
 }
 
 struct UniversalRegionRelationsBuilder<'a, 'tcx> {
-    infcx: &'a InferCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
+    infcx: &'a BorrowckInferCtxt<'tcx>,
     universal_regions: UniversalRegions<'tcx>,
     constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
 
@@ -205,7 +203,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
 
         // Insert the `'a: 'b` we know from the predicates.
         // This does not consider the type-outlives.
-        let param_env = self.param_env;
+        let param_env = self.infcx.param_env;
         self.add_outlives_bounds(outlives::explicit_outlives_bounds(param_env));
 
         // - outlives is reflexive, so `'r: 'r` for every region `'r`
@@ -263,7 +261,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
             let TypeOpOutput { output: norm_ty, constraints: constraints_normalize, .. } =
                 param_env
                     .and(DeeplyNormalize { value: ty })
-                    .fully_perform(self.infcx, span)
+                    .fully_perform(self.infcx, self.infcx.root_def_id, span)
                     .unwrap_or_else(|guar| TypeOpOutput {
                         output: Ty::new_error(self.infcx.tcx, guar),
                         constraints: None,
@@ -298,8 +296,9 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
         // Add implied bounds from impl header.
         if matches!(tcx.def_kind(defining_ty_def_id), DefKind::AssocFn | DefKind::AssocConst) {
             for &(ty, _) in tcx.assumed_wf_types(tcx.local_parent(defining_ty_def_id)) {
-                let result: Result<_, ErrorGuaranteed> =
-                    param_env.and(DeeplyNormalize { value: ty }).fully_perform(self.infcx, span);
+                let result: Result<_, ErrorGuaranteed> = param_env
+                    .and(DeeplyNormalize { value: ty })
+                    .fully_perform(self.infcx, self.infcx.root_def_id, span);
                 let Ok(TypeOpOutput { output: norm_ty, constraints: c, .. }) = result else {
                     continue;
                 };
@@ -318,7 +317,6 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
                 self.infcx,
                 &self.universal_regions,
                 &self.region_bound_pairs,
-                param_env,
                 &known_type_outlives_obligations,
                 Locations::All(span),
                 span,
@@ -353,10 +351,11 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
                 output: normalized_outlives,
                 constraints: constraints_normalize,
                 error_info: _,
-            }) = self
-                .param_env
-                .and(DeeplyNormalize { value: outlives })
-                .fully_perform(self.infcx, span)
+            }) = self.infcx.param_env.and(DeeplyNormalize { value: outlives }).fully_perform(
+                self.infcx,
+                self.infcx.root_def_id,
+                span,
+            )
             else {
                 self.infcx.dcx().delayed_bug(format!("could not normalize {outlives:?}"));
                 return;
@@ -381,9 +380,10 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
         span: Span,
     ) -> Option<&'tcx QueryRegionConstraints<'tcx>> {
         let TypeOpOutput { output: bounds, constraints, .. } = self
+            .infcx
             .param_env
             .and(type_op::ImpliedOutlivesBounds { ty })
-            .fully_perform(self.infcx, span)
+            .fully_perform(self.infcx, self.infcx.root_def_id, span)
             .map_err(|_: ErrorGuaranteed| debug!("failed to compute implied bounds {:?}", ty))
             .ok()?;
         debug!(?bounds, ?constraints);
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index 5d30fa71e92..b704d8f0a76 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -640,7 +640,7 @@ impl<'tcx> LivenessContext<'_, '_, 'tcx> {
 
         let op = typeck.infcx.param_env.and(DropckOutlives { dropped_ty });
 
-        match op.fully_perform(typeck.infcx, DUMMY_SP) {
+        match op.fully_perform(typeck.infcx, typeck.root_cx.root_def_id(), DUMMY_SP) {
             Ok(TypeOpOutput { output, constraints, .. }) => {
                 DropData { dropck_result: output, region_constraint_data: constraints }
             }
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 0e1dd5c701f..0d363935f14 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -34,6 +34,7 @@ use rustc_mir_dataflow::points::DenseLocationMap;
 use rustc_span::def_id::CRATE_DEF_ID;
 use rustc_span::source_map::Spanned;
 use rustc_span::{Span, sym};
+use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::query::type_op::custom::scrape_region_constraints;
 use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
 use tracing::{debug, instrument, trace};
@@ -120,7 +121,7 @@ pub(crate) fn type_check<'tcx>(
         region_bound_pairs,
         normalized_inputs_and_output,
         known_type_outlives_obligations,
-    } = free_region_relations::create(infcx, infcx.param_env, universal_regions, &mut constraints);
+    } = free_region_relations::create(infcx, universal_regions, &mut constraints);
 
     let pre_obligations = infcx.take_registered_region_obligations();
     assert!(
@@ -408,7 +409,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             self.infcx,
             self.universal_regions,
             self.region_bound_pairs,
-            self.infcx.param_env,
             self.known_type_outlives_obligations,
             locations,
             locations.span(self.body),
@@ -1455,68 +1455,79 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                     }
                     CastKind::PtrToPtr => {
                         let ty_from = op.ty(self.body, tcx);
-                        let cast_ty_from = CastTy::from_ty(ty_from);
-                        let cast_ty_to = CastTy::from_ty(*ty);
-                        match (cast_ty_from, cast_ty_to) {
-                            (Some(CastTy::Ptr(src)), Some(CastTy::Ptr(dst))) => {
-                                let src_tail = self.struct_tail(src.ty, location);
-                                let dst_tail = self.struct_tail(dst.ty, location);
-
-                                // This checks (lifetime part of) vtable validity for pointer casts,
-                                // which is irrelevant when there are aren't principal traits on
-                                // both sides (aka only auto traits).
-                                //
-                                // Note that other checks (such as denying `dyn Send` -> `dyn
-                                // Debug`) are in `rustc_hir_typeck`.
-                                if let ty::Dynamic(src_tty, _src_lt, ty::Dyn) = *src_tail.kind()
-                                    && let ty::Dynamic(dst_tty, dst_lt, ty::Dyn) = *dst_tail.kind()
-                                    && src_tty.principal().is_some()
-                                    && dst_tty.principal().is_some()
-                                {
-                                    // Remove auto traits.
-                                    // Auto trait checks are handled in `rustc_hir_typeck` as FCW.
-                                    let src_obj = Ty::new_dynamic(
-                                        tcx,
-                                        tcx.mk_poly_existential_predicates(
-                                            &src_tty.without_auto_traits().collect::<Vec<_>>(),
-                                        ),
-                                        // FIXME: Once we disallow casting `*const dyn Trait + 'short`
-                                        // to `*const dyn Trait + 'long`, then this can just be `src_lt`.
-                                        dst_lt,
-                                        ty::Dyn,
-                                    );
-                                    let dst_obj = Ty::new_dynamic(
-                                        tcx,
-                                        tcx.mk_poly_existential_predicates(
-                                            &dst_tty.without_auto_traits().collect::<Vec<_>>(),
-                                        ),
-                                        dst_lt,
-                                        ty::Dyn,
-                                    );
-
-                                    debug!(?src_tty, ?dst_tty, ?src_obj, ?dst_obj);
-
-                                    self.sub_types(
-                                        src_obj,
-                                        dst_obj,
-                                        location.to_locations(),
-                                        ConstraintCategory::Cast {
-                                            is_implicit_coercion: false,
-                                            unsize_to: None,
-                                        },
-                                    )
-                                    .unwrap();
-                                }
-                            }
-                            _ => {
-                                span_mirbug!(
-                                    self,
-                                    rvalue,
-                                    "Invalid PtrToPtr cast {:?} -> {:?}",
-                                    ty_from,
-                                    ty
-                                )
-                            }
+                        let Some(CastTy::Ptr(src)) = CastTy::from_ty(ty_from) else {
+                            unreachable!();
+                        };
+                        let Some(CastTy::Ptr(dst)) = CastTy::from_ty(*ty) else {
+                            unreachable!();
+                        };
+
+                        if self.infcx.type_is_sized_modulo_regions(self.infcx.param_env, dst.ty) {
+                            // Wide to thin ptr cast. This may even occur in an env with
+                            // impossible predicates, such as `where dyn Trait: Sized`.
+                            // In this case, we don't want to fall into the case below,
+                            // since the types may not actually be equatable, but it's
+                            // fine to perform this operation in an impossible env.
+                            let trait_ref = ty::TraitRef::new(
+                                tcx,
+                                tcx.require_lang_item(LangItem::Sized, self.last_span),
+                                [dst.ty],
+                            );
+                            self.prove_trait_ref(
+                                trait_ref,
+                                location.to_locations(),
+                                ConstraintCategory::Cast {
+                                    is_implicit_coercion: true,
+                                    unsize_to: None,
+                                },
+                            );
+                        } else if let ty::Dynamic(src_tty, _src_lt, ty::Dyn) =
+                            *self.struct_tail(src.ty, location).kind()
+                            && let ty::Dynamic(dst_tty, dst_lt, ty::Dyn) =
+                                *self.struct_tail(dst.ty, location).kind()
+                            && src_tty.principal().is_some()
+                            && dst_tty.principal().is_some()
+                        {
+                            // This checks (lifetime part of) vtable validity for pointer casts,
+                            // which is irrelevant when there are aren't principal traits on
+                            // both sides (aka only auto traits).
+                            //
+                            // Note that other checks (such as denying `dyn Send` -> `dyn
+                            // Debug`) are in `rustc_hir_typeck`.
+
+                            // Remove auto traits.
+                            // Auto trait checks are handled in `rustc_hir_typeck` as FCW.
+                            let src_obj = Ty::new_dynamic(
+                                tcx,
+                                tcx.mk_poly_existential_predicates(
+                                    &src_tty.without_auto_traits().collect::<Vec<_>>(),
+                                ),
+                                // FIXME: Once we disallow casting `*const dyn Trait + 'short`
+                                // to `*const dyn Trait + 'long`, then this can just be `src_lt`.
+                                dst_lt,
+                                ty::Dyn,
+                            );
+                            let dst_obj = Ty::new_dynamic(
+                                tcx,
+                                tcx.mk_poly_existential_predicates(
+                                    &dst_tty.without_auto_traits().collect::<Vec<_>>(),
+                                ),
+                                dst_lt,
+                                ty::Dyn,
+                            );
+
+                            debug!(?src_tty, ?dst_tty, ?src_obj, ?dst_obj);
+
+                            self.sub_types(
+                                src_obj,
+                                dst_obj,
+                                location.to_locations(),
+                                ConstraintCategory::Cast {
+                                    is_implicit_coercion: false,
+                                    unsize_to: None,
+                                },
+                            )
+                            .unwrap();
                         }
                     }
                     CastKind::Transmute => {
@@ -2458,12 +2469,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         args: GenericArgsRef<'tcx>,
         locations: Locations,
     ) -> ty::InstantiatedPredicates<'tcx> {
+        let root_def_id = self.root_cx.root_def_id();
         if let Some(closure_requirements) = &self.root_cx.closure_requirements(def_id) {
             constraint_conversion::ConstraintConversion::new(
                 self.infcx,
                 self.universal_regions,
                 self.region_bound_pairs,
-                self.infcx.param_env,
                 self.known_type_outlives_obligations,
                 locations,
                 self.body.span,             // irrelevant; will be overridden.
@@ -2473,9 +2484,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             .apply_closure_requirements(closure_requirements, def_id, args);
         }
 
-        // Now equate closure args to regions inherited from `typeck_root_def_id`. Fixes #98589.
-        let typeck_root_def_id = tcx.typeck_root_def_id(self.body.source.def_id());
-        let typeck_root_args = ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id);
+        // Now equate closure args to regions inherited from `root_def_id`. Fixes #98589.
+        let typeck_root_args = ty::GenericArgs::identity_for_item(tcx, root_def_id);
 
         let parent_args = match tcx.def_kind(def_id) {
             // We don't want to dispatch on 3 different kind of closures here, so take
@@ -2550,17 +2560,14 @@ impl<'tcx> TypeOp<'tcx> for InstantiateOpaqueType<'tcx> {
     fn fully_perform(
         mut self,
         infcx: &InferCtxt<'tcx>,
+        root_def_id: LocalDefId,
         span: Span,
     ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
-        let (mut output, region_constraints) = scrape_region_constraints(
-            infcx,
-            |ocx| {
+        let (mut output, region_constraints) =
+            scrape_region_constraints(infcx, root_def_id, "InstantiateOpaqueType", span, |ocx| {
                 ocx.register_obligations(self.obligations.clone());
                 Ok(())
-            },
-            "InstantiateOpaqueType",
-            span,
-        )?;
+            })?;
         self.region_constraints = Some(region_constraints);
         output.error_info = Some(self);
         Ok(output)
diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml
index e56b9e641a1..9ca44d67150 100644
--- a/compiler/rustc_builtin_macros/Cargo.toml
+++ b/compiler/rustc_builtin_macros/Cargo.toml
@@ -30,6 +30,6 @@ rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.12"
-tracing = "0.1"
+thin-vec.workspace = true
+tracing.workspace = true
 # tidy-alphabetical-end
diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs
index 3e5a26c0556..cf563a53973 100644
--- a/compiler/rustc_builtin_macros/src/format_foreign.rs
+++ b/compiler/rustc_builtin_macros/src/format_foreign.rs
@@ -416,7 +416,7 @@ pub(crate) mod printf {
                         // Yes, this *is* the parameter.
                         Some(('$', end2)) => {
                             state = Flags;
-                            parameter = Some(at.slice_between(end).unwrap().parse().unwrap());
+                            parameter = at.slice_between(end).unwrap().parse().ok();
                             move_to!(end2);
                         }
                         // Wait, no, actually, it's the width.
diff --git a/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml b/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml
index 759d0d59e26..e49c62d6c93 100644
--- a/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml
+++ b/compiler/rustc_codegen_gcc/.github/workflows/m68k.yml
@@ -82,20 +82,16 @@ jobs:
     - name: Build sample project with target defined as JSON spec
       run: |
         ./y.sh prepare --only-libcore --cross
-        ./y.sh build --sysroot --features compiler-builtins-no-f16-f128 --target-triple m68k-unknown-linux-gnu --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
+        ./y.sh build --sysroot --target-triple m68k-unknown-linux-gnu --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
         CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ./y.sh cargo build --manifest-path=./tests/hello-world/Cargo.toml --target ${{ github.workspace }}/target_specs/m68k-unknown-linux-gnu.json
         ./y.sh clean all
 
     - name: Build
       run: |
         ./y.sh prepare --only-libcore --cross
-        ./y.sh build --sysroot --features compiler-builtins-no-f16-f128 --target-triple m68k-unknown-linux-gnu
+        ./y.sh build --sysroot --target-triple m68k-unknown-linux-gnu
         ./y.sh test --mini-tests --target-triple m68k-unknown-linux-gnu
-        # FIXME: since https://github.com/rust-lang/rust/pull/140809, we cannot run programs for architectures not
-        # supported by the object crate, since this adds a dependency on symbols.o for the panic runtime.
-        # And as such, a wrong order of the object files in the linker command now fails with an undefined reference
-        # to some symbols like __rustc::rust_panic.
-        #CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu ./y.sh test --cargo-tests --target-triple m68k-unknown-linux-gnu
+        CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu ./y.sh test --cargo-tests --target-triple m68k-unknown-linux-gnu
         ./y.sh clean all
 
     - name: Prepare dependencies
@@ -104,23 +100,21 @@ jobs:
         git config --global user.name "User"
         ./y.sh prepare --cross
 
-    # FIXME: We cannot run programs for architectures not supported by the object crate. See comment above.
-    #- name: Run tests
-      #run: |
-        #./y.sh test --target-triple m68k-unknown-linux-gnu --release --clean --build-sysroot --sysroot-features compiler-builtins-no-f16-f128 ${{ matrix.commands }}
-
-    # FIXME: We cannot run programs for architectures not supported by the object crate. See comment above.
-    #- name: Run Hello World!
-      #run: |
-        #./y.sh build --target-triple m68k-unknown-linux-gnu
-
-        #vm_dir=$(pwd)/vm
-        #cd tests/hello-world
-        #CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ../../y.sh cargo build --target m68k-unknown-linux-gnu
-        #sudo cp target/m68k-unknown-linux-gnu/debug/hello_world $vm_dir/home/
-        #sudo chroot $vm_dir qemu-m68k-static /home/hello_world > hello_world_stdout
-        #expected_output="40"
-        #test $(cat hello_world_stdout) == $expected_output || (echo "Output differs. Actual output: $(cat hello_world_stdout)"; exit 1)
+    - name: Run tests
+      run: |
+        ./y.sh test --target-triple m68k-unknown-linux-gnu --release --clean --build-sysroot ${{ matrix.commands }}
+
+    - name: Run Hello World!
+      run: |
+        ./y.sh build --target-triple m68k-unknown-linux-gnu
+
+        vm_dir=$(pwd)/vm
+        cd tests/hello-world
+        CG_RUSTFLAGS="-Clinker=m68k-unknown-linux-gnu-gcc" ../../y.sh cargo build --target m68k-unknown-linux-gnu
+        sudo cp target/m68k-unknown-linux-gnu/debug/hello_world $vm_dir/home/
+        sudo chroot $vm_dir qemu-m68k-static /home/hello_world > hello_world_stdout
+        expected_output="40"
+        test $(cat hello_world_stdout) == $expected_output || (echo "Output differs. Actual output: $(cat hello_world_stdout)"; exit 1)
 
   # Summary job for the merge queue.
   # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB!
diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock
index 7f35c1a80bd..a5b972baf98 100644
--- a/compiler/rustc_codegen_gcc/Cargo.lock
+++ b/compiler/rustc_codegen_gcc/Cargo.lock
@@ -56,18 +56,18 @@ dependencies = [
 
 [[package]]
 name = "gccjit"
-version = "2.7.0"
+version = "2.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae99a89184220d967dd300139f2d2ae7d52c1a69d632b24aacc57c54625254ce"
+checksum = "4a0e310ef75f396cd11b2443b353d55376656ca92c13cba36f92b7aff346ac1a"
 dependencies = [
  "gccjit_sys",
 ]
 
 [[package]]
 name = "gccjit_sys"
-version = "0.8.0"
+version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24edb7bfe2b7b27c6d09ed23eebfcab0b359c8fe978433f902943e6f127a0f1b"
+checksum = "95ed7572b30cd32430294dde6fb70822d58e67c6846a548647e8739776a0125b"
 dependencies = [
  "libc",
 ]
diff --git a/compiler/rustc_codegen_gcc/Cargo.toml b/compiler/rustc_codegen_gcc/Cargo.toml
index 193348d1ef6..6031933bd2d 100644
--- a/compiler/rustc_codegen_gcc/Cargo.toml
+++ b/compiler/rustc_codegen_gcc/Cargo.toml
@@ -24,7 +24,7 @@ default = ["master"]
 [dependencies]
 object = { version = "0.37.0", default-features = false, features = ["std", "read"] }
 tempfile = "3.20"
-gccjit = "2.7"
+gccjit = "2.8"
 #gccjit = { git = "https://github.com/rust-lang/gccjit.rs" }
 
 # Local copy.
diff --git a/compiler/rustc_codegen_gcc/build_system/src/fmt.rs b/compiler/rustc_codegen_gcc/build_system/src/fmt.rs
index 7e6594f50f9..91535f217e3 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/fmt.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/fmt.rs
@@ -1,7 +1,7 @@
 use std::ffi::OsStr;
 use std::path::Path;
 
-use crate::utils::run_command_with_output;
+use crate::utils::{run_command_with_output, walk_dir};
 
 fn show_usage() {
     println!(
@@ -32,5 +32,31 @@ pub fn run() -> Result<(), String> {
         if check { &[&"cargo", &"fmt", &"--check"] } else { &[&"cargo", &"fmt"] };
 
     run_command_with_output(cmd, Some(Path::new(".")))?;
-    run_command_with_output(cmd, Some(Path::new("build_system")))
+    run_command_with_output(cmd, Some(Path::new("build_system")))?;
+
+    run_rustfmt_recursively("tests/run", check)
+}
+
+fn run_rustfmt_recursively<P>(dir: P, check: bool) -> Result<(), String>
+where
+    P: AsRef<Path>,
+{
+    walk_dir(
+        dir,
+        &mut |dir| run_rustfmt_recursively(dir, check),
+        &mut |file_path| {
+            if file_path.extension().filter(|ext| ext == &OsStr::new("rs")).is_some() {
+                let rustfmt_cmd: &[&dyn AsRef<OsStr>] = if check {
+                    &[&"rustfmt", &"--check", &file_path]
+                } else {
+                    &[&"rustfmt", &file_path]
+                };
+
+                run_command_with_output(rustfmt_cmd, Some(Path::new(".")))
+            } else {
+                Ok(())
+            }
+        },
+        true,
+    )
 }
diff --git a/compiler/rustc_codegen_gcc/build_system/src/test.rs b/compiler/rustc_codegen_gcc/build_system/src/test.rs
index 2c8271c36a9..3dd3fce2eec 100644
--- a/compiler/rustc_codegen_gcc/build_system/src/test.rs
+++ b/compiler/rustc_codegen_gcc/build_system/src/test.rs
@@ -531,7 +531,7 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result<PathBuf, String> {
             r#"change-id = 115898
 
 [rust]
-codegen-backends = []
+codegen-backends = ["gcc"]
 deny-warnings = false
 verbose-tests = true
 
diff --git a/compiler/rustc_codegen_gcc/libgccjit.version b/compiler/rustc_codegen_gcc/libgccjit.version
index f62154968d3..dc9a0012864 100644
--- a/compiler/rustc_codegen_gcc/libgccjit.version
+++ b/compiler/rustc_codegen_gcc/libgccjit.version
@@ -1 +1 @@
-04ce66d8c918de9273bd7101638ad8724edf5e21
+4e995bd73c4490edfe5080ec6014d63aa9abed5f
diff --git a/compiler/rustc_codegen_gcc/rust-toolchain b/compiler/rustc_codegen_gcc/rust-toolchain
index 058e734be5c..04d33dfb116 100644
--- a/compiler/rustc_codegen_gcc/rust-toolchain
+++ b/compiler/rustc_codegen_gcc/rust-toolchain
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2025-08-03"
+channel = "nightly-2025-08-25"
 components = ["rust-src", "rustc-dev", "llvm-tools-preview"]
diff --git a/compiler/rustc_codegen_gcc/src/back/lto.rs b/compiler/rustc_codegen_gcc/src/back/lto.rs
index d558dfbc1c4..fcee6b6df62 100644
--- a/compiler/rustc_codegen_gcc/src/back/lto.rs
+++ b/compiler/rustc_codegen_gcc/src/back/lto.rs
@@ -29,7 +29,7 @@ use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput};
 use rustc_codegen_ssa::traits::*;
 use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, looks_like_rust_object_file};
 use rustc_data_structures::memmap::Mmap;
-use rustc_errors::{DiagCtxtHandle, FatalError};
+use rustc_errors::DiagCtxtHandle;
 use rustc_middle::bug;
 use rustc_middle::dep_graph::WorkProduct;
 use rustc_session::config::Lto;
@@ -51,12 +51,11 @@ fn prepare_lto(
     cgcx: &CodegenContext<GccCodegenBackend>,
     each_linked_rlib_for_lto: &[PathBuf],
     dcx: DiagCtxtHandle<'_>,
-) -> Result<LtoData, FatalError> {
+) -> LtoData {
     let tmp_path = match tempdir() {
         Ok(tmp_path) => tmp_path,
         Err(error) => {
-            eprintln!("Cannot create temporary directory: {}", error);
-            return Err(FatalError);
+            dcx.fatal(format!("Cannot create temporary directory: {}", error));
         }
     };
 
@@ -91,15 +90,14 @@ fn prepare_lto(
                         upstream_modules.push((module, CString::new(name).unwrap()));
                     }
                     Err(e) => {
-                        dcx.emit_err(e);
-                        return Err(FatalError);
+                        dcx.emit_fatal(e);
                     }
                 }
             }
         }
     }
 
-    Ok(LtoData { upstream_modules, tmp_path })
+    LtoData { upstream_modules, tmp_path }
 }
 
 fn save_as_file(obj: &[u8], path: &Path) -> Result<(), LtoBitcodeFromRlib> {
@@ -114,10 +112,10 @@ pub(crate) fn run_fat(
     cgcx: &CodegenContext<GccCodegenBackend>,
     each_linked_rlib_for_lto: &[PathBuf],
     modules: Vec<FatLtoInput<GccCodegenBackend>>,
-) -> Result<ModuleCodegen<GccContext>, FatalError> {
+) -> ModuleCodegen<GccContext> {
     let dcx = cgcx.create_dcx();
     let dcx = dcx.handle();
-    let lto_data = prepare_lto(cgcx, each_linked_rlib_for_lto, dcx)?;
+    let lto_data = prepare_lto(cgcx, each_linked_rlib_for_lto, dcx);
     /*let symbols_below_threshold =
     lto_data.symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::<Vec<_>>();*/
     fat_lto(
@@ -137,7 +135,7 @@ fn fat_lto(
     mut serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
     tmp_path: TempDir,
     //symbols_below_threshold: &[String],
-) -> Result<ModuleCodegen<GccContext>, FatalError> {
+) -> ModuleCodegen<GccContext> {
     let _timer = cgcx.prof.generic_activity("GCC_fat_lto_build_monolithic_module");
     info!("going for a fat lto");
 
@@ -261,7 +259,7 @@ fn fat_lto(
     // of now.
     module.module_llvm.temp_dir = Some(tmp_path);
 
-    Ok(module)
+    module
 }
 
 pub struct ModuleBuffer(PathBuf);
@@ -286,10 +284,10 @@ pub(crate) fn run_thin(
     each_linked_rlib_for_lto: &[PathBuf],
     modules: Vec<(String, ThinBuffer)>,
     cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
-) -> Result<(Vec<ThinModule<GccCodegenBackend>>, Vec<WorkProduct>), FatalError> {
+) -> (Vec<ThinModule<GccCodegenBackend>>, Vec<WorkProduct>) {
     let dcx = cgcx.create_dcx();
     let dcx = dcx.handle();
-    let lto_data = prepare_lto(cgcx, each_linked_rlib_for_lto, dcx)?;
+    let lto_data = prepare_lto(cgcx, each_linked_rlib_for_lto, dcx);
     if cgcx.opts.cg.linker_plugin_lto.enabled() {
         unreachable!(
             "We should never reach this case if the LTO step \
@@ -355,7 +353,7 @@ fn thin_lto(
     tmp_path: TempDir,
     cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
     //_symbols_below_threshold: &[String],
-) -> Result<(Vec<ThinModule<GccCodegenBackend>>, Vec<WorkProduct>), FatalError> {
+) -> (Vec<ThinModule<GccCodegenBackend>>, Vec<WorkProduct>) {
     let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_global_analysis");
     info!("going for that thin, thin LTO");
 
@@ -518,13 +516,13 @@ fn thin_lto(
     // TODO: save the directory so that it gets deleted later.
     std::mem::forget(tmp_path);
 
-    Ok((opt_jobs, copy_jobs))
+    (opt_jobs, copy_jobs)
 }
 
 pub fn optimize_thin_module(
     thin_module: ThinModule<GccCodegenBackend>,
     _cgcx: &CodegenContext<GccCodegenBackend>,
-) -> Result<ModuleCodegen<GccContext>, FatalError> {
+) -> ModuleCodegen<GccContext> {
     //let dcx = cgcx.create_dcx();
 
     //let module_name = &thin_module.shared.module_names[thin_module.idx];
@@ -634,7 +632,8 @@ pub fn optimize_thin_module(
             save_temp_bitcode(cgcx, &module, "thin-lto-after-pm");
         }
     }*/
-    Ok(module)
+    #[allow(clippy::let_and_return)]
+    module
 }
 
 pub struct ThinBuffer {
diff --git a/compiler/rustc_codegen_gcc/src/back/write.rs b/compiler/rustc_codegen_gcc/src/back/write.rs
index c1231142c65..84bc7016271 100644
--- a/compiler/rustc_codegen_gcc/src/back/write.rs
+++ b/compiler/rustc_codegen_gcc/src/back/write.rs
@@ -6,7 +6,6 @@ use rustc_codegen_ssa::back::write::{BitcodeSection, CodegenContext, EmitObj, Mo
 use rustc_codegen_ssa::{CompiledModule, ModuleCodegen};
 use rustc_fs_util::link_or_copy;
 use rustc_session::config::OutputType;
-use rustc_span::fatal_error::FatalError;
 use rustc_target::spec::SplitDebuginfo;
 
 use crate::base::add_pic_option;
@@ -17,7 +16,7 @@ pub(crate) fn codegen(
     cgcx: &CodegenContext<GccCodegenBackend>,
     module: ModuleCodegen<GccContext>,
     config: &ModuleConfig,
-) -> Result<CompiledModule, FatalError> {
+) -> CompiledModule {
     let dcx = cgcx.create_dcx();
     let dcx = dcx.handle();
 
@@ -246,7 +245,7 @@ pub(crate) fn codegen(
         }
     }
 
-    Ok(module.into_compiled_module(
+    module.into_compiled_module(
         config.emit_obj != EmitObj::None,
         cgcx.target_can_use_split_dwarf && cgcx.split_debuginfo == SplitDebuginfo::Unpacked,
         config.emit_bc,
@@ -254,7 +253,7 @@ pub(crate) fn codegen(
         config.emit_ir,
         &cgcx.output_filenames,
         cgcx.invocation_temp.as_deref(),
-    ))
+    )
 }
 
 pub(crate) fn save_temp_bitcode(
diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
index fdc15d580ef..41363d6313d 100644
--- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
+++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs
@@ -1497,7 +1497,6 @@ fn simd_funnel_shift<'a, 'gcc, 'tcx>(
         let index = bx.context.new_rvalue_from_int(bx.int_type, i as i32);
         let a_val = bx.context.new_vector_access(None, a, index).to_rvalue();
         let a_val = bx.context.new_bitcast(None, a_val, unsigned_type);
-        // TODO: we probably need to use gcc_int_cast instead.
         let a_val = bx.gcc_int_cast(a_val, new_int_type);
         let b_val = bx.context.new_vector_access(None, b, index).to_rvalue();
         let b_val = bx.context.new_bitcast(None, b_val, unsigned_type);
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index 4025aba82da..2d7df79ba95 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -110,7 +110,6 @@ use rustc_middle::util::Providers;
 use rustc_session::Session;
 use rustc_session::config::{OptLevel, OutputFilenames};
 use rustc_span::Symbol;
-use rustc_span::fatal_error::FatalError;
 use rustc_target::spec::RelocModel;
 use tempfile::TempDir;
 
@@ -362,7 +361,7 @@ impl WriteBackendMethods for GccCodegenBackend {
         _exported_symbols_for_lto: &[String],
         each_linked_rlib_for_lto: &[PathBuf],
         modules: Vec<FatLtoInput<Self>>,
-    ) -> Result<ModuleCodegen<Self::Module>, FatalError> {
+    ) -> ModuleCodegen<Self::Module> {
         back::lto::run_fat(cgcx, each_linked_rlib_for_lto, modules)
     }
 
@@ -373,7 +372,7 @@ impl WriteBackendMethods for GccCodegenBackend {
         each_linked_rlib_for_lto: &[PathBuf],
         modules: Vec<(String, Self::ThinBuffer)>,
         cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
-    ) -> Result<(Vec<ThinModule<Self>>, Vec<WorkProduct>), FatalError> {
+    ) -> (Vec<ThinModule<Self>>, Vec<WorkProduct>) {
         back::lto::run_thin(cgcx, each_linked_rlib_for_lto, modules, cached_modules)
     }
 
@@ -390,15 +389,14 @@ impl WriteBackendMethods for GccCodegenBackend {
         _dcx: DiagCtxtHandle<'_>,
         module: &mut ModuleCodegen<Self::Module>,
         config: &ModuleConfig,
-    ) -> Result<(), FatalError> {
+    ) {
         module.module_llvm.context.set_optimization_level(to_gcc_opt_level(config.opt_level));
-        Ok(())
     }
 
     fn optimize_thin(
         cgcx: &CodegenContext<Self>,
         thin: ThinModule<Self>,
-    ) -> Result<ModuleCodegen<Self::Module>, FatalError> {
+    ) -> ModuleCodegen<Self::Module> {
         back::lto::optimize_thin_module(thin, cgcx)
     }
 
@@ -406,7 +404,7 @@ impl WriteBackendMethods for GccCodegenBackend {
         cgcx: &CodegenContext<Self>,
         module: ModuleCodegen<Self::Module>,
         config: &ModuleConfig,
-    ) -> Result<CompiledModule, FatalError> {
+    ) -> CompiledModule {
         back::write::codegen(cgcx, module, config)
     }
 
diff --git a/compiler/rustc_codegen_gcc/tests/failing-run-make-tests.txt b/compiler/rustc_codegen_gcc/tests/failing-run-make-tests.txt
index 29032b321fa..c5e22970c66 100644
--- a/compiler/rustc_codegen_gcc/tests/failing-run-make-tests.txt
+++ b/compiler/rustc_codegen_gcc/tests/failing-run-make-tests.txt
@@ -6,7 +6,6 @@ tests/run-make/doctests-keep-binaries/
 tests/run-make/doctests-runtool/
 tests/run-make/emit-shared-files/
 tests/run-make/exit-code/
-tests/run-make/issue-64153/
 tests/run-make/llvm-ident/
 tests/run-make/native-link-modifier-bundle/
 tests/run-make/remap-path-prefix-dwarf/
@@ -34,8 +33,6 @@ tests/run-make/c-link-to-rust-staticlib/
 tests/run-make/foreign-double-unwind/
 tests/run-make/foreign-exceptions/
 tests/run-make/glibc-staticlib-args/
-tests/run-make/issue-36710/
-tests/run-make/issue-68794-textrel-on-minimal-lib/
 tests/run-make/lto-smoke-c/
 tests/run-make/return-non-c-like-enum/
 
diff --git a/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt b/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt
index 41fb4729c07..e2615bce190 100644
--- a/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt
+++ b/compiler/rustc_codegen_gcc/tests/failing-ui-tests.txt
@@ -20,7 +20,7 @@ tests/ui/drop/dynamic-drop.rs
 tests/ui/rfcs/rfc-2091-track-caller/std-panic-locations.rs
 tests/ui/simd/issue-17170.rs
 tests/ui/simd/issue-39720.rs
-tests/ui/issues/issue-14875.rs
+tests/ui/drop/panic-during-drop-14875.rs
 tests/ui/issues/issue-29948.rs
 tests/ui/process/println-with-broken-pipe.rs
 tests/ui/lto/thin-lto-inlines2.rs
@@ -86,3 +86,5 @@ tests/ui/panics/unwind-force-no-unwind-tables.rs
 tests/ui/attributes/fn-align-dyn.rs
 tests/ui/linkage-attr/raw-dylib/elf/glibc-x86_64.rs
 tests/ui/explicit-tail-calls/recursion-etc.rs
+tests/ui/explicit-tail-calls/indexer.rs
+tests/ui/explicit-tail-calls/drop-order.rs
diff --git a/compiler/rustc_codegen_gcc/tests/run/int.rs b/compiler/rustc_codegen_gcc/tests/run/int.rs
index e20ecc23679..78675acb544 100644
--- a/compiler/rustc_codegen_gcc/tests/run/int.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/int.rs
@@ -7,12 +7,10 @@ fn main() {
     use std::hint::black_box;
 
     macro_rules! check {
-        ($ty:ty, $expr:expr) => {
-            {
-                const EXPECTED: $ty = $expr;
-                assert_eq!($expr, EXPECTED);
-            }
-        };
+        ($ty:ty, $expr:expr) => {{
+            const EXPECTED: $ty = $expr;
+            assert_eq!($expr, EXPECTED);
+        }};
     }
 
     check!(u32, (2220326408_u32 + black_box(1)) >> (32 - 6));
diff --git a/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs b/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs
index 78872159f62..78e1cac57e0 100644
--- a/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/int_overflow.rs
@@ -12,7 +12,7 @@ fn main() {
 
     let arg_count = std::env::args().count();
     let int = isize::MAX;
-    let _int = int + arg_count as isize;  // overflow
+    let _int = int + arg_count as isize; // overflow
 
     // If overflow checking is disabled, we should reach here.
     #[cfg(not(debug_assertions))]
diff --git a/compiler/rustc_codegen_gcc/tests/run/structs.rs b/compiler/rustc_codegen_gcc/tests/run/structs.rs
index da73cbed9ae..e08e67837be 100644
--- a/compiler/rustc_codegen_gcc/tests/run/structs.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/structs.rs
@@ -27,12 +27,8 @@ fn one() -> isize {
 
 #[no_mangle]
 extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 {
-    let test = Test {
-        field: one(),
-    };
-    let two = Two {
-        two: 2,
-    };
+    let test = Test { field: one() };
+    let two = Two { two: 2 };
     unsafe {
         libc::printf(b"%ld\n\0" as *const u8 as *const i8, test.field);
         libc::printf(b"%ld\n\0" as *const u8 as *const i8, two.two);
diff --git a/compiler/rustc_codegen_gcc/tests/run/volatile.rs b/compiler/rustc_codegen_gcc/tests/run/volatile.rs
index 94a7bdc5c06..dc11fbfa600 100644
--- a/compiler/rustc_codegen_gcc/tests/run/volatile.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/volatile.rs
@@ -12,15 +12,11 @@ struct Struct {
     func: unsafe fn(*const ()),
 }
 
-fn func(_ptr: *const ()) {
-}
+fn func(_ptr: *const ()) {}
 
 fn main() {
     let mut x = MaybeUninit::<&Struct>::uninit();
-    x.write(&Struct {
-        pointer: std::ptr::null(),
-        func,
-    });
+    x.write(&Struct { pointer: std::ptr::null(), func });
     let x = unsafe { x.assume_init() };
     let value = unsafe { (x as *const Struct).read_volatile() };
     println!("{:?}", value);
diff --git a/compiler/rustc_codegen_gcc/tests/run/volatile2.rs b/compiler/rustc_codegen_gcc/tests/run/volatile2.rs
index bdcb8259878..ada112687d3 100644
--- a/compiler/rustc_codegen_gcc/tests/run/volatile2.rs
+++ b/compiler/rustc_codegen_gcc/tests/run/volatile2.rs
@@ -7,7 +7,14 @@ mod libc {
     #[link(name = "c")]
     extern "C" {
         pub fn sigaction(signum: i32, act: *const sigaction, oldact: *mut sigaction) -> i32;
-        pub fn mmap(addr: *mut (), len: usize, prot: i32, flags: i32, fd: i32, offset: i64) -> *mut ();
+        pub fn mmap(
+            addr: *mut (),
+            len: usize,
+            prot: i32,
+            flags: i32,
+            fd: i32,
+            offset: i64,
+        ) -> *mut ();
         pub fn mprotect(addr: *mut (), len: usize, prot: i32) -> i32;
     }
 
@@ -54,7 +61,8 @@ fn main() {
             libc::MAP_PRIVATE | libc::MAP_ANONYMOUS,
             -1,
             0,
-        ).cast();
+        )
+        .cast();
         if STORAGE == libc::MAP_FAILED {
             panic!("error: mmap failed");
         }
diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml
index 2d11628250c..26d20acbe28 100644
--- a/compiler/rustc_codegen_llvm/Cargo.toml
+++ b/compiler/rustc_codegen_llvm/Cargo.toml
@@ -8,11 +8,11 @@ test = false
 
 [dependencies]
 # tidy-alphabetical-start
-bitflags = "2.4.1"
+bitflags.workspace = true
 # To avoid duplicate dependencies, this should match the version of gimli used
 # by `rustc_codegen_ssa` via its `thorin-dwp` dependency.
 gimli = "0.31"
-itertools = "0.12"
+itertools.workspace = true
 libc = "0.2"
 measureme = "12.0.1"
 object = { version = "0.37.0", default-features = false, features = ["std", "read"] }
@@ -40,7 +40,7 @@ rustc_target = { path = "../rustc_target" }
 serde = { version = "1", features = ["derive"] }
 serde_json = "1"
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
 
 [features]
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index 399f8b6e762..ac7583f5666 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -44,7 +44,7 @@ const ABI_AFFECTING_ATTRIBUTES: [(ArgAttribute, llvm::AttributeKind); 1] =
 
 const OPTIMIZATION_ATTRIBUTES: [(ArgAttribute, llvm::AttributeKind); 6] = [
     (ArgAttribute::NoAlias, llvm::AttributeKind::NoAlias),
-    (ArgAttribute::NoCapture, llvm::AttributeKind::NoCapture),
+    (ArgAttribute::CapturesAddress, llvm::AttributeKind::CapturesAddress),
     (ArgAttribute::NonNull, llvm::AttributeKind::NonNull),
     (ArgAttribute::ReadOnly, llvm::AttributeKind::ReadOnly),
     (ArgAttribute::NoUndef, llvm::AttributeKind::NoUndef),
@@ -84,8 +84,10 @@ fn get_attrs<'ll>(this: &ArgAttributes, cx: &CodegenCx<'ll, '_>) -> SmallVec<[&'
         }
         for (attr, llattr) in OPTIMIZATION_ATTRIBUTES {
             if regular.contains(attr) {
-                // captures(address, read_provenance) is only available since LLVM 21.
-                if attr == ArgAttribute::CapturesReadOnly && llvm_util::get_version() < (21, 0, 0) {
+                // captures(...) is only available since LLVM 21.
+                if (attr == ArgAttribute::CapturesReadOnly || attr == ArgAttribute::CapturesAddress)
+                    && llvm_util::get_version() < (21, 0, 0)
+                {
                     continue;
                 }
                 attrs.push(llattr.create_attr(cx.llcx));
diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs
index 23610aa856c..df3e49279d9 100644
--- a/compiler/rustc_codegen_llvm/src/allocator.rs
+++ b/compiler/rustc_codegen_llvm/src/allocator.rs
@@ -12,7 +12,7 @@ use smallvec::SmallVec;
 
 use crate::builder::SBuilder;
 use crate::declare::declare_simple_fn;
-use crate::llvm::{self, False, True, Type, Value};
+use crate::llvm::{self, FALSE, TRUE, Type, Value};
 use crate::{SimpleCx, attributes, debuginfo, llvm_util};
 
 pub(crate) unsafe fn codegen(
@@ -80,7 +80,7 @@ pub(crate) unsafe fn codegen(
             &cx,
             &mangle_internal_symbol(tcx, OomStrategy::SYMBOL),
             &i8,
-            &llvm::LLVMConstInt(i8, tcx.sess.opts.unstable_opts.oom.should_panic() as u64, False),
+            &llvm::LLVMConstInt(i8, tcx.sess.opts.unstable_opts.oom.should_panic() as u64, FALSE),
         );
 
         // __rust_no_alloc_shim_is_unstable_v2
@@ -201,7 +201,7 @@ fn create_wrapper_function(
             .map(|(i, _)| llvm::get_param(llfn, i as c_uint))
             .collect::<Vec<_>>();
         let ret = bx.call(ty, callee, &args, None);
-        llvm::LLVMSetTailCall(ret, True);
+        llvm::LLVMSetTailCall(ret, TRUE);
         if output.is_some() {
             bx.ret(ret);
         } else {
diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs
index a643a91141e..38c1d3b53e8 100644
--- a/compiler/rustc_codegen_llvm/src/asm.rs
+++ b/compiler/rustc_codegen_llvm/src/asm.rs
@@ -16,6 +16,7 @@ use tracing::debug;
 use crate::builder::Builder;
 use crate::common::Funclet;
 use crate::context::CodegenCx;
+use crate::llvm::ToLlvmBool;
 use crate::type_::Type;
 use crate::type_of::LayoutLlvmExt;
 use crate::value::Value;
@@ -470,10 +471,6 @@ pub(crate) fn inline_asm_call<'ll>(
     dest: Option<&'ll llvm::BasicBlock>,
     catch_funclet: Option<(&'ll llvm::BasicBlock, Option<&Funclet<'ll>>)>,
 ) -> Option<&'ll Value> {
-    let volatile = if volatile { llvm::True } else { llvm::False };
-    let alignstack = if alignstack { llvm::True } else { llvm::False };
-    let can_throw = if unwind { llvm::True } else { llvm::False };
-
     let argtys = inputs
         .iter()
         .map(|v| {
@@ -500,10 +497,10 @@ pub(crate) fn inline_asm_call<'ll>(
             asm.len(),
             cons.as_ptr(),
             cons.len(),
-            volatile,
-            alignstack,
+            volatile.to_llvm_bool(),
+            alignstack.to_llvm_bool(),
             dia,
-            can_throw,
+            unwind.to_llvm_bool(),
         )
     };
 
diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs
index 853d0295238..d85f432702c 100644
--- a/compiler/rustc_codegen_llvm/src/back/lto.rs
+++ b/compiler/rustc_codegen_llvm/src/back/lto.rs
@@ -14,7 +14,7 @@ use rustc_codegen_ssa::traits::*;
 use rustc_codegen_ssa::{ModuleCodegen, ModuleKind, looks_like_rust_object_file};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::memmap::Mmap;
-use rustc_errors::{DiagCtxtHandle, FatalError};
+use rustc_errors::DiagCtxtHandle;
 use rustc_middle::bug;
 use rustc_middle::dep_graph::WorkProduct;
 use rustc_session::config::{self, Lto};
@@ -36,7 +36,7 @@ fn prepare_lto(
     exported_symbols_for_lto: &[String],
     each_linked_rlib_for_lto: &[PathBuf],
     dcx: DiagCtxtHandle<'_>,
-) -> Result<(Vec<CString>, Vec<(SerializedModule<ModuleBuffer>, CString)>), FatalError> {
+) -> (Vec<CString>, Vec<(SerializedModule<ModuleBuffer>, CString)>) {
     let mut symbols_below_threshold = exported_symbols_for_lto
         .iter()
         .map(|symbol| CString::new(symbol.to_owned()).unwrap())
@@ -79,16 +79,13 @@ fn prepare_lto(
                         let module = SerializedModule::FromRlib(data.to_vec());
                         upstream_modules.push((module, CString::new(name).unwrap()));
                     }
-                    Err(e) => {
-                        dcx.emit_err(e);
-                        return Err(FatalError);
-                    }
+                    Err(e) => dcx.emit_fatal(e),
                 }
             }
         }
     }
 
-    Ok((symbols_below_threshold, upstream_modules))
+    (symbols_below_threshold, upstream_modules)
 }
 
 fn get_bitcode_slice_from_object_data<'a>(
@@ -123,11 +120,11 @@ pub(crate) fn run_fat(
     exported_symbols_for_lto: &[String],
     each_linked_rlib_for_lto: &[PathBuf],
     modules: Vec<FatLtoInput<LlvmCodegenBackend>>,
-) -> Result<ModuleCodegen<ModuleLlvm>, FatalError> {
+) -> ModuleCodegen<ModuleLlvm> {
     let dcx = cgcx.create_dcx();
     let dcx = dcx.handle();
     let (symbols_below_threshold, upstream_modules) =
-        prepare_lto(cgcx, exported_symbols_for_lto, each_linked_rlib_for_lto, dcx)?;
+        prepare_lto(cgcx, exported_symbols_for_lto, each_linked_rlib_for_lto, dcx);
     let symbols_below_threshold =
         symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::<Vec<_>>();
     fat_lto(cgcx, dcx, modules, upstream_modules, &symbols_below_threshold)
@@ -142,11 +139,11 @@ pub(crate) fn run_thin(
     each_linked_rlib_for_lto: &[PathBuf],
     modules: Vec<(String, ThinBuffer)>,
     cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
-) -> Result<(Vec<ThinModule<LlvmCodegenBackend>>, Vec<WorkProduct>), FatalError> {
+) -> (Vec<ThinModule<LlvmCodegenBackend>>, Vec<WorkProduct>) {
     let dcx = cgcx.create_dcx();
     let dcx = dcx.handle();
     let (symbols_below_threshold, upstream_modules) =
-        prepare_lto(cgcx, exported_symbols_for_lto, each_linked_rlib_for_lto, dcx)?;
+        prepare_lto(cgcx, exported_symbols_for_lto, each_linked_rlib_for_lto, dcx);
     let symbols_below_threshold =
         symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::<Vec<_>>();
     if cgcx.opts.cg.linker_plugin_lto.enabled() {
@@ -173,7 +170,7 @@ fn fat_lto(
     modules: Vec<FatLtoInput<LlvmCodegenBackend>>,
     mut serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
     symbols_below_threshold: &[*const libc::c_char],
-) -> Result<ModuleCodegen<ModuleLlvm>, FatalError> {
+) -> ModuleCodegen<ModuleLlvm> {
     let _timer = cgcx.prof.generic_activity("LLVM_fat_lto_build_monolithic_module");
     info!("going for a fat lto");
 
@@ -224,7 +221,7 @@ fn fat_lto(
             assert!(!serialized_modules.is_empty(), "must have at least one serialized module");
             let (buffer, name) = serialized_modules.remove(0);
             info!("no in-memory regular modules to choose from, parsing {:?}", name);
-            let llvm_module = ModuleLlvm::parse(cgcx, &name, buffer.data(), dcx)?;
+            let llvm_module = ModuleLlvm::parse(cgcx, &name, buffer.data(), dcx);
             ModuleCodegen::new_regular(name.into_string().unwrap(), llvm_module)
         }
     };
@@ -265,7 +262,9 @@ fn fat_lto(
                 });
             info!("linking {:?}", name);
             let data = bc_decoded.data();
-            linker.add(data).map_err(|()| write::llvm_err(dcx, LlvmError::LoadBitcode { name }))?;
+            linker
+                .add(data)
+                .unwrap_or_else(|()| write::llvm_err(dcx, LlvmError::LoadBitcode { name }));
         }
         drop(linker);
         save_temp_bitcode(cgcx, &module, "lto.input");
@@ -282,7 +281,7 @@ fn fat_lto(
         save_temp_bitcode(cgcx, &module, "lto.after-restriction");
     }
 
-    Ok(module)
+    module
 }
 
 pub(crate) struct Linker<'a>(&'a mut llvm::Linker<'a>);
@@ -352,7 +351,7 @@ fn thin_lto(
     serialized_modules: Vec<(SerializedModule<ModuleBuffer>, CString)>,
     cached_modules: Vec<(SerializedModule<ModuleBuffer>, WorkProduct)>,
     symbols_below_threshold: &[*const libc::c_char],
-) -> Result<(Vec<ThinModule<LlvmCodegenBackend>>, Vec<WorkProduct>), FatalError> {
+) -> (Vec<ThinModule<LlvmCodegenBackend>>, Vec<WorkProduct>) {
     let _timer = cgcx.prof.generic_activity("LLVM_thin_lto_global_analysis");
     unsafe {
         info!("going for that thin, thin LTO");
@@ -422,7 +421,7 @@ fn thin_lto(
             symbols_below_threshold.as_ptr(),
             symbols_below_threshold.len(),
         )
-        .ok_or_else(|| write::llvm_err(dcx, LlvmError::PrepareThinLtoContext))?;
+        .unwrap_or_else(|| write::llvm_err(dcx, LlvmError::PrepareThinLtoContext));
 
         let data = ThinData(data);
 
@@ -492,10 +491,10 @@ fn thin_lto(
         if let Some(path) = key_map_path
             && let Err(err) = curr_key_map.save_to_file(&path)
         {
-            return Err(write::llvm_err(dcx, LlvmError::WriteThinLtoKey { err }));
+            write::llvm_err(dcx, LlvmError::WriteThinLtoKey { err });
         }
 
-        Ok((opt_jobs, copy_jobs))
+        (opt_jobs, copy_jobs)
     }
 }
 
@@ -550,7 +549,7 @@ pub(crate) fn run_pass_manager(
     dcx: DiagCtxtHandle<'_>,
     module: &mut ModuleCodegen<ModuleLlvm>,
     thin: bool,
-) -> Result<(), FatalError> {
+) {
     let _timer = cgcx.prof.generic_activity_with_arg("LLVM_lto_optimize", &*module.name);
     let config = cgcx.config(module.kind);
 
@@ -582,7 +581,7 @@ pub(crate) fn run_pass_manager(
     }
 
     unsafe {
-        write::llvm_optimize(cgcx, dcx, module, None, config, opt_level, opt_stage, stage)?;
+        write::llvm_optimize(cgcx, dcx, module, None, config, opt_level, opt_stage, stage);
     }
 
     if enable_gpu && !thin {
@@ -596,7 +595,7 @@ pub(crate) fn run_pass_manager(
         let stage = write::AutodiffStage::PostAD;
         if !config.autodiff.contains(&config::AutoDiff::NoPostopt) {
             unsafe {
-                write::llvm_optimize(cgcx, dcx, module, None, config, opt_level, opt_stage, stage)?;
+                write::llvm_optimize(cgcx, dcx, module, None, config, opt_level, opt_stage, stage);
             }
         }
 
@@ -608,7 +607,6 @@ pub(crate) fn run_pass_manager(
     }
 
     debug!("lto done");
-    Ok(())
 }
 
 pub struct ModuleBuffer(&'static mut llvm::ModuleBuffer);
@@ -701,7 +699,7 @@ impl Drop for ThinBuffer {
 pub(crate) fn optimize_thin_module(
     thin_module: ThinModule<LlvmCodegenBackend>,
     cgcx: &CodegenContext<LlvmCodegenBackend>,
-) -> Result<ModuleCodegen<ModuleLlvm>, FatalError> {
+) -> ModuleCodegen<ModuleLlvm> {
     let dcx = cgcx.create_dcx();
     let dcx = dcx.handle();
 
@@ -712,7 +710,7 @@ pub(crate) fn optimize_thin_module(
     // into that context. One day, however, we may do this for upstream
     // crates but for locally codegened modules we may be able to reuse
     // that LLVM Context and Module.
-    let module_llvm = ModuleLlvm::parse(cgcx, module_name, thin_module.data(), dcx)?;
+    let module_llvm = ModuleLlvm::parse(cgcx, module_name, thin_module.data(), dcx);
     let mut module = ModuleCodegen::new_regular(thin_module.name(), module_llvm);
     // Given that the newly created module lacks a thinlto buffer for embedding, we need to re-add it here.
     if cgcx.config(ModuleKind::Regular).embed_bitcode() {
@@ -746,7 +744,7 @@ pub(crate) fn optimize_thin_module(
                 .generic_activity_with_arg("LLVM_thin_lto_resolve_weak", thin_module.name());
             if unsafe { !llvm::LLVMRustPrepareThinLTOResolveWeak(thin_module.shared.data.0, llmod) }
             {
-                return Err(write::llvm_err(dcx, LlvmError::PrepareThinLtoModule));
+                write::llvm_err(dcx, LlvmError::PrepareThinLtoModule);
             }
             save_temp_bitcode(cgcx, &module, "thin-lto-after-resolve");
         }
@@ -757,7 +755,7 @@ pub(crate) fn optimize_thin_module(
                 .generic_activity_with_arg("LLVM_thin_lto_internalize", thin_module.name());
             if unsafe { !llvm::LLVMRustPrepareThinLTOInternalize(thin_module.shared.data.0, llmod) }
             {
-                return Err(write::llvm_err(dcx, LlvmError::PrepareThinLtoModule));
+                write::llvm_err(dcx, LlvmError::PrepareThinLtoModule);
             }
             save_temp_bitcode(cgcx, &module, "thin-lto-after-internalize");
         }
@@ -768,7 +766,7 @@ pub(crate) fn optimize_thin_module(
             if unsafe {
                 !llvm::LLVMRustPrepareThinLTOImport(thin_module.shared.data.0, llmod, target.raw())
             } {
-                return Err(write::llvm_err(dcx, LlvmError::PrepareThinLtoModule));
+                write::llvm_err(dcx, LlvmError::PrepareThinLtoModule);
             }
             save_temp_bitcode(cgcx, &module, "thin-lto-after-import");
         }
@@ -780,11 +778,11 @@ pub(crate) fn optimize_thin_module(
         // little differently.
         {
             info!("running thin lto passes over {}", module.name);
-            run_pass_manager(cgcx, dcx, &mut module, true)?;
+            run_pass_manager(cgcx, dcx, &mut module, true);
             save_temp_bitcode(cgcx, &module, "thin-lto-after-pm");
         }
     }
-    Ok(module)
+    module
 }
 
 /// Maps LLVM module identifiers to their corresponding LLVM LTO cache keys
@@ -850,9 +848,9 @@ pub(crate) fn parse_module<'a>(
     name: &CStr,
     data: &[u8],
     dcx: DiagCtxtHandle<'_>,
-) -> Result<&'a llvm::Module, FatalError> {
+) -> &'a llvm::Module {
     unsafe {
         llvm::LLVMRustParseBitcodeForLTO(cx, data.as_ptr(), data.len(), name.as_ptr())
-            .ok_or_else(|| write::llvm_err(dcx, LlvmError::ParseBitcode))
+            .unwrap_or_else(|| write::llvm_err(dcx, LlvmError::ParseBitcode))
     }
 }
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 62998003ca1..7ea2ae6673b 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -20,7 +20,7 @@ use rustc_codegen_ssa::traits::*;
 use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, ModuleKind};
 use rustc_data_structures::profiling::SelfProfilerRef;
 use rustc_data_structures::small_c_str::SmallCStr;
-use rustc_errors::{DiagCtxtHandle, FatalError, Level};
+use rustc_errors::{DiagCtxtHandle, Level};
 use rustc_fs_util::{link_or_copy, path_to_c_string};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Session;
@@ -46,10 +46,10 @@ use crate::llvm::{self, DiagnosticInfo};
 use crate::type_::Type;
 use crate::{LlvmCodegenBackend, ModuleLlvm, base, common, llvm_util};
 
-pub(crate) fn llvm_err<'a>(dcx: DiagCtxtHandle<'_>, err: LlvmError<'a>) -> FatalError {
+pub(crate) fn llvm_err<'a>(dcx: DiagCtxtHandle<'_>, err: LlvmError<'a>) -> ! {
     match llvm::last_error() {
-        Some(llvm_err) => dcx.emit_almost_fatal(WithLlvmError(err, llvm_err)),
-        None => dcx.emit_almost_fatal(err),
+        Some(llvm_err) => dcx.emit_fatal(WithLlvmError(err, llvm_err)),
+        None => dcx.emit_fatal(err),
     }
 }
 
@@ -63,7 +63,7 @@ fn write_output_file<'ll>(
     file_type: llvm::FileType,
     self_profiler_ref: &SelfProfilerRef,
     verify_llvm_ir: bool,
-) -> Result<(), FatalError> {
+) {
     debug!("write_output_file output={:?} dwo_output={:?}", output, dwo_output);
     let output_c = path_to_c_string(output);
     let dwo_output_c;
@@ -100,7 +100,7 @@ fn write_output_file<'ll>(
         }
     }
 
-    result.into_result().map_err(|()| llvm_err(dcx, LlvmError::WriteOutput { path: output }))
+    result.into_result().unwrap_or_else(|()| llvm_err(dcx, LlvmError::WriteOutput { path: output }))
 }
 
 pub(crate) fn create_informational_target_machine(
@@ -112,7 +112,7 @@ pub(crate) fn create_informational_target_machine(
     // system/tcx is set up.
     let features = llvm_util::global_llvm_features(sess, false, only_base_features);
     target_machine_factory(sess, config::OptLevel::No, &features)(config)
-        .unwrap_or_else(|err| llvm_err(sess.dcx(), err).raise())
+        .unwrap_or_else(|err| llvm_err(sess.dcx(), err))
 }
 
 pub(crate) fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> OwnedTargetMachine {
@@ -139,7 +139,7 @@ pub(crate) fn create_target_machine(tcx: TyCtxt<'_>, mod_name: &str) -> OwnedTar
         tcx.backend_optimization_level(()),
         tcx.global_backend_features(()),
     )(config)
-    .unwrap_or_else(|err| llvm_err(tcx.dcx(), err).raise())
+    .unwrap_or_else(|err| llvm_err(tcx.dcx(), err))
 }
 
 fn to_llvm_opt_settings(cfg: config::OptLevel) -> (llvm::CodeGenOptLevel, llvm::CodeGenOptSize) {
@@ -565,7 +565,7 @@ pub(crate) unsafe fn llvm_optimize(
     opt_level: config::OptLevel,
     opt_stage: llvm::OptStage,
     autodiff_stage: AutodiffStage,
-) -> Result<(), FatalError> {
+) {
     // Enzyme:
     // The whole point of compiler based AD is to differentiate optimized IR instead of unoptimized
     // source code. However, benchmarks show that optimizations increasing the code size
@@ -704,7 +704,7 @@ pub(crate) unsafe fn llvm_optimize(
             llvm_plugins.len(),
         )
     };
-    result.into_result().map_err(|()| llvm_err(dcx, LlvmError::RunLlvmPasses))
+    result.into_result().unwrap_or_else(|()| llvm_err(dcx, LlvmError::RunLlvmPasses))
 }
 
 // Unsafe due to LLVM calls.
@@ -713,7 +713,7 @@ pub(crate) fn optimize(
     dcx: DiagCtxtHandle<'_>,
     module: &mut ModuleCodegen<ModuleLlvm>,
     config: &ModuleConfig,
-) -> Result<(), FatalError> {
+) {
     let _timer = cgcx.prof.generic_activity_with_arg("LLVM_module_optimize", &*module.name);
 
     let llcx = &*module.module_llvm.llcx;
@@ -765,7 +765,7 @@ pub(crate) fn optimize(
                 opt_stage,
                 autodiff_stage,
             )
-        }?;
+        };
         if let Some(thin_lto_buffer) = thin_lto_buffer {
             let thin_lto_buffer = unsafe { ThinBuffer::from_raw_ptr(thin_lto_buffer) };
             module.thin_lto_buffer = Some(thin_lto_buffer.data().to_vec());
@@ -793,14 +793,13 @@ pub(crate) fn optimize(
             }
         }
     }
-    Ok(())
 }
 
 pub(crate) fn codegen(
     cgcx: &CodegenContext<LlvmCodegenBackend>,
     module: ModuleCodegen<ModuleLlvm>,
     config: &ModuleConfig,
-) -> Result<CompiledModule, FatalError> {
+) -> CompiledModule {
     let dcx = cgcx.create_dcx();
     let dcx = dcx.handle();
 
@@ -909,7 +908,9 @@ pub(crate) fn codegen(
                 record_artifact_size(&cgcx.prof, "llvm_ir", &out);
             }
 
-            result.into_result().map_err(|()| llvm_err(dcx, LlvmError::WriteIr { path: &out }))?;
+            result
+                .into_result()
+                .unwrap_or_else(|()| llvm_err(dcx, LlvmError::WriteIr { path: &out }));
         }
 
         if config.emit_asm {
@@ -940,7 +941,7 @@ pub(crate) fn codegen(
                 llvm::FileType::AssemblyFile,
                 &cgcx.prof,
                 config.verify_llvm_ir,
-            )?;
+            );
         }
 
         match config.emit_obj {
@@ -976,7 +977,7 @@ pub(crate) fn codegen(
                     llvm::FileType::ObjectFile,
                     &cgcx.prof,
                     config.verify_llvm_ir,
-                )?;
+                );
             }
 
             EmitObj::Bitcode => {
@@ -1009,7 +1010,7 @@ pub(crate) fn codegen(
         && cgcx.target_can_use_split_dwarf
         && cgcx.split_debuginfo != SplitDebuginfo::Off
         && cgcx.split_dwarf_kind == SplitDwarfKind::Split;
-    Ok(module.into_compiled_module(
+    module.into_compiled_module(
         config.emit_obj != EmitObj::None,
         dwarf_object_emitted,
         config.emit_bc,
@@ -1017,7 +1018,7 @@ pub(crate) fn codegen(
         config.emit_ir,
         &cgcx.output_filenames,
         cgcx.invocation_temp.as_deref(),
-    ))
+    )
 }
 
 fn create_section_with_flags_asm(section_name: &str, section_flags: &str, data: &[u8]) -> Vec<u8> {
@@ -1110,7 +1111,7 @@ fn embed_bitcode(
 
         llvm::set_section(llglobal, bitcode_section_name(cgcx));
         llvm::set_linkage(llglobal, llvm::Linkage::PrivateLinkage);
-        llvm::LLVMSetGlobalConstant(llglobal, llvm::True);
+        llvm::LLVMSetGlobalConstant(llglobal, llvm::TRUE);
 
         let llconst = common::bytes_in_context(llcx, &[]);
         let llglobal = llvm::add_global(llmod, common::val_ty(llconst), c"rustc.embedded.cmdline");
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index 427c75d40e9..37379586d58 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -35,7 +35,7 @@ use crate::attributes;
 use crate::common::Funclet;
 use crate::context::{CodegenCx, FullCx, GenericCx, SCx};
 use crate::llvm::{
-    self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, False, GEPNoWrapFlags, Metadata, True,
+    self, AtomicOrdering, AtomicRmwBinOp, BasicBlock, GEPNoWrapFlags, Metadata, TRUE, ToLlvmBool,
 };
 use crate::type_::Type;
 use crate::type_of::LayoutLlvmExt;
@@ -493,8 +493,8 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         unsafe {
             let add = llvm::LLVMBuildAdd(self.llbuilder, a, b, UNNAMED);
             if llvm::LLVMIsAInstruction(add).is_some() {
-                llvm::LLVMSetNUW(add, True);
-                llvm::LLVMSetNSW(add, True);
+                llvm::LLVMSetNUW(add, TRUE);
+                llvm::LLVMSetNSW(add, TRUE);
             }
             add
         }
@@ -503,8 +503,8 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         unsafe {
             let sub = llvm::LLVMBuildSub(self.llbuilder, a, b, UNNAMED);
             if llvm::LLVMIsAInstruction(sub).is_some() {
-                llvm::LLVMSetNUW(sub, True);
-                llvm::LLVMSetNSW(sub, True);
+                llvm::LLVMSetNUW(sub, TRUE);
+                llvm::LLVMSetNSW(sub, TRUE);
             }
             sub
         }
@@ -513,8 +513,8 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         unsafe {
             let mul = llvm::LLVMBuildMul(self.llbuilder, a, b, UNNAMED);
             if llvm::LLVMIsAInstruction(mul).is_some() {
-                llvm::LLVMSetNUW(mul, True);
-                llvm::LLVMSetNSW(mul, True);
+                llvm::LLVMSetNUW(mul, TRUE);
+                llvm::LLVMSetNSW(mul, TRUE);
             }
             mul
         }
@@ -528,7 +528,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
             // an instruction, so we need to check before setting the flag.
             // (See also `LLVMBuildNUWNeg` which also needs a check.)
             if llvm::LLVMIsAInstruction(or).is_some() {
-                llvm::LLVMSetIsDisjoint(or, True);
+                llvm::LLVMSetIsDisjoint(or, TRUE);
             }
             or
         }
@@ -629,7 +629,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
     fn volatile_load(&mut self, ty: &'ll Type, ptr: &'ll Value) -> &'ll Value {
         unsafe {
             let load = llvm::LLVMBuildLoad2(self.llbuilder, ty, ptr, UNNAMED);
-            llvm::LLVMSetVolatile(load, llvm::True);
+            llvm::LLVMSetVolatile(load, llvm::TRUE);
             load
         }
     }
@@ -717,7 +717,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
             let mut const_llval = None;
             let llty = place.layout.llvm_type(self);
             if let Some(global) = llvm::LLVMIsAGlobalVariable(place.val.llval) {
-                if llvm::LLVMIsGlobalConstant(global) == llvm::True {
+                if llvm::LLVMIsGlobalConstant(global).is_true() {
                     if let Some(init) = llvm::LLVMGetInitializer(global) {
                         if self.val_ty(init) == llty {
                             const_llval = Some(init);
@@ -838,7 +838,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
                 if flags.contains(MemFlags::UNALIGNED) { 1 } else { align.bytes() as c_uint };
             llvm::LLVMSetAlignment(store, align);
             if flags.contains(MemFlags::VOLATILE) {
-                llvm::LLVMSetVolatile(store, llvm::True);
+                llvm::LLVMSetVolatile(store, llvm::TRUE);
             }
             if flags.contains(MemFlags::NONTEMPORAL) {
                 // Make sure that the current target architectures supports "sane" non-temporal
@@ -956,7 +956,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         let trunc = self.trunc(val, dest_ty);
         unsafe {
             if llvm::LLVMIsAInstruction(trunc).is_some() {
-                llvm::LLVMSetNUW(trunc, True);
+                llvm::LLVMSetNUW(trunc, TRUE);
             }
         }
         trunc
@@ -968,7 +968,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         let trunc = self.trunc(val, dest_ty);
         unsafe {
             if llvm::LLVMIsAInstruction(trunc).is_some() {
-                llvm::LLVMSetNSW(trunc, True);
+                llvm::LLVMSetNSW(trunc, TRUE);
             }
         }
         trunc
@@ -1067,13 +1067,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
 
     fn intcast(&mut self, val: &'ll Value, dest_ty: &'ll Type, is_signed: bool) -> &'ll Value {
         unsafe {
-            llvm::LLVMBuildIntCast2(
-                self.llbuilder,
-                val,
-                dest_ty,
-                if is_signed { True } else { False },
-                UNNAMED,
-            )
+            llvm::LLVMBuildIntCast2(self.llbuilder, val, dest_ty, is_signed.to_llvm_bool(), UNNAMED)
         }
     }
 
@@ -1229,7 +1223,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         let ty = self.type_struct(&[self.type_ptr(), self.type_i32()], false);
         let landing_pad = self.landing_pad(ty, pers_fn, 0);
         unsafe {
-            llvm::LLVMSetCleanup(landing_pad, llvm::True);
+            llvm::LLVMSetCleanup(landing_pad, llvm::TRUE);
         }
         (self.extract_value(landing_pad, 0), self.extract_value(landing_pad, 1))
     }
@@ -1317,7 +1311,6 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         failure_order: rustc_middle::ty::AtomicOrdering,
         weak: bool,
     ) -> (&'ll Value, &'ll Value) {
-        let weak = if weak { llvm::True } else { llvm::False };
         unsafe {
             let value = llvm::LLVMBuildAtomicCmpXchg(
                 self.llbuilder,
@@ -1326,9 +1319,9 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
                 src,
                 AtomicOrdering::from_generic(order),
                 AtomicOrdering::from_generic(failure_order),
-                llvm::False, // SingleThreaded
+                llvm::FALSE, // SingleThreaded
             );
-            llvm::LLVMSetWeak(value, weak);
+            llvm::LLVMSetWeak(value, weak.to_llvm_bool());
             let val = self.extract_value(value, 0);
             let success = self.extract_value(value, 1);
             (val, success)
@@ -1353,7 +1346,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
                 dst,
                 src,
                 AtomicOrdering::from_generic(order),
-                llvm::False, // SingleThreaded
+                llvm::FALSE, // SingleThreaded
             )
         };
         if ret_ptr && self.val_ty(res) != self.type_ptr() {
@@ -1368,14 +1361,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         scope: SynchronizationScope,
     ) {
         let single_threaded = match scope {
-            SynchronizationScope::SingleThread => llvm::True,
-            SynchronizationScope::CrossThread => llvm::False,
+            SynchronizationScope::SingleThread => true,
+            SynchronizationScope::CrossThread => false,
         };
         unsafe {
             llvm::LLVMBuildFence(
                 self.llbuilder,
                 AtomicOrdering::from_generic(order),
-                single_threaded,
+                single_threaded.to_llvm_bool(),
                 UNNAMED,
             );
         }
diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
index e2df3265f6f..6ddf53cdc87 100644
--- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
+++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs
@@ -11,7 +11,7 @@ use crate::builder::{Builder, PlaceRef, UNNAMED};
 use crate::context::SimpleCx;
 use crate::declare::declare_simple_fn;
 use crate::llvm;
-use crate::llvm::{Metadata, True, Type};
+use crate::llvm::{Metadata, TRUE, Type};
 use crate::value::Value;
 
 pub(crate) fn adjust_activity_to_abi<'tcx>(
@@ -293,7 +293,7 @@ pub(crate) fn generate_enzyme_call<'ll, 'tcx>(
     //   ret double %0
     // }
     // ```
-    let enzyme_ty = unsafe { llvm::LLVMFunctionType(ret_ty, ptr::null(), 0, True) };
+    let enzyme_ty = unsafe { llvm::LLVMFunctionType(ret_ty, ptr::null(), 0, TRUE) };
 
     // FIXME(ZuseZ4): the CC/Addr/Vis values are best effort guesses, we should look at tests and
     // think a bit more about what should go here.
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index f29fefb66f0..11b79a7fe68 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -20,7 +20,7 @@ use tracing::debug;
 use crate::consts::const_alloc_to_llvm;
 pub(crate) use crate::context::CodegenCx;
 use crate::context::{GenericCx, SCx};
-use crate::llvm::{self, BasicBlock, Bool, ConstantInt, False, Metadata, True};
+use crate::llvm::{self, BasicBlock, ConstantInt, FALSE, Metadata, TRUE, ToLlvmBool};
 use crate::type_::Type;
 use crate::value::Value;
 
@@ -158,7 +158,7 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
             self.type_kind(t) == TypeKind::Integer,
             "only allows integer types in const_int"
         );
-        unsafe { llvm::LLVMConstInt(t, i as u64, True) }
+        unsafe { llvm::LLVMConstInt(t, i as u64, TRUE) }
     }
 
     fn const_u8(&self, i: u8) -> &'ll Value {
@@ -192,7 +192,7 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
             self.type_kind(t) == TypeKind::Integer,
             "only allows integer types in const_uint"
         );
-        unsafe { llvm::LLVMConstInt(t, i, False) }
+        unsafe { llvm::LLVMConstInt(t, i, FALSE) }
     }
 
     fn const_uint_big(&self, t: &'ll Type, u: u128) -> &'ll Value {
@@ -377,7 +377,7 @@ pub(crate) fn val_ty(v: &Value) -> &Type {
 pub(crate) fn bytes_in_context<'ll>(llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value {
     unsafe {
         let ptr = bytes.as_ptr() as *const c_char;
-        llvm::LLVMConstStringInContext2(llcx, ptr, bytes.len(), True)
+        llvm::LLVMConstStringInContext2(llcx, ptr, bytes.len(), TRUE)
     }
 }
 
@@ -392,7 +392,7 @@ fn struct_in_context<'ll>(
     packed: bool,
 ) -> &'ll Value {
     let len = c_uint::try_from(elts.len()).expect("LLVMConstStructInContext elements len overflow");
-    unsafe { llvm::LLVMConstStructInContext(llcx, elts.as_ptr(), len, packed as Bool) }
+    unsafe { llvm::LLVMConstStructInContext(llcx, elts.as_ptr(), len, packed.to_llvm_bool()) }
 }
 
 #[inline]
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 4a7de7d2e69..4fd6110ac4a 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -701,7 +701,7 @@ impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
     }
 
     pub(crate) fn get_const_int(&self, ty: &'ll Type, val: u64) -> &'ll Value {
-        unsafe { llvm::LLVMConstInt(ty, val, llvm::False) }
+        unsafe { llvm::LLVMConstInt(ty, val, llvm::FALSE) }
     }
 
     pub(crate) fn get_const_i64(&self, n: u64) -> &'ll Value {
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
index 6eb7042da61..7a6dc008c7b 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs
@@ -72,7 +72,7 @@ pub(crate) fn get_or_insert_gdb_debug_scripts_section_global<'ll>(
                 .unwrap_or_else(|| bug!("symbol `{}` is already defined", section_var_name));
             llvm::set_section(section_var, c".debug_gdb_scripts");
             llvm::set_initializer(section_var, cx.const_bytes(section_contents));
-            llvm::LLVMSetGlobalConstant(section_var, llvm::True);
+            llvm::LLVMSetGlobalConstant(section_var, llvm::TRUE);
             llvm::set_unnamed_address(section_var, llvm::UnnamedAddr::Global);
             llvm::set_linkage(section_var, llvm::Linkage::LinkOnceODRLinkage);
             // This should make sure that the whole section is not larger than
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
index b4d639368b0..1dcf4ff3062 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/namespace.rs
@@ -38,7 +38,7 @@ pub(crate) fn item_namespace<'ll>(cx: &CodegenCx<'ll, '_>, def_id: DefId) -> &'l
             parent_scope,
             namespace_name_string.as_ptr(),
             namespace_name_string.len(),
-            llvm::False, // ExportSymbols (only relevant for C++ anonymous namespaces)
+            llvm::FALSE, // ExportSymbols (only relevant for C++ anonymous namespaces)
         )
     };
 
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 0fcf31d7993..628cb34fd9e 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -37,7 +37,7 @@ use rustc_codegen_ssa::back::write::{
 use rustc_codegen_ssa::traits::*;
 use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleCodegen, TargetConfig};
 use rustc_data_structures::fx::FxIndexMap;
-use rustc_errors::{DiagCtxtHandle, FatalError};
+use rustc_errors::DiagCtxtHandle;
 use rustc_metadata::EncodedMetadata;
 use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
 use rustc_middle::ty::TyCtxt;
@@ -165,15 +165,15 @@ impl WriteBackendMethods for LlvmCodegenBackend {
         exported_symbols_for_lto: &[String],
         each_linked_rlib_for_lto: &[PathBuf],
         modules: Vec<FatLtoInput<Self>>,
-    ) -> Result<ModuleCodegen<Self::Module>, FatalError> {
+    ) -> ModuleCodegen<Self::Module> {
         let mut module =
-            back::lto::run_fat(cgcx, exported_symbols_for_lto, each_linked_rlib_for_lto, modules)?;
+            back::lto::run_fat(cgcx, exported_symbols_for_lto, each_linked_rlib_for_lto, modules);
 
         let dcx = cgcx.create_dcx();
         let dcx = dcx.handle();
-        back::lto::run_pass_manager(cgcx, dcx, &mut module, false)?;
+        back::lto::run_pass_manager(cgcx, dcx, &mut module, false);
 
-        Ok(module)
+        module
     }
     fn run_thin_lto(
         cgcx: &CodegenContext<Self>,
@@ -181,7 +181,7 @@ impl WriteBackendMethods for LlvmCodegenBackend {
         each_linked_rlib_for_lto: &[PathBuf],
         modules: Vec<(String, Self::ThinBuffer)>,
         cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
-    ) -> Result<(Vec<ThinModule<Self>>, Vec<WorkProduct>), FatalError> {
+    ) -> (Vec<ThinModule<Self>>, Vec<WorkProduct>) {
         back::lto::run_thin(
             cgcx,
             exported_symbols_for_lto,
@@ -195,20 +195,20 @@ impl WriteBackendMethods for LlvmCodegenBackend {
         dcx: DiagCtxtHandle<'_>,
         module: &mut ModuleCodegen<Self::Module>,
         config: &ModuleConfig,
-    ) -> Result<(), FatalError> {
+    ) {
         back::write::optimize(cgcx, dcx, module, config)
     }
     fn optimize_thin(
         cgcx: &CodegenContext<Self>,
         thin: ThinModule<Self>,
-    ) -> Result<ModuleCodegen<Self::Module>, FatalError> {
+    ) -> ModuleCodegen<Self::Module> {
         back::lto::optimize_thin_module(thin, cgcx)
     }
     fn codegen(
         cgcx: &CodegenContext<Self>,
         module: ModuleCodegen<Self::Module>,
         config: &ModuleConfig,
-    ) -> Result<CompiledModule, FatalError> {
+    ) -> CompiledModule {
         back::write::codegen(cgcx, module, config)
     }
     fn prepare_thin(
@@ -407,12 +407,12 @@ impl ModuleLlvm {
         cgcx: &CodegenContext<LlvmCodegenBackend>,
         name: &str,
         dcx: DiagCtxtHandle<'_>,
-    ) -> Result<OwnedTargetMachine, FatalError> {
+    ) -> OwnedTargetMachine {
         let tm_factory_config = TargetMachineFactoryConfig::new(cgcx, name);
         match (cgcx.tm_factory)(tm_factory_config) {
-            Ok(m) => Ok(m),
+            Ok(m) => m,
             Err(e) => {
-                return Err(dcx.emit_almost_fatal(ParseTargetMachineConfig(e)));
+                dcx.emit_fatal(ParseTargetMachineConfig(e));
             }
         }
     }
@@ -422,13 +422,13 @@ impl ModuleLlvm {
         name: &CStr,
         buffer: &[u8],
         dcx: DiagCtxtHandle<'_>,
-    ) -> Result<Self, FatalError> {
+    ) -> Self {
         unsafe {
             let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
-            let llmod_raw = back::lto::parse_module(llcx, name, buffer, dcx)?;
-            let tm = ModuleLlvm::tm_from_cgcx(cgcx, name.to_str().unwrap(), dcx)?;
+            let llmod_raw = back::lto::parse_module(llcx, name, buffer, dcx);
+            let tm = ModuleLlvm::tm_from_cgcx(cgcx, name.to_str().unwrap(), dcx);
 
-            Ok(ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) })
+            ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) }
         }
     }
 
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 2461f70a86e..ba590851dbd 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -11,9 +11,8 @@
 //! the need for an extra cast from `*const u8` on the Rust side.
 
 #![allow(non_camel_case_types)]
-#![allow(non_upper_case_globals)]
 
-use std::fmt::Debug;
+use std::fmt::{self, Debug};
 use std::marker::PhantomData;
 use std::num::NonZero;
 use std::ptr;
@@ -33,10 +32,59 @@ use crate::llvm;
 
 /// In the LLVM-C API, boolean values are passed as `typedef int LLVMBool`,
 /// which has a different ABI from Rust or C++ `bool`.
-pub(crate) type Bool = c_int;
+///
+/// This wrapper does not implement `PartialEq`.
+/// To test the underlying boolean value, use [`Self::is_true`].
+#[derive(Clone, Copy)]
+#[repr(transparent)]
+pub(crate) struct Bool {
+    value: c_int,
+}
+
+pub(crate) const TRUE: Bool = Bool::TRUE;
+pub(crate) const FALSE: Bool = Bool::FALSE;
+
+impl Bool {
+    pub(crate) const TRUE: Self = Self { value: 1 };
+    pub(crate) const FALSE: Self = Self { value: 0 };
+
+    pub(crate) const fn from_bool(rust_bool: bool) -> Self {
+        if rust_bool { Self::TRUE } else { Self::FALSE }
+    }
+
+    /// Converts this LLVM-C boolean to a Rust `bool`
+    pub(crate) fn is_true(self) -> bool {
+        // Since we're interacting with a C API, follow the C convention of
+        // treating any nonzero value as true.
+        self.value != Self::FALSE.value
+    }
+}
 
-pub(crate) const True: Bool = 1 as Bool;
-pub(crate) const False: Bool = 0 as Bool;
+impl Debug for Bool {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self.value {
+            0 => f.write_str("FALSE"),
+            1 => f.write_str("TRUE"),
+            // As with `Self::is_true`, treat any nonzero value as true.
+            v => write!(f, "TRUE ({v})"),
+        }
+    }
+}
+
+/// Convenience trait to convert `bool` to `llvm::Bool` with an explicit method call.
+///
+/// Being able to write `b.to_llvm_bool()` is less noisy than `llvm::Bool::from(b)`,
+/// while being more explicit and less mistake-prone than something like `b.into()`.
+pub(crate) trait ToLlvmBool: Copy {
+    fn to_llvm_bool(self) -> llvm::Bool;
+}
+
+impl ToLlvmBool for bool {
+    #[inline(always)]
+    fn to_llvm_bool(self) -> llvm::Bool {
+        llvm::Bool::from_bool(self)
+    }
+}
 
 /// Wrapper for a raw enum value returned from LLVM's C APIs.
 ///
@@ -215,7 +263,7 @@ pub(crate) enum AttributeKind {
     MinSize = 4,
     Naked = 5,
     NoAlias = 6,
-    NoCapture = 7,
+    CapturesAddress = 7,
     NoInline = 8,
     NonNull = 9,
     NoRedZone = 10,
@@ -1881,11 +1929,17 @@ unsafe extern "C" {
         C: &Context,
         effects: MemoryEffects,
     ) -> &Attribute;
+    /// ## Safety
+    /// - Each of `LowerWords` and `UpperWords` must point to an array that is
+    ///   long enough to fully define an integer of size `NumBits`, i.e. each
+    ///   pointer must point to `NumBits.div_ceil(64)` elements or more.
+    /// - The implementation will make its own copy of the pointed-to `u64`
+    ///   values, so the pointers only need to outlive this function call.
     pub(crate) fn LLVMRustCreateRangeAttribute(
         C: &Context,
-        num_bits: c_uint,
-        lower_words: *const u64,
-        upper_words: *const u64,
+        NumBits: c_uint,
+        LowerWords: *const u64,
+        UpperWords: *const u64,
     ) -> &Attribute;
 
     // Operations on functions
diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
index 7fea7b79a8c..d6974e22c85 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs
@@ -112,16 +112,26 @@ pub(crate) fn CreateAllocKindAttr(llcx: &Context, kind_arg: AllocKindFlags) -> &
 
 pub(crate) fn CreateRangeAttr(llcx: &Context, size: Size, range: WrappingRange) -> &Attribute {
     let lower = range.start;
+    // LLVM treats the upper bound as exclusive, but allows wrapping.
     let upper = range.end.wrapping_add(1);
-    let lower_words = [lower as u64, (lower >> 64) as u64];
-    let upper_words = [upper as u64, (upper >> 64) as u64];
+
+    // Pass each `u128` endpoint value as a `[u64; 2]` array, least-significant part first.
+    let as_u64_array = |x: u128| [x as u64, (x >> 64) as u64];
+    let lower_words: [u64; 2] = as_u64_array(lower);
+    let upper_words: [u64; 2] = as_u64_array(upper);
+
+    // To ensure that LLVM doesn't try to read beyond the `[u64; 2]` arrays,
+    // we must explicitly check that `size_bits` does not exceed 128.
+    let size_bits = size.bits();
+    assert!(size_bits <= 128);
+    // More robust assertions that are redundant with `size_bits <= 128` and
+    // should be optimized away.
+    assert!(size_bits.div_ceil(64) <= u64::try_from(lower_words.len()).unwrap());
+    assert!(size_bits.div_ceil(64) <= u64::try_from(upper_words.len()).unwrap());
+    let size_bits = c_uint::try_from(size_bits).unwrap();
+
     unsafe {
-        LLVMRustCreateRangeAttribute(
-            llcx,
-            size.bits().try_into().unwrap(),
-            lower_words.as_ptr(),
-            upper_words.as_ptr(),
-        )
+        LLVMRustCreateRangeAttribute(llcx, size_bits, lower_words.as_ptr(), upper_words.as_ptr())
     }
 }
 
@@ -215,7 +225,7 @@ pub(crate) fn set_initializer(llglobal: &Value, constant_val: &Value) {
 }
 
 pub(crate) fn set_global_constant(llglobal: &Value, is_constant: bool) {
-    LLVMSetGlobalConstant(llglobal, if is_constant { ffi::True } else { ffi::False });
+    LLVMSetGlobalConstant(llglobal, is_constant.to_llvm_bool());
 }
 
 pub(crate) fn get_linkage(llglobal: &Value) -> Linkage {
@@ -229,7 +239,7 @@ pub(crate) fn set_linkage(llglobal: &Value, linkage: Linkage) {
 }
 
 pub(crate) fn is_declaration(llglobal: &Value) -> bool {
-    unsafe { LLVMIsDeclaration(llglobal) == ffi::True }
+    unsafe { LLVMIsDeclaration(llglobal) }.is_true()
 }
 
 pub(crate) fn get_visibility(llglobal: &Value) -> Visibility {
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 90f7cd43268..d927ffd78c2 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -26,7 +26,7 @@ static INIT: Once = Once::new();
 pub(crate) fn init(sess: &Session) {
     unsafe {
         // Before we touch LLVM, make sure that multithreading is enabled.
-        if llvm::LLVMIsMultithreaded() != 1 {
+        if !llvm::LLVMIsMultithreaded().is_true() {
             bug!("LLVM compiled without support for threads");
         }
         INIT.call_once(|| {
@@ -279,7 +279,7 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
         }
         ("loongarch32" | "loongarch64", "32s") if get_version().0 < 21 => None,
         // Filter out features that are not supported by the current LLVM version
-        ("riscv32" | "riscv64", "zacas") if get_version().0 < 20 => None,
+        ("riscv32" | "riscv64", "zacas" | "rva23u64" | "supm") if get_version().0 < 20 => None,
         (
             "s390x",
             "message-security-assist-extension12"
diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs
index 5075befae8a..52eefe2d4d2 100644
--- a/compiler/rustc_codegen_llvm/src/mono_item.rs
+++ b/compiler/rustc_codegen_llvm/src/mono_item.rs
@@ -133,7 +133,7 @@ impl CodegenCx<'_, '_> {
 
         // Thread-local variables generally don't support copy relocations.
         let is_thread_local_var = llvm::LLVMIsAGlobalVariable(llval)
-            .is_some_and(|v| llvm::LLVMIsThreadLocal(v) == llvm::True);
+            .is_some_and(|v| llvm::LLVMIsThreadLocal(v).is_true());
         if is_thread_local_var {
             return false;
         }
diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs
index f02d16baf94..9ecaf5f24fe 100644
--- a/compiler/rustc_codegen_llvm/src/type_.rs
+++ b/compiler/rustc_codegen_llvm/src/type_.rs
@@ -15,7 +15,7 @@ use rustc_target::callconv::{CastTarget, FnAbi};
 use crate::abi::{FnAbiLlvmExt, LlvmType};
 use crate::context::{CodegenCx, GenericCx, SCx};
 pub(crate) use crate::llvm::Type;
-use crate::llvm::{Bool, False, Metadata, True};
+use crate::llvm::{FALSE, Metadata, TRUE, ToLlvmBool};
 use crate::type_of::LayoutLlvmExt;
 use crate::value::Value;
 use crate::{common, llvm};
@@ -53,7 +53,9 @@ impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
     }
 
     pub(crate) fn set_struct_body(&self, ty: &'ll Type, els: &[&'ll Type], packed: bool) {
-        unsafe { llvm::LLVMStructSetBody(ty, els.as_ptr(), els.len() as c_uint, packed as Bool) }
+        unsafe {
+            llvm::LLVMStructSetBody(ty, els.as_ptr(), els.len() as c_uint, packed.to_llvm_bool())
+        }
     }
     pub(crate) fn type_void(&self) -> &'ll Type {
         unsafe { llvm::LLVMVoidTypeInContext(self.llcx()) }
@@ -139,7 +141,7 @@ impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
     }
 
     pub(crate) fn type_variadic_func(&self, args: &[&'ll Type], ret: &'ll Type) -> &'ll Type {
-        unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, True) }
+        unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, TRUE) }
     }
 
     pub(crate) fn type_i1(&self) -> &'ll Type {
@@ -152,7 +154,7 @@ impl<'ll, CX: Borrow<SCx<'ll>>> GenericCx<'ll, CX> {
                 self.llcx(),
                 els.as_ptr(),
                 els.len() as c_uint,
-                packed as Bool,
+                packed.to_llvm_bool(),
             )
         }
     }
@@ -200,7 +202,7 @@ impl<'ll, CX: Borrow<SCx<'ll>>> BaseTypeCodegenMethods for GenericCx<'ll, CX> {
     }
 
     fn type_func(&self, args: &[&'ll Type], ret: &'ll Type) -> &'ll Type {
-        unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, False) }
+        unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, FALSE) }
     }
 
     fn type_kind(&self, ty: &'ll Type) -> TypeKind {
diff --git a/compiler/rustc_codegen_ssa/Cargo.toml b/compiler/rustc_codegen_ssa/Cargo.toml
index 6a8971de746..6b989a96488 100644
--- a/compiler/rustc_codegen_ssa/Cargo.toml
+++ b/compiler/rustc_codegen_ssa/Cargo.toml
@@ -6,12 +6,12 @@ edition = "2024"
 [dependencies]
 # tidy-alphabetical-start
 ar_archive_writer = "0.4.2"
-bitflags = "2.4.1"
+bitflags.workspace = true
 bstr = "1.11.3"
 # `cc` updates often break things, so we pin it here. Cargo enforces "max 1 semver-compat version
 # per crate", so if you change this, you need to also change it in `rustc_llvm`.
 cc = "=1.2.16"
-itertools = "0.12"
+itertools.workspace = true
 pathdiff = "0.2.0"
 regex = "1.4"
 rustc_abi = { path = "../rustc_abi" }
@@ -40,9 +40,9 @@ rustc_trait_selection = { path = "../rustc_trait_selection" }
 serde_json = "1.0.59"
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
 tempfile = "3.2"
-thin-vec = "0.2.12"
+thin-vec.workspace = true
 thorin-dwp = "0.9"
-tracing = "0.1"
+tracing.workspace = true
 wasm-encoder = "0.219"
 # tidy-alphabetical-end
 
diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl
index 42ba0154192..44b9941691a 100644
--- a/compiler/rustc_codegen_ssa/messages.ftl
+++ b/compiler/rustc_codegen_ssa/messages.ftl
@@ -171,9 +171,6 @@ codegen_ssa_invalid_monomorphization_unsupported_symbol = invalid monomorphizati
 
 codegen_ssa_invalid_monomorphization_unsupported_symbol_of_size = invalid monomorphization of `{$name}` intrinsic: unsupported {$symbol} from `{$in_ty}` with element `{$in_elem}` of size `{$size}` to `{$ret_ty}`
 
-codegen_ssa_invalid_sanitize = invalid argument for `sanitize`
-    .note = expected one of: `address`, `kernel_address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow_call_stack`, or `thread`
-
 codegen_ssa_invalid_windows_subsystem = invalid windows subsystem `{$subsystem}`, only `windows` and `console` are allowed
 
 codegen_ssa_ld64_unimplemented_modifier = `as-needed` modifier not implemented yet for ld64
diff --git a/compiler/rustc_codegen_ssa/src/back/apple.rs b/compiler/rustc_codegen_ssa/src/back/apple.rs
index 2274450e20e..b1d646d9265 100644
--- a/compiler/rustc_codegen_ssa/src/back/apple.rs
+++ b/compiler/rustc_codegen_ssa/src/back/apple.rs
@@ -164,7 +164,7 @@ pub(super) fn get_sdk_root(sess: &Session) -> Option<PathBuf> {
     //
     // Note that when cross-compiling from e.g. Linux, the `xcrun` binary may sometimes be provided
     // as a shim by a cross-compilation helper tool. It usually isn't, but we still try nonetheless.
-    match xcrun_show_sdk_path(sdk_name, sess.verbose_internals()) {
+    match xcrun_show_sdk_path(sdk_name, false) {
         Ok((path, stderr)) => {
             // Emit extra stderr, such as if `-verbose` was passed, or if `xcrun` emitted a warning.
             if !stderr.is_empty() {
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index c3777f64e9e..19c919c0e4e 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -14,11 +14,13 @@ use itertools::Itertools;
 use regex::Regex;
 use rustc_arena::TypedArena;
 use rustc_ast::CRATE_NODE_ID;
+use rustc_attr_parsing::{ShouldEmit, eval_config_entry};
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_data_structures::memmap::Mmap;
 use rustc_data_structures::temp_dir::MaybeTempDir;
 use rustc_errors::{DiagCtxtHandle, LintDiagnostic};
 use rustc_fs_util::{TempDirBuilder, fix_windows_verbatim_for_gcc, try_canonicalize};
+use rustc_hir::attrs::NativeLibKind;
 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
 use rustc_macros::LintDiagnostic;
 use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file};
@@ -38,7 +40,6 @@ use rustc_session::config::{
 use rustc_session::lint::builtin::LINKER_MESSAGES;
 use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename};
 use rustc_session::search_paths::PathKind;
-use rustc_session::utils::NativeLibKind;
 /// For all the linkers we support, and information they might
 /// need out of the shared crate context before we get rid of it.
 use rustc_session::{Session, filesearch};
@@ -3019,7 +3020,9 @@ fn add_dynamic_crate(cmd: &mut dyn Linker, sess: &Session, cratepath: &Path) {
 
 fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
     match lib.cfg {
-        Some(ref cfg) => rustc_attr_parsing::cfg_matches(cfg, sess, CRATE_NODE_ID, None),
+        Some(ref cfg) => {
+            eval_config_entry(sess, cfg, CRATE_NODE_ID, None, ShouldEmit::ErrorsAndLints).as_bool()
+        }
         None => true,
     }
 }
diff --git a/compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs b/compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs
index b9e0c957363..9f42991d4c0 100644
--- a/compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link/raw_dylib.rs
@@ -7,9 +7,9 @@ use rustc_data_structures::base_n::{CASE_INSENSITIVE, ToBaseN};
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
 use rustc_data_structures::stable_hasher::StableHasher;
 use rustc_hashes::Hash128;
+use rustc_hir::attrs::NativeLibKind;
 use rustc_session::Session;
 use rustc_session::cstore::DllImport;
-use rustc_session::utils::NativeLibKind;
 use rustc_span::Symbol;
 
 use crate::back::archive::ImportLibraryItem;
@@ -307,11 +307,14 @@ fn create_elf_raw_dylib_stub(sess: &Session, soname: &str, symbols: &[DllImport]
     stub.reserve_section_headers();
     stub.reserve_dynsym();
     stub.reserve_dynstr();
+    let verdef_count = 1 + vers.len();
+    let mut dynamic_entries = 2; // DT_SONAME, DT_NULL
     if !vers.is_empty() {
         stub.reserve_gnu_versym();
-        stub.reserve_gnu_verdef(1 + vers.len(), 1 + vers.len());
+        stub.reserve_gnu_verdef(verdef_count, verdef_count);
+        dynamic_entries += 1; // DT_VERDEFNUM
     }
-    stub.reserve_dynamic(2); // DT_SONAME, DT_NULL
+    stub.reserve_dynamic(dynamic_entries);
 
     // First write the ELF header with the arch information.
     let e_machine = match (arch, sub_arch) {
@@ -443,9 +446,13 @@ fn create_elf_raw_dylib_stub(sess: &Session, soname: &str, symbols: &[DllImport]
     // .dynamic
     // the DT_SONAME will be used by the linker to populate DT_NEEDED
     // which the loader uses to find the library.
-    // DT_NULL terminates the .dynamic table.
     stub.write_align_dynamic();
     stub.write_dynamic_string(elf::DT_SONAME, soname);
+    // LSB section "2.7. Symbol Versioning" requires `DT_VERDEFNUM` to be reliable.
+    if verdef_count > 1 {
+        stub.write_dynamic(elf::DT_VERDEFNUM, verdef_count as u64);
+    }
+    // DT_NULL terminates the .dynamic table.
     stub.write_dynamic(elf::DT_NULL, 0);
 
     stub_buf
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index bf38c02e908..10aaadd5688 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -329,12 +329,18 @@ pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {
             // Source: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/079772828bd10933d34121117a222b4cc0ee2200/riscv-elf.adoc
             let mut e_flags: u32 = 0x0;
 
-            // Check if compressed is enabled
-            // `unstable_target_features` is used here because "c" is gated behind riscv_target_feature.
-            if sess.unstable_target_features.contains(&sym::c) {
+            // Check if compression is enabled
+            // `unstable_target_features` is used here because "zca" is gated behind riscv_target_feature.
+            if sess.unstable_target_features.contains(&sym::zca) {
                 e_flags |= elf::EF_RISCV_RVC;
             }
 
+            // Check if RVTSO is enabled
+            // `unstable_target_features` is used here because "ztso" is gated behind riscv_target_feature.
+            if sess.unstable_target_features.contains(&sym::ztso) {
+                e_flags |= elf::EF_RISCV_TSO;
+            }
+
             // Set the appropriate flag based on ABI
             // This needs to match LLVM `RISCVELFStreamer.cpp`
             match &*sess.target.llvm_abiname {
diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
index 77096822fdc..13419bcb22c 100644
--- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
+++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs
@@ -570,7 +570,7 @@ fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel
     // core/std/allocators/etc. For example symbols used to hook up allocation
     // are not considered for export
     let codegen_fn_attrs = tcx.codegen_fn_attrs(sym_def_id);
-    let is_extern = codegen_fn_attrs.contains_extern_indicator(tcx, sym_def_id);
+    let is_extern = codegen_fn_attrs.contains_extern_indicator();
     let std_internal =
         codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
 
diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs
index 26d089a1171..8586615f7c7 100644
--- a/compiler/rustc_codegen_ssa/src/back/write.rs
+++ b/compiler/rustc_codegen_ssa/src/back/write.rs
@@ -1,5 +1,6 @@
 use std::assert_matches::assert_matches;
 use std::marker::PhantomData;
+use std::panic::AssertUnwindSafe;
 use std::path::{Path, PathBuf};
 use std::sync::Arc;
 use std::sync::mpsc::{Receiver, Sender, channel};
@@ -14,7 +15,7 @@ use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard};
 use rustc_errors::emitter::Emitter;
 use rustc_errors::translation::Translator;
 use rustc_errors::{
-    Diag, DiagArgMap, DiagCtxt, DiagMessage, ErrCode, FatalError, Level, MultiSpan, Style,
+    Diag, DiagArgMap, DiagCtxt, DiagMessage, ErrCode, FatalErrorMarker, Level, MultiSpan, Style,
     Suggestions,
 };
 use rustc_fs_util::link_or_copy;
@@ -395,8 +396,7 @@ fn generate_thin_lto_work<B: ExtraBackendMethods>(
         each_linked_rlib_for_lto,
         needs_thin_lto,
         import_only_modules,
-    )
-    .unwrap_or_else(|e| e.raise());
+    );
     lto_modules
         .into_iter()
         .map(|module| {
@@ -844,11 +844,11 @@ fn execute_optimize_work_item<B: ExtraBackendMethods>(
     cgcx: &CodegenContext<B>,
     mut module: ModuleCodegen<B::Module>,
     module_config: &ModuleConfig,
-) -> Result<WorkItemResult<B>, FatalError> {
+) -> WorkItemResult<B> {
     let dcx = cgcx.create_dcx();
     let dcx = dcx.handle();
 
-    B::optimize(cgcx, dcx, &mut module, module_config)?;
+    B::optimize(cgcx, dcx, &mut module, module_config);
 
     // After we've done the initial round of optimizations we need to
     // decide whether to synchronously codegen this module or ship it
@@ -868,8 +868,8 @@ fn execute_optimize_work_item<B: ExtraBackendMethods>(
 
     match lto_type {
         ComputedLtoType::No => {
-            let module = B::codegen(cgcx, module, module_config)?;
-            Ok(WorkItemResult::Finished(module))
+            let module = B::codegen(cgcx, module, module_config);
+            WorkItemResult::Finished(module)
         }
         ComputedLtoType::Thin => {
             let (name, thin_buffer) = B::prepare_thin(module, false);
@@ -878,7 +878,7 @@ fn execute_optimize_work_item<B: ExtraBackendMethods>(
                     panic!("Error writing pre-lto-bitcode file `{}`: {}", path.display(), e);
                 });
             }
-            Ok(WorkItemResult::NeedsThinLto(name, thin_buffer))
+            WorkItemResult::NeedsThinLto(name, thin_buffer)
         }
         ComputedLtoType::Fat => match bitcode {
             Some(path) => {
@@ -886,12 +886,12 @@ fn execute_optimize_work_item<B: ExtraBackendMethods>(
                 fs::write(&path, buffer.data()).unwrap_or_else(|e| {
                     panic!("Error writing pre-lto-bitcode file `{}`: {}", path.display(), e);
                 });
-                Ok(WorkItemResult::NeedsFatLto(FatLtoInput::Serialized {
+                WorkItemResult::NeedsFatLto(FatLtoInput::Serialized {
                     name,
                     buffer: SerializedModule::Local(buffer),
-                }))
+                })
             }
-            None => Ok(WorkItemResult::NeedsFatLto(FatLtoInput::InMemory(module))),
+            None => WorkItemResult::NeedsFatLto(FatLtoInput::InMemory(module)),
         },
     }
 }
@@ -987,7 +987,7 @@ fn execute_fat_lto_work_item<B: ExtraBackendMethods>(
     mut needs_fat_lto: Vec<FatLtoInput<B>>,
     import_only_modules: Vec<(SerializedModule<B::ModuleBuffer>, WorkProduct)>,
     module_config: &ModuleConfig,
-) -> Result<WorkItemResult<B>, FatalError> {
+) -> WorkItemResult<B> {
     for (module, wp) in import_only_modules {
         needs_fat_lto.push(FatLtoInput::Serialized { name: wp.cgu_name, buffer: module })
     }
@@ -997,19 +997,19 @@ fn execute_fat_lto_work_item<B: ExtraBackendMethods>(
         exported_symbols_for_lto,
         each_linked_rlib_for_lto,
         needs_fat_lto,
-    )?;
-    let module = B::codegen(cgcx, module, module_config)?;
-    Ok(WorkItemResult::Finished(module))
+    );
+    let module = B::codegen(cgcx, module, module_config);
+    WorkItemResult::Finished(module)
 }
 
 fn execute_thin_lto_work_item<B: ExtraBackendMethods>(
     cgcx: &CodegenContext<B>,
     module: lto::ThinModule<B>,
     module_config: &ModuleConfig,
-) -> Result<WorkItemResult<B>, FatalError> {
-    let module = B::optimize_thin(cgcx, module)?;
-    let module = B::codegen(cgcx, module, module_config)?;
-    Ok(WorkItemResult::Finished(module))
+) -> WorkItemResult<B> {
+    let module = B::optimize_thin(cgcx, module);
+    let module = B::codegen(cgcx, module, module_config);
+    WorkItemResult::Finished(module)
 }
 
 /// Messages sent to the coordinator.
@@ -1722,37 +1722,10 @@ fn spawn_work<'a, B: ExtraBackendMethods>(
     let cgcx = cgcx.clone();
 
     B::spawn_named_thread(cgcx.time_trace, work.short_description(), move || {
-        // Set up a destructor which will fire off a message that we're done as
-        // we exit.
-        struct Bomb<B: ExtraBackendMethods> {
-            coordinator_send: Sender<Message<B>>,
-            result: Option<Result<WorkItemResult<B>, FatalError>>,
-        }
-        impl<B: ExtraBackendMethods> Drop for Bomb<B> {
-            fn drop(&mut self) {
-                let msg = match self.result.take() {
-                    Some(Ok(result)) => Message::WorkItem::<B> { result: Ok(result) },
-                    Some(Err(FatalError)) => {
-                        Message::WorkItem::<B> { result: Err(Some(WorkerFatalError)) }
-                    }
-                    None => Message::WorkItem::<B> { result: Err(None) },
-                };
-                drop(self.coordinator_send.send(msg));
-            }
-        }
-
-        let mut bomb = Bomb::<B> { coordinator_send, result: None };
-
-        // Execute the work itself, and if it finishes successfully then flag
-        // ourselves as a success as well.
-        //
-        // Note that we ignore any `FatalError` coming out of `execute_work_item`,
-        // as a diagnostic was already sent off to the main thread - just
-        // surface that there was an error in this worker.
-        bomb.result = {
+        let result = std::panic::catch_unwind(AssertUnwindSafe(|| {
             let module_config = cgcx.config(work.module_kind());
 
-            Some(match work {
+            match work {
                 WorkItem::Optimize(m) => {
                     let _timer =
                         cgcx.prof.generic_activity_with_arg("codegen_module_optimize", &*m.name);
@@ -1763,7 +1736,7 @@ fn spawn_work<'a, B: ExtraBackendMethods>(
                         "codegen_copy_artifacts_from_incr_cache",
                         &*m.name,
                     );
-                    Ok(execute_copy_from_cache_work_item(&cgcx, m, module_config))
+                    execute_copy_from_cache_work_item(&cgcx, m, module_config)
                 }
                 WorkItem::FatLto {
                     exported_symbols_for_lto,
@@ -1788,8 +1761,22 @@ fn spawn_work<'a, B: ExtraBackendMethods>(
                         cgcx.prof.generic_activity_with_arg("codegen_module_perform_lto", m.name());
                     execute_thin_lto_work_item(&cgcx, m, module_config)
                 }
-            })
+            }
+        }));
+
+        let msg = match result {
+            Ok(result) => Message::WorkItem::<B> { result: Ok(result) },
+
+            // We ignore any `FatalError` coming out of `execute_work_item`, as a
+            // diagnostic was already sent off to the main thread - just surface
+            // that there was an error in this worker.
+            Err(err) if err.is::<FatalErrorMarker>() => {
+                Message::WorkItem::<B> { result: Err(Some(WorkerFatalError)) }
+            }
+
+            Err(_) => Message::WorkItem::<B> { result: Err(None) },
         };
+        drop(coordinator_send.send(msg));
     })
     .expect("failed to spawn work thread");
 }
@@ -1970,10 +1957,13 @@ impl<B: ExtraBackendMethods> Drop for Coordinator<B> {
 pub struct OngoingCodegen<B: ExtraBackendMethods> {
     pub backend: B,
     pub crate_info: CrateInfo,
-    pub codegen_worker_receive: Receiver<CguMessage>,
-    pub shared_emitter_main: SharedEmitterMain,
     pub output_filenames: Arc<OutputFilenames>,
+    // Field order below is intended to terminate the coordinator thread before two fields below
+    // drop and prematurely close channels used by coordinator thread. See `Coordinator`'s
+    // `Drop` implementation for more info.
     pub coordinator: Coordinator<B>,
+    pub codegen_worker_receive: Receiver<CguMessage>,
+    pub shared_emitter_main: SharedEmitterMain,
 }
 
 impl<B: ExtraBackendMethods> OngoingCodegen<B> {
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 23e2abd6de3..961bb788149 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -293,6 +293,9 @@ fn process_builtin_attrs(
                         codegen_fn_attrs.linkage = linkage;
                     }
                 }
+                AttributeKind::Sanitize { span, .. } => {
+                    interesting_spans.sanitize = Some(*span);
+                }
                 _ => {}
             }
         }
@@ -310,7 +313,6 @@ fn process_builtin_attrs(
                 codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED
             }
             sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL,
-            sym::sanitize => interesting_spans.sanitize = Some(attr.span()),
             sym::instruction_set => {
                 codegen_fn_attrs.instruction_set = parse_instruction_set_attr(tcx, attr)
             }
@@ -383,6 +385,8 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code
 
     // Foreign items by default use no mangling for their symbol name.
     if tcx.is_foreign_item(did) {
+        codegen_fn_attrs.flags |= CodegenFnAttrFlags::FOREIGN_ITEM;
+
         // There's a few exceptions to this rule though:
         if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
             // * `#[rustc_std_internal_symbol]` mangles the symbol name in a special way
@@ -560,79 +564,9 @@ fn opt_trait_item(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
     }
 }
 
-/// For an attr that has the `sanitize` attribute, read the list of
-/// disabled sanitizers. `current_attr` holds the information about
-/// previously parsed attributes.
-fn parse_sanitize_attr(
-    tcx: TyCtxt<'_>,
-    attr: &Attribute,
-    current_attr: SanitizerSet,
-) -> SanitizerSet {
-    let mut result = current_attr;
-    if let Some(list) = attr.meta_item_list() {
-        for item in list.iter() {
-            let MetaItemInner::MetaItem(set) = item else {
-                tcx.dcx().emit_err(errors::InvalidSanitize { span: attr.span() });
-                break;
-            };
-            let segments = set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
-            match segments.as_slice() {
-                // Similar to clang, sanitize(address = ..) and
-                // sanitize(kernel_address = ..) control both ASan and KASan
-                // Source: https://reviews.llvm.org/D44981.
-                [sym::address] | [sym::kernel_address] if set.value_str() == Some(sym::off) => {
-                    result |= SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS
-                }
-                [sym::address] | [sym::kernel_address] if set.value_str() == Some(sym::on) => {
-                    result &= !SanitizerSet::ADDRESS;
-                    result &= !SanitizerSet::KERNELADDRESS;
-                }
-                [sym::cfi] if set.value_str() == Some(sym::off) => result |= SanitizerSet::CFI,
-                [sym::cfi] if set.value_str() == Some(sym::on) => result &= !SanitizerSet::CFI,
-                [sym::kcfi] if set.value_str() == Some(sym::off) => result |= SanitizerSet::KCFI,
-                [sym::kcfi] if set.value_str() == Some(sym::on) => result &= !SanitizerSet::KCFI,
-                [sym::memory] if set.value_str() == Some(sym::off) => {
-                    result |= SanitizerSet::MEMORY
-                }
-                [sym::memory] if set.value_str() == Some(sym::on) => {
-                    result &= !SanitizerSet::MEMORY
-                }
-                [sym::memtag] if set.value_str() == Some(sym::off) => {
-                    result |= SanitizerSet::MEMTAG
-                }
-                [sym::memtag] if set.value_str() == Some(sym::on) => {
-                    result &= !SanitizerSet::MEMTAG
-                }
-                [sym::shadow_call_stack] if set.value_str() == Some(sym::off) => {
-                    result |= SanitizerSet::SHADOWCALLSTACK
-                }
-                [sym::shadow_call_stack] if set.value_str() == Some(sym::on) => {
-                    result &= !SanitizerSet::SHADOWCALLSTACK
-                }
-                [sym::thread] if set.value_str() == Some(sym::off) => {
-                    result |= SanitizerSet::THREAD
-                }
-                [sym::thread] if set.value_str() == Some(sym::on) => {
-                    result &= !SanitizerSet::THREAD
-                }
-                [sym::hwaddress] if set.value_str() == Some(sym::off) => {
-                    result |= SanitizerSet::HWADDRESS
-                }
-                [sym::hwaddress] if set.value_str() == Some(sym::on) => {
-                    result &= !SanitizerSet::HWADDRESS
-                }
-                _ => {
-                    tcx.dcx().emit_err(errors::InvalidSanitize { span: attr.span() });
-                }
-            }
-        }
-    }
-    result
-}
-
 fn disabled_sanitizers_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerSet {
     // Backtrack to the crate root.
-    let disabled = match tcx.opt_local_parent(did) {
+    let mut disabled = match tcx.opt_local_parent(did) {
         // Check the parent (recursively).
         Some(parent) => tcx.disabled_sanitizers_for(parent),
         // We reached the crate root without seeing an attribute, so
@@ -641,8 +575,17 @@ fn disabled_sanitizers_for(tcx: TyCtxt<'_>, did: LocalDefId) -> SanitizerSet {
     };
 
     // Check for a sanitize annotation directly on this def.
-    if let Some(attr) = tcx.get_attr(did, sym::sanitize) {
-        return parse_sanitize_attr(tcx, attr, disabled);
+    if let Some((on_set, off_set)) = find_attr!(tcx.get_all_attrs(did), AttributeKind::Sanitize {on_set, off_set, ..} => (on_set, off_set))
+    {
+        // the on set is the set of sanitizers explicitly enabled.
+        // we mask those out since we want the set of disabled sanitizers here
+        disabled &= !*on_set;
+        // the off set is the set of sanitizers explicitly disabled.
+        // we or those in here.
+        disabled |= *off_set;
+        // the on set and off set are distjoint since there's a third option: unset.
+        // a node may not set the sanitizer setting in which case it inherits from parents.
+        // the code above in this function does this backtracking
     }
     disabled
 }
diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs
index a6fd6c763ed..08e2f355953 100644
--- a/compiler/rustc_codegen_ssa/src/common.rs
+++ b/compiler/rustc_codegen_ssa/src/common.rs
@@ -1,10 +1,11 @@
 #![allow(non_camel_case_types)]
 
 use rustc_hir::LangItem;
+use rustc_hir::attrs::PeImportNameType;
 use rustc_middle::ty::layout::TyAndLayout;
 use rustc_middle::ty::{self, Instance, TyCtxt};
 use rustc_middle::{bug, mir, span_bug};
-use rustc_session::cstore::{DllCallingConvention, DllImport, PeImportNameType};
+use rustc_session::cstore::{DllCallingConvention, DllImport};
 use rustc_span::Span;
 use rustc_target::spec::Target;
 
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index 209c78ddeda..fb5a8205140 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -1121,14 +1121,6 @@ impl IntoDiagArg for ExpectedPointerMutability {
 }
 
 #[derive(Diagnostic)]
-#[diag(codegen_ssa_invalid_sanitize)]
-#[note]
-pub(crate) struct InvalidSanitize {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(codegen_ssa_target_feature_safe_trait)]
 pub(crate) struct TargetFeatureSafeTrait {
     #[primary_span]
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 23ed387a3ff..fe0500a5d4c 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -25,10 +25,10 @@ use std::io;
 use std::path::{Path, PathBuf};
 use std::sync::Arc;
 
-use rustc_ast as ast;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_data_structures::unord::UnordMap;
 use rustc_hir::CRATE_HIR_ID;
+use rustc_hir::attrs::{CfgEntry, NativeLibKind};
 use rustc_hir::def_id::CrateNum;
 use rustc_macros::{Decodable, Encodable, HashStable};
 use rustc_metadata::EncodedMetadata;
@@ -45,7 +45,6 @@ use rustc_session::Session;
 use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT};
 use rustc_session::cstore::{self, CrateSource};
 use rustc_session::lint::builtin::LINKER_MESSAGES;
-use rustc_session::utils::NativeLibKind;
 use rustc_span::Symbol;
 
 pub mod assert_module_sources;
@@ -187,7 +186,7 @@ pub struct NativeLib {
     pub kind: NativeLibKind,
     pub name: Symbol,
     pub filename: Option<Symbol>,
-    pub cfg: Option<ast::MetaItemInner>,
+    pub cfg: Option<CfgEntry>,
     pub verbatim: bool,
     pub dll_imports: Vec<cstore::DllImport>,
 }
diff --git a/compiler/rustc_codegen_ssa/src/traits/write.rs b/compiler/rustc_codegen_ssa/src/traits/write.rs
index c29ad90735b..cc7c4e46d7b 100644
--- a/compiler/rustc_codegen_ssa/src/traits/write.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/write.rs
@@ -1,6 +1,6 @@
 use std::path::PathBuf;
 
-use rustc_errors::{DiagCtxtHandle, FatalError};
+use rustc_errors::DiagCtxtHandle;
 use rustc_middle::dep_graph::WorkProduct;
 
 use crate::back::lto::{SerializedModule, ThinModule};
@@ -22,7 +22,7 @@ pub trait WriteBackendMethods: Clone + 'static {
         exported_symbols_for_lto: &[String],
         each_linked_rlib_for_lto: &[PathBuf],
         modules: Vec<FatLtoInput<Self>>,
-    ) -> Result<ModuleCodegen<Self::Module>, FatalError>;
+    ) -> ModuleCodegen<Self::Module>;
     /// Performs thin LTO by performing necessary global analysis and returning two
     /// lists, one of the modules that need optimization and another for modules that
     /// can simply be copied over from the incr. comp. cache.
@@ -32,7 +32,7 @@ pub trait WriteBackendMethods: Clone + 'static {
         each_linked_rlib_for_lto: &[PathBuf],
         modules: Vec<(String, Self::ThinBuffer)>,
         cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
-    ) -> Result<(Vec<ThinModule<Self>>, Vec<WorkProduct>), FatalError>;
+    ) -> (Vec<ThinModule<Self>>, Vec<WorkProduct>);
     fn print_pass_timings(&self);
     fn print_statistics(&self);
     fn optimize(
@@ -40,16 +40,16 @@ pub trait WriteBackendMethods: Clone + 'static {
         dcx: DiagCtxtHandle<'_>,
         module: &mut ModuleCodegen<Self::Module>,
         config: &ModuleConfig,
-    ) -> Result<(), FatalError>;
+    );
     fn optimize_thin(
         cgcx: &CodegenContext<Self>,
         thin: ThinModule<Self>,
-    ) -> Result<ModuleCodegen<Self::Module>, FatalError>;
+    ) -> ModuleCodegen<Self::Module>;
     fn codegen(
         cgcx: &CodegenContext<Self>,
         module: ModuleCodegen<Self::Module>,
         config: &ModuleConfig,
-    ) -> Result<CompiledModule, FatalError>;
+    ) -> CompiledModule;
     fn prepare_thin(
         module: ModuleCodegen<Self::Module>,
         want_summary: bool,
diff --git a/compiler/rustc_const_eval/Cargo.toml b/compiler/rustc_const_eval/Cargo.toml
index 51dcee8d882..88dfc83f7fc 100644
--- a/compiler/rustc_const_eval/Cargo.toml
+++ b/compiler/rustc_const_eval/Cargo.toml
@@ -22,5 +22,5 @@ rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index da954cf4ed7..fccb6b171b1 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -280,22 +280,110 @@ impl<'tcx> CompileTimeInterpCx<'tcx> {
         interp_ok(match (a, b) {
             // Comparisons between integers are always known.
             (Scalar::Int(a), Scalar::Int(b)) => (a == b) as u8,
-            // Comparisons of null with an arbitrary scalar can be known if `scalar_may_be_null`
-            // indicates that the scalar can definitely *not* be null.
-            (Scalar::Int(int), ptr) | (ptr, Scalar::Int(int))
-                if int.is_null() && !self.scalar_may_be_null(ptr)? =>
-            {
-                0
+            // Comparing a pointer `ptr` with an integer `int` is equivalent to comparing
+            // `ptr-int` with null, so we can reduce this case to a `scalar_may_be_null` test.
+            (Scalar::Int(int), Scalar::Ptr(ptr, _)) | (Scalar::Ptr(ptr, _), Scalar::Int(int)) => {
+                let int = int.to_target_usize(*self.tcx);
+                // The `wrapping_neg` here may produce a value that is not
+                // a valid target usize any more... but `wrapping_offset` handles that correctly.
+                let offset_ptr = ptr.wrapping_offset(Size::from_bytes(int.wrapping_neg()), self);
+                if !self.scalar_may_be_null(Scalar::from_pointer(offset_ptr, self))? {
+                    // `ptr.wrapping_sub(int)` is definitely not equal to `0`, so `ptr != int`
+                    0
+                } else {
+                    // `ptr.wrapping_sub(int)` could be equal to `0`, but might not be,
+                    // so we cannot know for sure if `ptr == int` or not
+                    2
+                }
+            }
+            (Scalar::Ptr(a, _), Scalar::Ptr(b, _)) => {
+                let (a_prov, a_offset) = a.prov_and_relative_offset();
+                let (b_prov, b_offset) = b.prov_and_relative_offset();
+                let a_allocid = a_prov.alloc_id();
+                let b_allocid = b_prov.alloc_id();
+                let a_info = self.get_alloc_info(a_allocid);
+                let b_info = self.get_alloc_info(b_allocid);
+
+                // Check if the pointers cannot be equal due to alignment
+                if a_info.align > Align::ONE && b_info.align > Align::ONE {
+                    let min_align = Ord::min(a_info.align.bytes(), b_info.align.bytes());
+                    let a_residue = a_offset.bytes() % min_align;
+                    let b_residue = b_offset.bytes() % min_align;
+                    if a_residue != b_residue {
+                        // If the two pointers have a different residue modulo their
+                        // common alignment, they cannot be equal.
+                        return interp_ok(0);
+                    }
+                    // The pointers have the same residue modulo their common alignment,
+                    // so they could be equal. Try the other checks.
+                }
+
+                if let (Some(GlobalAlloc::Static(a_did)), Some(GlobalAlloc::Static(b_did))) = (
+                    self.tcx.try_get_global_alloc(a_allocid),
+                    self.tcx.try_get_global_alloc(b_allocid),
+                ) {
+                    if a_allocid == b_allocid {
+                        debug_assert_eq!(
+                            a_did, b_did,
+                            "different static item DefIds had same AllocId? {a_allocid:?} == {b_allocid:?}, {a_did:?} != {b_did:?}"
+                        );
+                        // Comparing two pointers into the same static. As per
+                        // https://doc.rust-lang.org/nightly/reference/items/static-items.html#r-items.static.intro
+                        // a static cannot be duplicated, so if two pointers are into the same
+                        // static, they are equal if and only if their offsets are equal.
+                        (a_offset == b_offset) as u8
+                    } else {
+                        debug_assert_ne!(
+                            a_did, b_did,
+                            "same static item DefId had two different AllocIds? {a_allocid:?} != {b_allocid:?}, {a_did:?} == {b_did:?}"
+                        );
+                        // Comparing two pointers into the different statics.
+                        // We can never determine for sure that two pointers into different statics
+                        // are *equal*, but we can know that they are *inequal* if they are both
+                        // strictly in-bounds (i.e. in-bounds and not one-past-the-end) of
+                        // their respective static, as different non-zero-sized statics cannot
+                        // overlap or be deduplicated as per
+                        // https://doc.rust-lang.org/nightly/reference/items/static-items.html#r-items.static.intro
+                        // (non-deduplication), and
+                        // https://doc.rust-lang.org/nightly/reference/items/static-items.html#r-items.static.storage-disjointness
+                        // (non-overlapping).
+                        if a_offset < a_info.size && b_offset < b_info.size {
+                            0
+                        } else {
+                            // Otherwise, conservatively say we don't know.
+                            // There are some cases we could still return `0` for, e.g.
+                            // if the pointers being equal would require their statics to overlap
+                            // one or more bytes, but for simplicity we currently only check
+                            // strictly in-bounds pointers.
+                            2
+                        }
+                    }
+                } else {
+                    // All other cases we conservatively say we don't know.
+                    //
+                    // For comparing statics to non-statics, as per https://doc.rust-lang.org/nightly/reference/items/static-items.html#r-items.static.storage-disjointness
+                    // immutable statics can overlap with other kinds of allocations sometimes.
+                    //
+                    // FIXME: We could be more decisive for (non-zero-sized) mutable statics,
+                    // which cannot overlap with other kinds of allocations.
+                    //
+                    // Functions and vtables can be duplicated and deduplicated, so we
+                    // cannot be sure of runtime equality of pointers to the same one, or the
+                    // runtime inequality of pointers to different ones (see e.g. #73722),
+                    // so comparing those should return 2, whether they are the same allocation
+                    // or not.
+                    //
+                    // `GlobalAlloc::TypeId` exists mostly to prevent consteval from comparing
+                    // `TypeId`s, so comparing those should always return 2, whether they are the
+                    // same allocation or not.
+                    //
+                    // FIXME: We could revisit comparing pointers into the same
+                    // `GlobalAlloc::Memory` once https://github.com/rust-lang/rust/issues/128775
+                    // is fixed (but they can be deduplicated, so comparing pointers into different
+                    // ones should return 2).
+                    2
+                }
             }
-            // Other ways of comparing integers and pointers can never be known for sure.
-            (Scalar::Int { .. }, Scalar::Ptr(..)) | (Scalar::Ptr(..), Scalar::Int { .. }) => 2,
-            // FIXME: return a `1` for when both sides are the same pointer, *except* that
-            // some things (like functions and vtables) do not have stable addresses
-            // so we need to be careful around them (see e.g. #73722).
-            // FIXME: return `0` for at least some comparisons where we can reliably
-            // determine the result of runtime inequality tests at compile-time.
-            // Examples include comparison of addresses in different static items.
-            (Scalar::Ptr(..), Scalar::Ptr(..)) => 2,
         })
     }
 }
diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs
index 084d45cf2cb..23d362de308 100644
--- a/compiler/rustc_const_eval/src/interpret/step.rs
+++ b/compiler/rustc_const_eval/src/interpret/step.rs
@@ -2,6 +2,8 @@
 //!
 //! The main entry point is the `step` method.
 
+use std::iter;
+
 use either::Either;
 use rustc_abi::{FIRST_VARIANT, FieldIdx};
 use rustc_data_structures::fx::FxHashSet;
@@ -426,6 +428,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         terminator: &mir::Terminator<'tcx>,
         func: &mir::Operand<'tcx>,
         args: &[Spanned<mir::Operand<'tcx>>],
+        dest: &mir::Place<'tcx>,
     ) -> InterpResult<'tcx, EvaluatedCalleeAndArgs<'tcx, M>> {
         let func = self.eval_operand(func, None)?;
 
@@ -435,14 +438,20 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
         // protection, but then we'd force *a lot* of arguments into memory. So we do some syntactic
         // pre-processing here where if all `move` arguments are syntactically distinct local
         // variables (and none is indirect), we can skip the in-memory forcing.
+        // We have to include `dest` in that list so that we can detect aliasing of an in-place
+        // argument with the return place.
         let move_definitely_disjoint = 'move_definitely_disjoint: {
             let mut previous_locals = FxHashSet::<mir::Local>::default();
-            for arg in args {
-                let mir::Operand::Move(place) = arg.node else {
-                    continue; // we can skip non-`Move` arguments.
-                };
+            for place in args
+                .iter()
+                .filter_map(|a| {
+                    // We only have to care about `Move` arguments.
+                    if let mir::Operand::Move(place) = &a.node { Some(place) } else { None }
+                })
+                .chain(iter::once(dest))
+            {
                 if place.is_indirect_first_projection() {
-                    // An indirect `Move` argument could alias with anything else...
+                    // An indirect in-place argument could alias with anything else...
                     break 'move_definitely_disjoint false;
                 }
                 if !previous_locals.insert(place.local) {
@@ -544,7 +553,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 let old_loc = self.frame().loc;
 
                 let EvaluatedCalleeAndArgs { callee, args, fn_sig, fn_abi, with_caller_location } =
-                    self.eval_callee_and_args(terminator, func, args)?;
+                    self.eval_callee_and_args(terminator, func, args, &destination)?;
 
                 let destination = self.eval_place(destination)?;
                 self.init_fn_call(
@@ -567,7 +576,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                 let old_frame_idx = self.frame_idx();
 
                 let EvaluatedCalleeAndArgs { callee, args, fn_sig, fn_abi, with_caller_location } =
-                    self.eval_callee_and_args(terminator, func, args)?;
+                    self.eval_callee_and_args(terminator, func, args, &mir::Place::return_place())?;
 
                 self.init_fn_tail_call(callee, (fn_sig.abi, fn_abi), &args, with_caller_location)?;
 
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index 17204883fb0..0ac9e02508a 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -6,13 +6,14 @@ edition = "2024"
 [dependencies]
 # tidy-alphabetical-start
 arrayvec = { version = "0.7", default-features = false }
-bitflags = "2.4.1"
+bitflags.workspace = true
 either = "1.0"
 elsa = "1.11.0"
 ena = "0.14.3"
 indexmap = "2.4.0"
 jobserver_crate = { version = "0.1.28", package = "jobserver" }
 measureme = "12.0.1"
+parking_lot = "0.12"
 rustc-hash = "2.0.0"
 rustc-stable-hash = { version = "0.1.0", features = ["nightly"] }
 rustc_arena = { path = "../rustc_arena" }
@@ -25,8 +26,8 @@ rustc_thread_pool = { path = "../rustc_thread_pool" }
 smallvec = { version = "1.8.1", features = ["const_generics", "union", "may_dangle"] }
 stacker = "0.1.17"
 tempfile = "3.2"
-thin-vec = "0.2.12"
-tracing = "0.1"
+thin-vec.workspace = true
+tracing.workspace = true
 # tidy-alphabetical-end
 
 [dependencies.hashbrown]
@@ -34,9 +35,6 @@ version = "0.15.2"
 default-features = false
 features = ["nightly"] # for may_dangle
 
-[dependencies.parking_lot]
-version = "0.12"
-
 [target.'cfg(windows)'.dependencies.windows]
 version = "0.61.0"
 features = [
diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml
index ae1dbd2cf51..7e9af054aff 100644
--- a/compiler/rustc_driver_impl/Cargo.toml
+++ b/compiler/rustc_driver_impl/Cargo.toml
@@ -51,7 +51,7 @@ rustc_trait_selection = { path = "../rustc_trait_selection" }
 rustc_ty_utils = { path = "../rustc_ty_utils" }
 serde_json = "1.0.59"
 shlex = "1.0"
-tracing = { version = "0.1.35" }
+tracing.workspace = true
 # tidy-alphabetical-end
 
 [target.'cfg(all(unix, any(target_env = "gnu", target_os = "macos")))'.dependencies]
diff --git a/compiler/rustc_error_codes/src/error_codes/E0458.md b/compiler/rustc_error_codes/src/error_codes/E0458.md
index 1b280cba44f..651bc378879 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0458.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0458.md
@@ -1,8 +1,10 @@
+#### Note: this error code is no longer emitted by the compiler.
+
 An unknown "kind" was specified for a link attribute.
 
 Erroneous code example:
 
-```compile_fail,E0458
+```ignore (no longer emitted)
 #[link(kind = "wonderful_unicorn")] extern "C" {}
 // error: unknown kind: `wonderful_unicorn`
 ```
diff --git a/compiler/rustc_error_messages/Cargo.toml b/compiler/rustc_error_messages/Cargo.toml
index 552ad672752..7d2dc20e136 100644
--- a/compiler/rustc_error_messages/Cargo.toml
+++ b/compiler/rustc_error_messages/Cargo.toml
@@ -7,9 +7,8 @@ edition = "2024"
 # tidy-alphabetical-start
 fluent-bundle = "0.16"
 fluent-syntax = "0.12"
-icu_list = "1.2"
-icu_locid = "1.2"
-icu_provider_adapters = "1.2"
+icu_list = { version = "2.0", default-features = false, features = ["alloc"] }
+icu_locale = { version = "2.0", default-features = false }
 intl-memoizer = "0.5.1"
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
@@ -18,6 +17,6 @@ rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_span = { path = "../rustc_span" }
-tracing = "0.1"
+tracing.workspace = true
 unic-langid = { version = "0.9.0", features = ["macros"] }
 # tidy-alphabetical-end
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index d8bacbe762b..7b7843f6cf3 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -15,7 +15,6 @@ use fluent_bundle::FluentResource;
 pub use fluent_bundle::types::FluentType;
 pub use fluent_bundle::{self, FluentArgs, FluentError, FluentValue};
 use fluent_syntax::parser::ParserError;
-use icu_provider_adapters::fallback::{LocaleFallbackProvider, LocaleFallbacker};
 use intl_memoizer::concurrent::IntlLangMemoizer;
 use rustc_data_structures::sync::{DynSend, IntoDynSyncSend};
 use rustc_macros::{Decodable, Encodable};
@@ -515,8 +514,8 @@ impl From<Vec<Span>> for MultiSpan {
     }
 }
 
-fn icu_locale_from_unic_langid(lang: LanguageIdentifier) -> Option<icu_locid::Locale> {
-    icu_locid::Locale::try_from_bytes(lang.to_string().as_bytes()).ok()
+fn icu_locale_from_unic_langid(lang: LanguageIdentifier) -> Option<icu_locale::Locale> {
+    icu_locale::Locale::try_from_str(&lang.to_string()).ok()
 }
 
 pub fn fluent_value_from_str_list_sep_by_and(l: Vec<Cow<'_, str>>) -> FluentValue<'_> {
@@ -568,21 +567,15 @@ pub fn fluent_value_from_str_list_sep_by_and(l: Vec<Cow<'_, str>>) -> FluentValu
         where
             Self: Sized,
         {
-            let baked_data_provider = rustc_baked_icu_data::baked_data_provider();
-            let locale_fallbacker =
-                LocaleFallbacker::try_new_with_any_provider(&baked_data_provider)
-                    .expect("Failed to create fallback provider");
-            let data_provider =
-                LocaleFallbackProvider::new_with_fallbacker(baked_data_provider, locale_fallbacker);
             let locale = icu_locale_from_unic_langid(lang)
                 .unwrap_or_else(|| rustc_baked_icu_data::supported_locales::EN);
-            let list_formatter =
-                icu_list::ListFormatter::try_new_and_with_length_with_any_provider(
-                    &data_provider,
-                    &locale.into(),
-                    icu_list::ListLength::Wide,
-                )
-                .expect("Failed to create list formatter");
+            let list_formatter = icu_list::ListFormatter::try_new_and_unstable(
+                &rustc_baked_icu_data::BakedDataProvider,
+                locale.into(),
+                icu_list::options::ListFormatterOptions::default()
+                    .with_length(icu_list::options::ListLength::Wide),
+            )
+            .expect("Failed to create list formatter");
 
             Ok(MemoizableListFormatter(list_formatter))
         }
diff --git a/compiler/rustc_errors/Cargo.toml b/compiler/rustc_errors/Cargo.toml
index f37b6fb748f..f5853855673 100644
--- a/compiler/rustc_errors/Cargo.toml
+++ b/compiler/rustc_errors/Cargo.toml
@@ -14,7 +14,6 @@ rustc_error_codes = { path = "../rustc_error_codes" }
 rustc_error_messages = { path = "../rustc_error_messages" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_hashes = { path = "../rustc_hashes" }
-rustc_hir_id = { path = "../rustc_hir_id" }
 rustc_index = { path = "../rustc_index" }
 rustc_lexer = { path = "../rustc_lexer" }
 rustc_lint_defs = { path = "../rustc_lint_defs" }
@@ -25,7 +24,7 @@ serde = { version = "1.0.125", features = ["derive"] }
 serde_json = "1.0.59"
 termcolor = "1.2.0"
 termize = "0.2"
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
 
 [target.'cfg(windows)'.dependencies.windows]
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 43ce886975c..96a4ed3218f 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -577,6 +577,29 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
         self.level = Level::DelayedBug;
     }
 
+    /// Make emitting this diagnostic fatal
+    ///
+    /// Changes the level of this diagnostic to Fatal, and importantly also changes the emission guarantee.
+    /// This is sound for errors that would otherwise be printed, but now simply exit the process instead.
+    /// This function still gives an emission guarantee, the guarantee is now just that it exits fatally.
+    /// For delayed bugs this is different, since those are buffered. If we upgrade one to fatal, another
+    /// might now be ignored.
+    #[rustc_lint_diagnostics]
+    #[track_caller]
+    pub fn upgrade_to_fatal(mut self) -> Diag<'a, FatalAbort> {
+        assert!(
+            matches!(self.level, Level::Error),
+            "upgrade_to_fatal: cannot upgrade {:?} to Fatal: not an error",
+            self.level
+        );
+        self.level = Level::Fatal;
+
+        // Take is okay since we immediately rewrap it in another diagnostic.
+        // i.e. we do emit it despite defusing the original diagnostic's drop bomb.
+        let diag = self.diag.take();
+        Diag { dcx: self.dcx, diag, _marker: PhantomData }
+    }
+
     with_fn! { with_span_label,
     /// Appends a labeled span to the diagnostic.
     ///
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 749bba5de12..b94370e8e9b 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -1462,7 +1462,7 @@ impl HumanEmitter {
         max_line_num_len: usize,
         is_secondary: bool,
         is_cont: bool,
-    ) -> io::Result<()> {
+    ) -> io::Result<CodeWindowStatus> {
         let mut buffer = StyledBuffer::new();
 
         if !msp.has_primary_spans() && !msp.has_span_labels() && is_secondary && !self.short_message
@@ -1575,12 +1575,14 @@ impl HumanEmitter {
         }
         let mut annotated_files = FileWithAnnotatedLines::collect_annotations(self, args, msp);
         trace!("{annotated_files:#?}");
+        let mut code_window_status = CodeWindowStatus::Open;
 
         // Make sure our primary file comes first
         let primary_span = msp.primary_span().unwrap_or_default();
         let (Some(sm), false) = (self.sm.as_ref(), primary_span.is_dummy()) else {
             // If we don't have span information, emit and exit
-            return emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message);
+            return emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)
+                .map(|_| code_window_status);
         };
         let primary_lo = sm.lookup_char_pos(primary_span.lo());
         if let Ok(pos) =
@@ -1589,6 +1591,9 @@ impl HumanEmitter {
             annotated_files.swap(0, pos);
         }
 
+        // An end column separator should be emitted when a file with with a
+        // source, is followed by one without a source
+        let mut col_sep_before_no_show_source = false;
         let annotated_files_len = annotated_files.len();
         // Print out the annotate source lines that correspond with the error
         for (file_idx, annotated_file) in annotated_files.into_iter().enumerate() {
@@ -1599,6 +1604,26 @@ impl HumanEmitter {
                 &annotated_file.file,
             ) {
                 if !self.short_message {
+                    // Add an end column separator when a file without a source
+                    // comes after one with a source
+                    //    ╭▸ $DIR/deriving-meta-unknown-trait.rs:1:10
+                    //    │
+                    // LL │ #[derive(Eqr)]
+                    //    │          ━━━
+                    //    ╰╴ (<- It prints *this* line)
+                    //    ╭▸ $SRC_DIR/core/src/cmp.rs:356:0
+                    //    │
+                    //    ╰╴note: similarly named derive macro `Eq` defined here
+                    if col_sep_before_no_show_source {
+                        let buffer_msg_line_offset = buffer.num_lines();
+                        self.draw_col_separator_end(
+                            &mut buffer,
+                            buffer_msg_line_offset,
+                            max_line_num_len + 1,
+                        );
+                    }
+                    col_sep_before_no_show_source = false;
+
                     // We'll just print an unannotated message.
                     for (annotation_id, line) in annotated_file.lines.iter().enumerate() {
                         let mut annotations = line.annotations.clone();
@@ -1639,29 +1664,42 @@ impl HumanEmitter {
                             }
                             line_idx += 1;
                         }
-                        for (label, is_primary) in labels.into_iter() {
+                        if is_cont
+                            && file_idx == annotated_files_len - 1
+                            && annotation_id == annotated_file.lines.len() - 1
+                            && !labels.is_empty()
+                        {
+                            code_window_status = CodeWindowStatus::Closed;
+                        }
+                        let labels_len = labels.len();
+                        for (label_idx, (label, is_primary)) in labels.into_iter().enumerate() {
                             let style = if is_primary {
                                 Style::LabelPrimary
                             } else {
                                 Style::LabelSecondary
                             };
-                            let pipe = self.col_separator();
-                            buffer.prepend(line_idx, &format!(" {pipe}"), Style::LineNumber);
-                            for _ in 0..max_line_num_len {
-                                buffer.prepend(line_idx, " ", Style::NoStyle);
-                            }
+                            self.draw_col_separator_no_space(
+                                &mut buffer,
+                                line_idx,
+                                max_line_num_len + 1,
+                            );
                             line_idx += 1;
-                            let chr = self.note_separator();
-                            buffer.append(line_idx, &format!(" {chr} note: "), style);
-                            for _ in 0..max_line_num_len {
-                                buffer.prepend(line_idx, " ", Style::NoStyle);
-                            }
+                            self.draw_note_separator(
+                                &mut buffer,
+                                line_idx,
+                                max_line_num_len + 1,
+                                label_idx != labels_len - 1,
+                            );
+                            buffer.append(line_idx, "note", Style::MainHeaderMsg);
+                            buffer.append(line_idx, ": ", Style::NoStyle);
                             buffer.append(line_idx, label, style);
                             line_idx += 1;
                         }
                     }
                 }
                 continue;
+            } else {
+                col_sep_before_no_show_source = true;
             }
 
             // print out the span location and spacer before we print the annotated source
@@ -1976,7 +2014,7 @@ impl HumanEmitter {
         // final step: take our styled buffer, render it, then output it
         emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?;
 
-        Ok(())
+        Ok(code_window_status)
     }
 
     fn column_width(&self, code_offset: usize) -> usize {
@@ -2491,7 +2529,7 @@ impl HumanEmitter {
             !children.is_empty()
                 || suggestions.iter().any(|s| s.style != SuggestionStyle::CompletelyHidden),
         ) {
-            Ok(()) => {
+            Ok(code_window_status) => {
                 if !children.is_empty()
                     || suggestions.iter().any(|s| s.style != SuggestionStyle::CompletelyHidden)
                 {
@@ -2502,7 +2540,7 @@ impl HumanEmitter {
                         {
                             // We'll continue the vertical bar to point into the next note.
                             self.draw_col_separator_no_space(&mut buffer, 0, max_line_num_len + 1);
-                        } else {
+                        } else if matches!(code_window_status, CodeWindowStatus::Open) {
                             // We'll close the vertical bar to visually end the code window.
                             self.draw_col_separator_end(&mut buffer, 0, max_line_num_len + 1);
                         }
@@ -2829,10 +2867,11 @@ impl HumanEmitter {
         }
     }
 
-    fn note_separator(&self) -> char {
+    fn note_separator(&self, is_cont: bool) -> &'static str {
         match self.theme {
-            OutputTheme::Ascii => '=',
-            OutputTheme::Unicode => '╰',
+            OutputTheme::Ascii => "= ",
+            OutputTheme::Unicode if is_cont => "├ ",
+            OutputTheme::Unicode => "╰ ",
         }
     }
 
@@ -2945,11 +2984,7 @@ impl HumanEmitter {
         col: usize,
         is_cont: bool,
     ) {
-        let chr = match self.theme {
-            OutputTheme::Ascii => "= ",
-            OutputTheme::Unicode if is_cont => "├ ",
-            OutputTheme::Unicode => "╰ ",
-        };
+        let chr = self.note_separator(is_cont);
         buffer.puts(line, col, chr, Style::LineNumber);
     }
 
@@ -3050,6 +3085,12 @@ enum DisplaySuggestion {
     Add,
 }
 
+#[derive(Clone, Copy, Debug)]
+enum CodeWindowStatus {
+    Closed,
+    Open,
+}
+
 impl FileWithAnnotatedLines {
     /// Preprocess all the annotations so that they are grouped by file and by line number
     /// This helps us quickly iterate over the whole message (including secondary file spans)
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 38c5716348f..71fc54f0d33 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -61,7 +61,6 @@ pub use rustc_error_messages::{
     fallback_fluent_bundle, fluent_bundle, into_diag_arg_using_display,
 };
 use rustc_hashes::Hash128;
-use rustc_hir_id::HirId;
 pub use rustc_lint_defs::{Applicability, listify, pluralize};
 use rustc_lint_defs::{Lint, LintExpectationId};
 use rustc_macros::{Decodable, Encodable};
@@ -110,13 +109,14 @@ rustc_data_structures::static_assert_size!(PResult<'_, bool>, 24);
 /// Used to avoid depending on `rustc_middle` in `rustc_attr_parsing`.
 /// Always the `TyCtxt`.
 pub trait LintEmitter: Copy {
+    type Id: Copy;
     #[track_caller]
     fn emit_node_span_lint(
         self,
         lint: &'static Lint,
-        hir_id: HirId,
+        hir_id: Self::Id,
         span: impl Into<MultiSpan>,
-        decorator: impl for<'a> LintDiagnostic<'a, ()>,
+        decorator: impl for<'a> LintDiagnostic<'a, ()> + DynSend + 'static,
     );
 }
 
diff --git a/compiler/rustc_expand/Cargo.toml b/compiler/rustc_expand/Cargo.toml
index f897833d85c..9bb7143af51 100644
--- a/compiler/rustc_expand/Cargo.toml
+++ b/compiler/rustc_expand/Cargo.toml
@@ -29,6 +29,6 @@ rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.12"
-tracing = "0.1"
+thin-vec.workspace = true
+tracing.workspace = true
 # tidy-alphabetical-end
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 012bfe226f2..dbb4a9de9e0 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -7,12 +7,12 @@ use rustc_ast::mut_visit::*;
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::visit::{self, AssocCtxt, Visitor, VisitorResult, try_visit, walk_list};
 use rustc_ast::{
-    self as ast, AssocItemKind, AstNodeWrapper, AttrArgs, AttrStyle, AttrVec, CRATE_NODE_ID,
-    DUMMY_NODE_ID, ExprKind, ForeignItemKind, HasAttrs, HasNodeId, Inline, ItemKind, MacStmtStyle,
-    MetaItemInner, MetaItemKind, ModKind, NodeId, PatKind, StmtKind, TyKind, token,
+    self as ast, AssocItemKind, AstNodeWrapper, AttrArgs, AttrStyle, AttrVec, DUMMY_NODE_ID,
+    ExprKind, ForeignItemKind, HasAttrs, HasNodeId, Inline, ItemKind, MacStmtStyle, MetaItemInner,
+    MetaItemKind, ModKind, NodeId, PatKind, StmtKind, TyKind, token,
 };
 use rustc_ast_pretty::pprust;
-use rustc_attr_parsing::{AttributeParser, EvalConfigResult, ShouldEmit, validate_attr};
+use rustc_attr_parsing::{AttributeParser, Early, EvalConfigResult, ShouldEmit, validate_attr};
 use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::PResult;
@@ -2165,7 +2165,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                 None,
                 Target::MacroCall,
                 call.span(),
-                CRATE_NODE_ID,
+                self.cx.current_expansion.lint_node_id,
                 Some(self.cx.ecfg.features),
                 ShouldEmit::ErrorsAndLints,
             );
@@ -2184,7 +2184,9 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
                     self.cx.current_expansion.lint_node_id,
                     BuiltinLintDiag::UnusedDocComment(attr.span),
                 );
-            } else if rustc_attr_parsing::is_builtin_attr(attr) {
+            } else if rustc_attr_parsing::is_builtin_attr(attr)
+                && !AttributeParser::<Early>::is_parsed_attribute(&attr.path())
+            {
                 let attr_name = attr.ident().unwrap().name;
                 // `#[cfg]` and `#[cfg_attr]` are special - they are
                 // eagerly evaluated.
diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml
index 1008a3e787d..ea72ed68c5e 100644
--- a/compiler/rustc_hir/Cargo.toml
+++ b/compiler/rustc_hir/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
-bitflags = "2.9.1"
+bitflags.workspace = true
 odht = { version = "0.3.1", features = ["nightly"] }
 rustc_abi = { path = "../rustc_abi" }
 rustc_arena = { path = "../rustc_arena" }
@@ -21,6 +21,6 @@ rustc_serialize = { path = "../rustc_serialize" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.12"
-tracing = "0.1"
+thin-vec.workspace = true
+tracing.workspace = true
 # tidy-alphabetical-end
diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs
index 2209b18df3f..dd5565d6f90 100644
--- a/compiler/rustc_hir/src/attrs/data_structures.rs
+++ b/compiler/rustc_hir/src/attrs/data_structures.rs
@@ -10,6 +10,7 @@ use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute};
 use rustc_span::def_id::DefId;
 use rustc_span::hygiene::Transparency;
 use rustc_span::{Ident, Span, Symbol};
+pub use rustc_target::spec::SanitizerSet;
 use thin_vec::ThinVec;
 
 use crate::attrs::pretty_printing::PrintAttribute;
@@ -247,6 +248,120 @@ impl IntoDiagArg for MirPhase {
     }
 }
 
+/// Different ways that the PE Format can decorate a symbol name.
+/// From <https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-name-type>
+#[derive(
+    Copy,
+    Clone,
+    Debug,
+    Encodable,
+    Decodable,
+    HashStable_Generic,
+    PartialEq,
+    Eq,
+    PrintAttribute
+)]
+pub enum PeImportNameType {
+    /// IMPORT_ORDINAL
+    /// Uses the ordinal (i.e., a number) rather than the name.
+    Ordinal(u16),
+    /// Same as IMPORT_NAME
+    /// Name is decorated with all prefixes and suffixes.
+    Decorated,
+    /// Same as IMPORT_NAME_NOPREFIX
+    /// Prefix (e.g., the leading `_` or `@`) is skipped, but suffix is kept.
+    NoPrefix,
+    /// Same as IMPORT_NAME_UNDECORATE
+    /// Prefix (e.g., the leading `_` or `@`) and suffix (the first `@` and all
+    /// trailing characters) are skipped.
+    Undecorated,
+}
+
+#[derive(
+    Copy,
+    Clone,
+    Debug,
+    PartialEq,
+    Eq,
+    PartialOrd,
+    Ord,
+    Hash,
+    Encodable,
+    Decodable,
+    PrintAttribute
+)]
+#[derive(HashStable_Generic)]
+pub enum NativeLibKind {
+    /// Static library (e.g. `libfoo.a` on Linux or `foo.lib` on Windows/MSVC)
+    Static {
+        /// Whether to bundle objects from static library into produced rlib
+        bundle: Option<bool>,
+        /// Whether to link static library without throwing any object files away
+        whole_archive: Option<bool>,
+    },
+    /// Dynamic library (e.g. `libfoo.so` on Linux)
+    /// or an import library corresponding to a dynamic library (e.g. `foo.lib` on Windows/MSVC).
+    Dylib {
+        /// Whether the dynamic library will be linked only if it satisfies some undefined symbols
+        as_needed: Option<bool>,
+    },
+    /// Dynamic library (e.g. `foo.dll` on Windows) without a corresponding import library.
+    /// On Linux, it refers to a generated shared library stub.
+    RawDylib,
+    /// A macOS-specific kind of dynamic libraries.
+    Framework {
+        /// Whether the framework will be linked only if it satisfies some undefined symbols
+        as_needed: Option<bool>,
+    },
+    /// Argument which is passed to linker, relative order with libraries and other arguments
+    /// is preserved
+    LinkArg,
+
+    /// Module imported from WebAssembly
+    WasmImportModule,
+
+    /// The library kind wasn't specified, `Dylib` is currently used as a default.
+    Unspecified,
+}
+
+impl NativeLibKind {
+    pub fn has_modifiers(&self) -> bool {
+        match self {
+            NativeLibKind::Static { bundle, whole_archive } => {
+                bundle.is_some() || whole_archive.is_some()
+            }
+            NativeLibKind::Dylib { as_needed } | NativeLibKind::Framework { as_needed } => {
+                as_needed.is_some()
+            }
+            NativeLibKind::RawDylib
+            | NativeLibKind::Unspecified
+            | NativeLibKind::LinkArg
+            | NativeLibKind::WasmImportModule => false,
+        }
+    }
+
+    pub fn is_statically_included(&self) -> bool {
+        matches!(self, NativeLibKind::Static { .. })
+    }
+
+    pub fn is_dllimport(&self) -> bool {
+        matches!(
+            self,
+            NativeLibKind::Dylib { .. } | NativeLibKind::RawDylib | NativeLibKind::Unspecified
+        )
+    }
+}
+
+#[derive(Debug, Encodable, Decodable, Clone, HashStable_Generic, PrintAttribute)]
+pub struct LinkEntry {
+    pub span: Span,
+    pub kind: NativeLibKind,
+    pub name: Symbol,
+    pub cfg: Option<CfgEntry>,
+    pub verbatim: Option<bool>,
+    pub import_name_type: Option<(PeImportNameType, Span)>,
+}
+
 /// Represents parsed *built-in* inert attributes.
 ///
 /// ## Overview
@@ -366,6 +481,9 @@ pub enum AttributeKind {
     /// Represents `#[coverage(..)]`.
     Coverage(Span, CoverageAttrKind),
 
+    /// Represents `#[crate_name = ...]`
+    CrateName { name: Symbol, name_span: Span, attr_span: Span, style: AttrStyle },
+
     /// Represents `#[custom_mir]`.
     CustomMir(Option<(MirDialect, Span)>, Option<(MirPhase, Span)>, Span),
 
@@ -414,6 +532,9 @@ pub enum AttributeKind {
     /// Represents `#[inline]` and `#[rustc_force_inline]`.
     Inline(InlineAttr, Span),
 
+    /// Represents `#[link]`.
+    Link(ThinVec<LinkEntry>, Span),
+
     /// Represents `#[link_name]`.
     LinkName { name: Symbol, span: Span },
 
@@ -505,6 +626,12 @@ pub enum AttributeKind {
     /// Represents `#[rustc_object_lifetime_default]`.
     RustcObjectLifetimeDefault,
 
+    /// Represents `#[sanitize]`
+    ///
+    /// the on set and off set are distjoint since there's a third option: unset.
+    /// a node may not set the sanitizer setting in which case it inherits from parents.
+    Sanitize { on_set: SanitizerSet, off_set: SanitizerSet, span: Span },
+
     /// Represents `#[should_panic]`
     ShouldPanic { reason: Option<Symbol>, span: Span },
 
diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs
index 485ded3981f..3810bb6d003 100644
--- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs
+++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs
@@ -7,6 +7,11 @@ pub enum EncodeCrossCrate {
 }
 
 impl AttributeKind {
+    /// Whether this attribute should be encoded in metadata files.
+    ///
+    /// If this is "Yes", then another crate can do `tcx.get_all_attrs(did)` for a did in this crate, and get the attribute.
+    /// When this is No, the attribute is filtered out while encoding and other crate won't be able to observe it.
+    /// This can be unexpectedly good for performance, so unless necessary for cross-crate compilation, prefer No.
     pub fn encode_cross_crate(&self) -> EncodeCrossCrate {
         use AttributeKind::*;
         use EncodeCrossCrate::*;
@@ -31,6 +36,7 @@ impl AttributeKind {
             ConstTrait(..) => No,
             Coroutine(..) => No,
             Coverage(..) => No,
+            CrateName { .. } => No,
             CustomMir(_, _, _) => Yes,
             DenyExplicitImpl(..) => No,
             Deprecation { .. } => Yes,
@@ -44,6 +50,7 @@ impl AttributeKind {
             Fundamental { .. } => Yes,
             Ignore { .. } => No,
             Inline(..) => No,
+            Link(..) => No,
             LinkName { .. } => Yes, // Needed for rustdoc
             LinkOrdinal { .. } => No,
             LinkSection { .. } => Yes, // Needed for rustdoc
@@ -73,6 +80,7 @@ impl AttributeKind {
             RustcLayoutScalarValidRangeEnd(..) => Yes,
             RustcLayoutScalarValidRangeStart(..) => Yes,
             RustcObjectLifetimeDefault => No,
+            Sanitize { .. } => No,
             ShouldPanic { .. } => No,
             SkipDuringMethodDispatch { .. } => No,
             SpecializationTrait(..) => No,
diff --git a/compiler/rustc_hir/src/attrs/pretty_printing.rs b/compiler/rustc_hir/src/attrs/pretty_printing.rs
index e44b29141da..e65de25b451 100644
--- a/compiler/rustc_hir/src/attrs/pretty_printing.rs
+++ b/compiler/rustc_hir/src/attrs/pretty_printing.rs
@@ -6,6 +6,7 @@ use rustc_ast::{AttrStyle, IntTy, UintTy};
 use rustc_ast_pretty::pp::Printer;
 use rustc_span::hygiene::Transparency;
 use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};
+use rustc_target::spec::SanitizerSet;
 use thin_vec::ThinVec;
 
 /// This trait is used to print attributes in `rustc_hir_pretty`.
@@ -146,4 +147,14 @@ macro_rules! print_tup {
 print_tup!(A B C D E F G H);
 print_skip!(Span, (), ErrorGuaranteed);
 print_disp!(u16, bool, NonZero<u32>);
-print_debug!(Symbol, Ident, UintTy, IntTy, Align, AttrStyle, CommentKind, Transparency);
+print_debug!(
+    Symbol,
+    Ident,
+    UintTy,
+    IntTy,
+    Align,
+    AttrStyle,
+    CommentKind,
+    Transparency,
+    SanitizerSet,
+);
diff --git a/compiler/rustc_hir/src/lints.rs b/compiler/rustc_hir/src/lints.rs
index 061ec786dc8..0b24052b453 100644
--- a/compiler/rustc_hir/src/lints.rs
+++ b/compiler/rustc_hir/src/lints.rs
@@ -35,4 +35,5 @@ pub enum AttributeLintKind {
     IllFormedAttributeInput { suggestions: Vec<String> },
     EmptyAttribute { first_span: Span },
     InvalidTarget { name: AttrPath, target: Target, applied: Vec<String>, only: &'static str },
+    InvalidStyle { name: AttrPath, is_used_as_inner: bool, target: Target, target_span: Span },
 }
diff --git a/compiler/rustc_hir_analysis/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml
index e5017794d8f..bb86beb2251 100644
--- a/compiler/rustc_hir_analysis/Cargo.toml
+++ b/compiler/rustc_hir_analysis/Cargo.toml
@@ -9,7 +9,7 @@ doctest = false
 
 [dependencies]
 # tidy-alphabetical-start
-itertools = "0.12"
+itertools.workspace = true
 rustc_abi = { path = "../rustc_abi" }
 rustc_arena = { path = "../rustc_arena" }
 rustc_ast = { path = "../rustc_ast" }
@@ -29,5 +29,5 @@ rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 2428c1aa29f..06f2ec512ab 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -509,10 +509,6 @@ hir_analysis_supertrait_item_shadowee = item from `{$supertrait}` is shadowed by
 
 hir_analysis_supertrait_item_shadowing = trait item `{$item}` from `{$subtrait}` shadows identically named item from supertrait
 
-hir_analysis_tait_forward_compat2 = item does not constrain `{$opaque_type}`
-    .note = consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
-    .opaque = this opaque type is supposed to be constrained
-
 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 target architecture
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 161a8566b04..eccb88a938f 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -2053,3 +2053,29 @@ pub(super) fn check_coroutine_obligations(
 
     Ok(())
 }
+
+pub(super) fn check_potentially_region_dependent_goals<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    def_id: LocalDefId,
+) -> Result<(), ErrorGuaranteed> {
+    if !tcx.next_trait_solver_globally() {
+        return Ok(());
+    }
+    let typeck_results = tcx.typeck(def_id);
+    let param_env = tcx.param_env(def_id);
+
+    // We use `TypingMode::Borrowck` as we want to use the opaque types computed by HIR typeck.
+    let typing_mode = TypingMode::borrowck(tcx, def_id);
+    let infcx = tcx.infer_ctxt().ignoring_regions().build(typing_mode);
+    let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
+    for (predicate, cause) in &typeck_results.potentially_region_dependent_goals {
+        let predicate = fold_regions(tcx, *predicate, |_, _| {
+            infcx.next_region_var(RegionVariableOrigin::Misc(cause.span))
+        });
+        ocx.register_obligation(Obligation::new(tcx, cause.clone(), param_env, predicate));
+    }
+
+    let errors = ocx.select_all_or_error();
+    debug!(?errors);
+    if errors.is_empty() { Ok(()) } else { Err(infcx.err_ctxt().report_fulfillment_errors(errors)) }
+}
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 85445cb3c00..2e4b151d4dc 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -109,6 +109,7 @@ pub(super) fn provide(providers: &mut Providers) {
         collect_return_position_impl_trait_in_trait_tys,
         compare_impl_item: compare_impl_item::compare_impl_item,
         check_coroutine_obligations: check::check_coroutine_obligations,
+        check_potentially_region_dependent_goals: check::check_potentially_region_dependent_goals,
         check_type_wf: wfcheck::check_type_wf,
         check_well_formed: wfcheck::check_well_formed,
         ..*providers
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
index 50e20a19eda..b6d898886ac 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -4,9 +4,10 @@ use rustc_hir::{self as hir, Expr, ImplItem, Item, Node, TraitItem, def, intravi
 use rustc_middle::bug;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, DefiningScopeKind, Ty, TyCtxt, TypeVisitableExt};
+use rustc_trait_selection::opaque_types::report_item_does_not_constrain_error;
 use tracing::{debug, instrument, trace};
 
-use crate::errors::{TaitForwardCompat2, UnconstrainedOpaqueType};
+use crate::errors::UnconstrainedOpaqueType;
 
 /// Checks "defining uses" of opaque `impl Trait` in associated types.
 /// These can only be defined by associated items of the same trait.
@@ -127,14 +128,11 @@ impl<'tcx> TaitConstraintLocator<'tcx> {
     }
 
     fn non_defining_use_in_defining_scope(&mut self, item_def_id: LocalDefId) {
-        let guar = self.tcx.dcx().emit_err(TaitForwardCompat2 {
-            span: self
-                .tcx
-                .def_ident_span(item_def_id)
-                .unwrap_or_else(|| self.tcx.def_span(item_def_id)),
-            opaque_type_span: self.tcx.def_span(self.def_id),
-            opaque_type: self.tcx.def_path_str(self.def_id),
-        });
+        // We make sure that all opaque types get defined while
+        // type checking the defining scope, so this error is unreachable
+        // with the new solver.
+        assert!(!self.tcx.next_trait_solver_globally());
+        let guar = report_item_does_not_constrain_error(self.tcx, item_def_id, self.def_id, None);
         self.insert_found(ty::OpaqueHiddenType::new_error(self.tcx, guar));
     }
 
@@ -252,9 +250,7 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
             } else if let Some(hidden_ty) = tables.concrete_opaque_types.get(&def_id) {
                 hidden_ty.ty
             } else {
-                // FIXME(-Znext-solver): This should not be necessary and we should
-                // instead rely on inference variable fallback inside of typeck itself.
-
+                assert!(!tcx.next_trait_solver_globally());
                 // We failed to resolve the opaque type or it
                 // resolves to itself. We interpret this as the
                 // no values of the hidden type ever being constructed,
@@ -273,6 +269,7 @@ pub(super) fn find_opaque_ty_constraints_for_rpit<'tcx>(
                     if let Err(guar) = hir_ty.error_reported() {
                         Ty::new_error(tcx, guar)
                     } else {
+                        assert!(!tcx.next_trait_solver_globally());
                         hir_ty
                     }
                 }
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 26a98722b34..6565ad7cf53 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -410,17 +410,6 @@ pub(crate) struct UnconstrainedOpaqueType {
     pub what: &'static str,
 }
 
-#[derive(Diagnostic)]
-#[diag(hir_analysis_tait_forward_compat2)]
-#[note]
-pub(crate) struct TaitForwardCompat2 {
-    #[primary_span]
-    pub span: Span,
-    #[note(hir_analysis_opaque)]
-    pub opaque_type_span: Span,
-    pub opaque_type: String,
-}
-
 pub(crate) struct MissingTypeParams {
     pub span: Span,
     pub def_span: Span,
diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs
index 3a153ab089a..44a5ceed469 100644
--- a/compiler/rustc_hir_analysis/src/lib.rs
+++ b/compiler/rustc_hir_analysis/src/lib.rs
@@ -82,7 +82,7 @@ mod coherence;
 mod collect;
 mod constrained_generic_params;
 mod delegation;
-mod errors;
+pub mod errors;
 pub mod hir_ty_lowering;
 pub mod hir_wf_check;
 mod impl_wf_check;
diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml
index f00125c3e09..5af0c6134ca 100644
--- a/compiler/rustc_hir_typeck/Cargo.toml
+++ b/compiler/rustc_hir_typeck/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
-itertools = "0.12"
+itertools.workspace = true
 rustc_abi = { path = "../rustc_abi" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_attr_parsing = { path = "../rustc_attr_parsing" }
@@ -25,5 +25,5 @@ rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index 7afc555b598..4200afb74e6 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -511,7 +511,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // Untranslatable diagnostics are okay for rustc internals
                 #[allow(rustc::untranslatable_diagnostic)]
                 #[allow(rustc::diagnostic_outside_of_impl)]
-                if self.tcx.has_attr(def_id, sym::rustc_evaluate_where_clauses) {
+                if self.has_rustc_attrs
+                    && self.tcx.has_attr(def_id, sym::rustc_evaluate_where_clauses)
+                {
                     let predicates = self.tcx.predicates_of(def_id);
                     let predicates = predicates.instantiate(self.tcx, args);
                     for (predicate, predicate_span) in predicates {
@@ -894,7 +896,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         // If we have `rustc_do_not_const_check`, do not check `[const]` bounds.
-        if self.tcx.has_attr(self.body_id, sym::rustc_do_not_const_check) {
+        if self.has_rustc_attrs && self.tcx.has_attr(self.body_id, sym::rustc_do_not_const_check) {
             return;
         }
 
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index 0c6226ce71e..74f27e85cba 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -126,6 +126,10 @@ pub(crate) struct FnCtxt<'a, 'tcx> {
     /// These are stored here so we may collect them when canonicalizing user
     /// type ascriptions later.
     pub(super) trait_ascriptions: RefCell<ItemLocalMap<Vec<ty::Clause<'tcx>>>>,
+
+    /// Whether the current crate enables the `rustc_attrs` feature.
+    /// This allows to skip processing attributes in many places.
+    pub(super) has_rustc_attrs: bool,
 }
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -154,6 +158,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             diverging_fallback_behavior,
             diverging_block_behavior,
             trait_ascriptions: Default::default(),
+            has_rustc_attrs: root_ctxt.tcx.features().rustc_attrs(),
         }
     }
 
@@ -525,10 +530,13 @@ fn parse_never_type_options_attr(
     let mut fallback = None;
     let mut block = None;
 
-    let items = tcx
-        .get_attr(CRATE_DEF_ID, sym::rustc_never_type_options)
-        .map(|attr| attr.meta_item_list().unwrap())
-        .unwrap_or_default();
+    let items = if tcx.features().rustc_attrs() {
+        tcx.get_attr(CRATE_DEF_ID, sym::rustc_never_type_options)
+            .map(|attr| attr.meta_item_list().unwrap())
+    } else {
+        None
+    };
+    let items = items.unwrap_or_default();
 
     for item in items {
         if item.has_name(sym::fallback) && fallback.is_none() {
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index ab4181f5293..129de32fd4a 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -46,14 +46,14 @@ use rustc_data_structures::unord::UnordSet;
 use rustc_errors::codes::*;
 use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err};
 use rustc_hir as hir;
-use rustc_hir::attrs::AttributeKind;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::{HirId, HirIdMap, Node, find_attr};
+use rustc_hir::{HirId, HirIdMap, Node};
 use rustc_hir_analysis::check::{check_abi, check_custom_abi};
 use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
 use rustc_infer::traits::{ObligationCauseCode, ObligationInspector, WellFormedLoc};
+use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::{bug, span_bug};
 use rustc_session::config;
 use rustc_span::Span;
@@ -174,7 +174,7 @@ fn typeck_with_inspect<'tcx>(
                 .map(|(idx, ty)| fcx.normalize(arg_span(idx), ty)),
         );
 
-        if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::Naked(..)) {
+        if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NAKED) {
             naked_functions::typeck_naked_fn(tcx, def_id, body);
         }
 
@@ -247,6 +247,13 @@ fn typeck_with_inspect<'tcx>(
 
     debug!(pending_obligations = ?fcx.fulfillment_cx.borrow().pending_obligations());
 
+    // We need to handle opaque types before emitting ambiguity errors as applying
+    // defining uses may guide type inference.
+    if fcx.next_trait_solver() {
+        fcx.handle_opaque_type_uses_next();
+    }
+
+    fcx.select_obligations_where_possible(|_| {});
     if let None = fcx.infcx.tainted_by_errors() {
         fcx.report_ambiguity_errors();
     }
@@ -255,21 +262,6 @@ fn typeck_with_inspect<'tcx>(
 
     let typeck_results = fcx.resolve_type_vars_in_body(body);
 
-    // Handle potentially region dependent goals, see `InferCtxt::in_hir_typeck`.
-    if let None = fcx.infcx.tainted_by_errors() {
-        for obligation in fcx.take_hir_typeck_potentially_region_dependent_goals() {
-            let obligation = fcx.resolve_vars_if_possible(obligation);
-            if obligation.has_non_region_infer() {
-                bug!("unexpected inference variable after writeback: {obligation:?}");
-            }
-            fcx.register_predicate(obligation);
-        }
-        fcx.select_obligations_where_possible(|_| {});
-        if let None = fcx.infcx.tainted_by_errors() {
-            fcx.report_ambiguity_errors();
-        }
-    }
-
     fcx.detect_opaque_types_added_during_writeback();
 
     // Consistency check our TypeckResults instance can hold all ItemLocalIds
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 3ca3b56b87e..bb4748b0565 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -777,31 +777,16 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
 
                 self.assemble_inherent_candidates_from_object(generalized_self_ty);
                 self.assemble_inherent_impl_candidates_for_type(p.def_id(), receiver_steps);
-                if self.tcx.has_attr(p.def_id(), sym::rustc_has_incoherent_inherent_impls) {
-                    self.assemble_inherent_candidates_for_incoherent_ty(
-                        raw_self_ty,
-                        receiver_steps,
-                    );
-                }
+                self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty, receiver_steps);
             }
             ty::Adt(def, _) => {
                 let def_id = def.did();
                 self.assemble_inherent_impl_candidates_for_type(def_id, receiver_steps);
-                if self.tcx.has_attr(def_id, sym::rustc_has_incoherent_inherent_impls) {
-                    self.assemble_inherent_candidates_for_incoherent_ty(
-                        raw_self_ty,
-                        receiver_steps,
-                    );
-                }
+                self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty, receiver_steps);
             }
             ty::Foreign(did) => {
                 self.assemble_inherent_impl_candidates_for_type(did, receiver_steps);
-                if self.tcx.has_attr(did, sym::rustc_has_incoherent_inherent_impls) {
-                    self.assemble_inherent_candidates_for_incoherent_ty(
-                        raw_self_ty,
-                        receiver_steps,
-                    );
-                }
+                self.assemble_inherent_candidates_for_incoherent_ty(raw_self_ty, receiver_steps);
             }
             ty::Param(_) => {
                 self.assemble_inherent_candidates_from_param(raw_self_ty);
@@ -909,6 +894,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         debug_assert_matches!(param_ty.kind(), ty::Param(_));
 
         let tcx = self.tcx;
+
+        // We use `DeepRejectCtxt` here which may return false positive on where clauses
+        // with alias self types. We need to later on reject these as inherent candidates
+        // in `consider_probe`.
         let bounds = self.param_env.caller_bounds().iter().filter_map(|predicate| {
             let bound_predicate = predicate.kind();
             match bound_predicate.skip_binder() {
@@ -1945,6 +1934,29 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     );
                     (xform_self_ty, xform_ret_ty) =
                         self.xform_self_ty(probe.item, trait_ref.self_ty(), trait_ref.args);
+
+                    if matches!(probe.kind, WhereClauseCandidate(_)) {
+                        // `WhereClauseCandidate` requires that the self type is a param,
+                        // because it has special behavior with candidate preference as an
+                        // inherent pick.
+                        match ocx.structurally_normalize_ty(
+                            cause,
+                            self.param_env,
+                            trait_ref.self_ty(),
+                        ) {
+                            Ok(ty) => {
+                                if !matches!(ty.kind(), ty::Param(_)) {
+                                    debug!("--> not a param ty: {xform_self_ty:?}");
+                                    return ProbeResult::NoMatch;
+                                }
+                            }
+                            Err(errors) => {
+                                debug!("--> cannot relate self-types {:?}", errors);
+                                return ProbeResult::NoMatch;
+                            }
+                        }
+                    }
+
                     xform_self_ty = ocx.normalize(cause, self.param_env, xform_self_ty);
                     match ocx.relate(cause, self.param_env, self.variance(), self_ty, xform_self_ty)
                     {
@@ -2373,17 +2385,14 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                         if !self.is_relevant_kind_for_mode(x.kind) {
                             return false;
                         }
-                        if self.matches_by_doc_alias(x.def_id) {
-                            return true;
-                        }
-                        match edit_distance_with_substrings(
+                        if let Some(d) = edit_distance_with_substrings(
                             name.as_str(),
                             x.name().as_str(),
                             max_dist,
                         ) {
-                            Some(d) => d > 0,
-                            None => false,
+                            return d > 0;
                         }
+                        self.matches_by_doc_alias(x.def_id)
                     })
                     .copied()
                     .collect()
diff --git a/compiler/rustc_hir_typeck/src/opaque_types.rs b/compiler/rustc_hir_typeck/src/opaque_types.rs
index e0224f8c6e1..97feac3d009 100644
--- a/compiler/rustc_hir_typeck/src/opaque_types.rs
+++ b/compiler/rustc_hir_typeck/src/opaque_types.rs
@@ -1,5 +1,218 @@
-use super::FnCtxt;
+use rustc_hir::def::DefKind;
+use rustc_infer::traits::ObligationCause;
+use rustc_middle::ty::{
+    self, DefiningScopeKind, EarlyBinder, OpaqueHiddenType, OpaqueTypeKey, TypeVisitableExt,
+    TypingMode,
+};
+use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
+use rustc_trait_selection::opaque_types::{
+    NonDefiningUseReason, opaque_type_has_defining_use_args, report_item_does_not_constrain_error,
+};
+use rustc_trait_selection::solve;
+use tracing::{debug, instrument};
+
+use crate::FnCtxt;
+
 impl<'tcx> FnCtxt<'_, 'tcx> {
+    /// This takes all the opaque type uses during HIR typeck. It first computes
+    /// the concrete hidden type by iterating over all defining uses.
+    ///
+    /// A use during HIR typeck is defining if all non-lifetime arguments are
+    /// unique generic parameters and the hidden type does not reference any
+    /// inference variables.
+    ///
+    /// It then uses these defining uses to guide inference for all other uses.
+    #[instrument(level = "debug", skip(self))]
+    pub(super) fn handle_opaque_type_uses_next(&mut self) {
+        // We clone the opaques instead of stealing them here as they are still used for
+        // normalization in the next generation trait solver.
+        let mut opaque_types: Vec<_> = self.infcx.clone_opaque_types();
+        let num_entries = self.inner.borrow_mut().opaque_types().num_entries();
+        let prev = self.checked_opaque_types_storage_entries.replace(Some(num_entries));
+        debug_assert_eq!(prev, None);
+        for entry in &mut opaque_types {
+            *entry = self.resolve_vars_if_possible(*entry);
+        }
+        debug!(?opaque_types);
+
+        self.compute_concrete_opaque_types(&opaque_types);
+        self.apply_computed_concrete_opaque_types(&opaque_types);
+    }
+}
+
+enum UsageKind<'tcx> {
+    None,
+    NonDefiningUse(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>),
+    UnconstrainedHiddenType(OpaqueHiddenType<'tcx>),
+    HasDefiningUse,
+}
+
+impl<'tcx> UsageKind<'tcx> {
+    fn merge(&mut self, other: UsageKind<'tcx>) {
+        match (&*self, &other) {
+            (UsageKind::HasDefiningUse, _) | (_, UsageKind::None) => unreachable!(),
+            (UsageKind::None, _) => *self = other,
+            // When mergining non-defining uses, prefer earlier ones. This means
+            // the error happens as early as possible.
+            (
+                UsageKind::NonDefiningUse(..) | UsageKind::UnconstrainedHiddenType(..),
+                UsageKind::NonDefiningUse(..),
+            ) => {}
+            // When merging unconstrained hidden types, we prefer later ones. This is
+            // used as in most cases, the defining use is the final return statement
+            // of our function, and other uses with defining arguments are likely not
+            // intended to be defining.
+            (
+                UsageKind::NonDefiningUse(..) | UsageKind::UnconstrainedHiddenType(..),
+                UsageKind::UnconstrainedHiddenType(..) | UsageKind::HasDefiningUse,
+            ) => *self = other,
+        }
+    }
+}
+
+impl<'tcx> FnCtxt<'_, 'tcx> {
+    fn compute_concrete_opaque_types(
+        &mut self,
+        opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)],
+    ) {
+        let tcx = self.tcx;
+        let TypingMode::Analysis { defining_opaque_types_and_generators } = self.typing_mode()
+        else {
+            unreachable!();
+        };
+
+        for def_id in defining_opaque_types_and_generators {
+            match tcx.def_kind(def_id) {
+                DefKind::OpaqueTy => {}
+                DefKind::Closure => continue,
+                _ => unreachable!("not opaque or generator: {def_id:?}"),
+            }
+
+            let mut usage_kind = UsageKind::None;
+            for &(opaque_type_key, hidden_type) in opaque_types {
+                if opaque_type_key.def_id != def_id {
+                    continue;
+                }
+
+                usage_kind.merge(self.consider_opaque_type_use(opaque_type_key, hidden_type));
+                if let UsageKind::HasDefiningUse = usage_kind {
+                    break;
+                }
+            }
+
+            let guar = match usage_kind {
+                UsageKind::None => {
+                    if let Some(guar) = self.tainted_by_errors() {
+                        guar
+                    } else {
+                        report_item_does_not_constrain_error(self.tcx, self.body_id, def_id, None)
+                    }
+                }
+                UsageKind::NonDefiningUse(opaque_type_key, hidden_type) => {
+                    report_item_does_not_constrain_error(
+                        self.tcx,
+                        self.body_id,
+                        def_id,
+                        Some((opaque_type_key, hidden_type.span)),
+                    )
+                }
+                UsageKind::UnconstrainedHiddenType(hidden_type) => {
+                    let infer_var = hidden_type
+                        .ty
+                        .walk()
+                        .filter_map(ty::GenericArg::as_term)
+                        .find(|term| term.is_infer())
+                        .unwrap_or_else(|| hidden_type.ty.into());
+                    self.err_ctxt()
+                        .emit_inference_failure_err(
+                            self.body_id,
+                            hidden_type.span,
+                            infer_var,
+                            TypeAnnotationNeeded::E0282,
+                            false,
+                        )
+                        .emit()
+                }
+                UsageKind::HasDefiningUse => continue,
+            };
+
+            self.typeck_results
+                .borrow_mut()
+                .concrete_opaque_types
+                .insert(def_id, OpaqueHiddenType::new_error(tcx, guar));
+            self.set_tainted_by_errors(guar);
+        }
+    }
+
+    fn consider_opaque_type_use(
+        &mut self,
+        opaque_type_key: OpaqueTypeKey<'tcx>,
+        hidden_type: OpaqueHiddenType<'tcx>,
+    ) -> UsageKind<'tcx> {
+        if let Err(err) = opaque_type_has_defining_use_args(
+            &self,
+            opaque_type_key,
+            hidden_type.span,
+            DefiningScopeKind::HirTypeck,
+        ) {
+            match err {
+                NonDefiningUseReason::Tainted(guar) => {
+                    self.typeck_results.borrow_mut().concrete_opaque_types.insert(
+                        opaque_type_key.def_id,
+                        OpaqueHiddenType::new_error(self.tcx, guar),
+                    );
+                    return UsageKind::HasDefiningUse;
+                }
+                _ => return UsageKind::NonDefiningUse(opaque_type_key, hidden_type),
+            };
+        }
+
+        // We ignore uses of the opaque if they have any inference variables
+        // as this can frequently happen with recursive calls.
+        //
+        // See `tests/ui/traits/next-solver/opaques/universal-args-non-defining.rs`.
+        if hidden_type.ty.has_non_region_infer() {
+            return UsageKind::UnconstrainedHiddenType(hidden_type);
+        }
+
+        let cause = ObligationCause::misc(hidden_type.span, self.body_id);
+        let at = self.at(&cause, self.param_env);
+        let hidden_type = match solve::deeply_normalize(at, hidden_type) {
+            Ok(hidden_type) => hidden_type,
+            Err(errors) => {
+                let guar = self.err_ctxt().report_fulfillment_errors(errors);
+                OpaqueHiddenType::new_error(self.tcx, guar)
+            }
+        };
+        let hidden_type = hidden_type.remap_generic_params_to_declaration_params(
+            opaque_type_key,
+            self.tcx,
+            DefiningScopeKind::HirTypeck,
+        );
+
+        let prev = self
+            .typeck_results
+            .borrow_mut()
+            .concrete_opaque_types
+            .insert(opaque_type_key.def_id, hidden_type);
+        assert!(prev.is_none());
+        UsageKind::HasDefiningUse
+    }
+
+    fn apply_computed_concrete_opaque_types(
+        &mut self,
+        opaque_types: &[(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)],
+    ) {
+        let tcx = self.tcx;
+        for &(key, hidden_type) in opaque_types {
+            let expected =
+                *self.typeck_results.borrow_mut().concrete_opaque_types.get(&key.def_id).unwrap();
+
+            let expected = EarlyBinder::bind(expected.ty).instantiate(tcx, key.args);
+            self.demand_eqtype(hidden_type.span, expected, hidden_type.ty);
+        }
+    }
+
     /// We may in theory add further uses of an opaque after cloning the opaque
     /// types storage during writeback when computing the defining uses.
     ///
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index 50fa3f2cc9d..06acff06a51 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -1747,7 +1747,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     fn should_log_capture_analysis(&self, closure_def_id: LocalDefId) -> bool {
-        self.tcx.has_attr(closure_def_id, sym::rustc_capture_analysis)
+        self.has_rustc_attrs && self.tcx.has_attr(closure_def_id, sym::rustc_capture_analysis)
     }
 
     fn log_capture_analysis_first_pass(
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index 42736a07b2a..d75bc9edab2 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -27,7 +27,7 @@ use rustc_middle::ty::{
 };
 use rustc_span::{Span, sym};
 use rustc_trait_selection::error_reporting::infer::need_type_info::TypeAnnotationNeeded;
-use rustc_trait_selection::opaque_types::check_opaque_type_parameter_valid;
+use rustc_trait_selection::opaque_types::opaque_type_has_defining_use_args;
 use rustc_trait_selection::solve;
 use tracing::{debug, instrument};
 
@@ -45,7 +45,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // This attribute causes us to dump some writeback information
         // in the form of errors, which is used for unit tests.
-        let rustc_dump_user_args = self.tcx.has_attr(item_def_id, sym::rustc_dump_user_args);
+        let rustc_dump_user_args =
+            self.has_rustc_attrs && self.tcx.has_attr(item_def_id, sym::rustc_dump_user_args);
 
         let mut wbcx = WritebackCx::new(self, body, rustc_dump_user_args);
         for param in body.params {
@@ -76,6 +77,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         wbcx.visit_coroutine_interior();
         wbcx.visit_transmutes();
         wbcx.visit_offset_of_container_types();
+        wbcx.visit_potentially_region_dependent_goals();
 
         wbcx.typeck_results.rvalue_scopes =
             mem::take(&mut self.typeck_results.borrow_mut().rvalue_scopes);
@@ -545,8 +547,24 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         }
     }
 
+    fn visit_opaque_types_next(&mut self) {
+        let mut fcx_typeck_results = self.fcx.typeck_results.borrow_mut();
+        assert_eq!(fcx_typeck_results.hir_owner, self.typeck_results.hir_owner);
+        for hidden_ty in fcx_typeck_results.concrete_opaque_types.values() {
+            assert!(!hidden_ty.has_infer());
+        }
+
+        assert_eq!(self.typeck_results.concrete_opaque_types.len(), 0);
+        self.typeck_results.concrete_opaque_types =
+            mem::take(&mut fcx_typeck_results.concrete_opaque_types);
+    }
+
     #[instrument(skip(self), level = "debug")]
     fn visit_opaque_types(&mut self) {
+        if self.fcx.next_trait_solver() {
+            return self.visit_opaque_types_next();
+        }
+
         let tcx = self.tcx();
         // We clone the opaques instead of stealing them here as they are still used for
         // normalization in the next generation trait solver.
@@ -557,17 +575,14 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         for (opaque_type_key, hidden_type) in opaque_types {
             let hidden_type = self.resolve(hidden_type, &hidden_type.span);
             let opaque_type_key = self.resolve(opaque_type_key, &hidden_type.span);
-
-            if !self.fcx.next_trait_solver() {
-                if let ty::Alias(ty::Opaque, alias_ty) = hidden_type.ty.kind()
-                    && alias_ty.def_id == opaque_type_key.def_id.to_def_id()
-                    && alias_ty.args == opaque_type_key.args
-                {
-                    continue;
-                }
+            if let ty::Alias(ty::Opaque, alias_ty) = hidden_type.ty.kind()
+                && alias_ty.def_id == opaque_type_key.def_id.to_def_id()
+                && alias_ty.args == opaque_type_key.args
+            {
+                continue;
             }
 
-            if let Err(err) = check_opaque_type_parameter_valid(
+            if let Err(err) = opaque_type_has_defining_use_args(
                 &self.fcx,
                 opaque_type_key,
                 hidden_type.span,
@@ -775,6 +790,32 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         }
     }
 
+    fn visit_potentially_region_dependent_goals(&mut self) {
+        let obligations = self.fcx.take_hir_typeck_potentially_region_dependent_goals();
+        if let None = self.fcx.tainted_by_errors() {
+            for obligation in obligations {
+                let (predicate, mut cause) =
+                    self.fcx.resolve_vars_if_possible((obligation.predicate, obligation.cause));
+                if predicate.has_non_region_infer() {
+                    self.fcx.dcx().span_delayed_bug(
+                        cause.span,
+                        format!("unexpected inference variable after writeback: {predicate:?}"),
+                    );
+                } else {
+                    let predicate = self.tcx().erase_regions(predicate);
+                    if cause.has_infer() || cause.has_placeholders() {
+                        // We can't use the the obligation cause as it references
+                        // information local to this query.
+                        cause = self.fcx.misc(cause.span);
+                    }
+                    self.typeck_results
+                        .potentially_region_dependent_goals
+                        .insert((predicate, cause));
+                }
+            }
+        }
+    }
+
     fn resolve<T>(&mut self, value: T, span: &dyn Locatable) -> T
     where
         T: TypeFoldable<TyCtxt<'tcx>>,
@@ -896,6 +937,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
         }
     }
 
+    #[instrument(level = "debug", skip(self, outer_exclusive_binder, new_err))]
     fn handle_term<T>(
         &mut self,
         value: T,
diff --git a/compiler/rustc_incremental/Cargo.toml b/compiler/rustc_incremental/Cargo.toml
index db0a5841887..8d7f2eb8414 100644
--- a/compiler/rustc_incremental/Cargo.toml
+++ b/compiler/rustc_incremental/Cargo.toml
@@ -19,6 +19,6 @@ rustc_middle = { path = "../rustc_middle" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
-thin-vec = "0.2.12"
-tracing = "0.1"
+thin-vec.workspace = true
+tracing.workspace = true
 # tidy-alphabetical-end
diff --git a/compiler/rustc_index/src/bit_set.rs b/compiler/rustc_index/src/bit_set.rs
index 645d95b1dba..684bd34f909 100644
--- a/compiler/rustc_index/src/bit_set.rs
+++ b/compiler/rustc_index/src/bit_set.rs
@@ -491,19 +491,15 @@ pub struct ChunkedBitSet<T> {
     marker: PhantomData<T>,
 }
 
-// Note: the chunk domain size is duplicated in each variant. This is a bit
-// inconvenient, but it allows the type size to be smaller than if we had an
-// outer struct containing a chunk domain size plus the `Chunk`, because the
-// compiler can place the chunk domain size after the tag.
+// NOTE: The chunk size is computed on-the-fly on each manipulation of a chunk.
+// This avoids storing it, as it's almost always CHUNK_BITS except for the last one.
 #[derive(Clone, Debug, PartialEq, Eq)]
 enum Chunk {
     /// A chunk that is all zeros; we don't represent the zeros explicitly.
-    /// The `ChunkSize` is always non-zero.
-    Zeros(ChunkSize),
+    Zeros,
 
     /// A chunk that is all ones; we don't represent the ones explicitly.
-    /// `ChunkSize` is always non-zero.
-    Ones(ChunkSize),
+    Ones,
 
     /// A chunk that has a mix of zeros and ones, which are represented
     /// explicitly and densely. It never has all zeros or all ones.
@@ -514,16 +510,14 @@ enum Chunk {
     /// to store the length, which would make this type larger. These excess
     /// words are always zero, as are any excess bits in the final in-use word.
     ///
-    /// The first `ChunkSize` field is always non-zero.
-    ///
-    /// The second `ChunkSize` field is the count of 1s set in the chunk, and
+    /// The `ChunkSize` field is the count of 1s set in the chunk, and
     /// must satisfy `0 < count < chunk_domain_size`.
     ///
     /// The words are within an `Rc` because it's surprisingly common to
     /// duplicate an entire chunk, e.g. in `ChunkedBitSet::clone_from()`, or
     /// when a `Mixed` chunk is union'd into a `Zeros` chunk. When we do need
     /// to modify a chunk we use `Rc::make_mut`.
-    Mixed(ChunkSize, ChunkSize, Rc<[Word; CHUNK_WORDS]>),
+    Mixed(ChunkSize, Rc<[Word; CHUNK_WORDS]>),
 }
 
 // This type is used a lot. Make sure it doesn't unintentionally get bigger.
@@ -535,6 +529,22 @@ impl<T> ChunkedBitSet<T> {
         self.domain_size
     }
 
+    #[inline]
+    fn last_chunk_size(&self) -> ChunkSize {
+        let n = self.domain_size % CHUNK_BITS;
+        if n == 0 { CHUNK_BITS as ChunkSize } else { n as ChunkSize }
+    }
+
+    /// All the chunks have a chunk_domain_size of `CHUNK_BITS` except the final one.
+    #[inline]
+    fn chunk_domain_size(&self, chunk: usize) -> ChunkSize {
+        if chunk == self.chunks.len() - 1 {
+            self.last_chunk_size()
+        } else {
+            CHUNK_BITS as ChunkSize
+        }
+    }
+
     #[cfg(test)]
     fn assert_valid(&self) {
         if self.domain_size == 0 {
@@ -544,8 +554,9 @@ impl<T> ChunkedBitSet<T> {
 
         assert!((self.chunks.len() - 1) * CHUNK_BITS <= self.domain_size);
         assert!(self.chunks.len() * CHUNK_BITS >= self.domain_size);
-        for chunk in self.chunks.iter() {
-            chunk.assert_valid();
+        for (chunk_index, chunk) in self.chunks.iter().enumerate() {
+            let chunk_domain_size = self.chunk_domain_size(chunk_index);
+            chunk.assert_valid(chunk_domain_size);
         }
     }
 }
@@ -556,16 +567,7 @@ impl<T: Idx> ChunkedBitSet<T> {
         let chunks = if domain_size == 0 {
             Box::new([])
         } else {
-            // All the chunks have a chunk_domain_size of `CHUNK_BITS` except
-            // the final one.
-            let final_chunk_domain_size = {
-                let n = domain_size % CHUNK_BITS;
-                if n == 0 { CHUNK_BITS } else { n }
-            };
-            let mut chunks =
-                vec![Chunk::new(CHUNK_BITS, is_empty); num_chunks(domain_size)].into_boxed_slice();
-            *chunks.last_mut().unwrap() = Chunk::new(final_chunk_domain_size, is_empty);
-            chunks
+            vec![if is_empty { Zeros } else { Ones }; num_chunks(domain_size)].into_boxed_slice()
         };
         ChunkedBitSet { domain_size, chunks, marker: PhantomData }
     }
@@ -594,11 +596,15 @@ impl<T: Idx> ChunkedBitSet<T> {
 
     /// Count the number of bits in the set.
     pub fn count(&self) -> usize {
-        self.chunks.iter().map(|chunk| chunk.count()).sum()
+        self.chunks
+            .iter()
+            .enumerate()
+            .map(|(index, chunk)| chunk.count(self.chunk_domain_size(index)))
+            .sum()
     }
 
     pub fn is_empty(&self) -> bool {
-        self.chunks.iter().all(|chunk| matches!(chunk, Zeros(..)))
+        self.chunks.iter().all(|chunk| matches!(chunk, Zeros))
     }
 
     /// Returns `true` if `self` contains `elem`.
@@ -607,9 +613,9 @@ impl<T: Idx> ChunkedBitSet<T> {
         assert!(elem.index() < self.domain_size);
         let chunk = &self.chunks[chunk_index(elem)];
         match &chunk {
-            Zeros(_) => false,
-            Ones(_) => true,
-            Mixed(_, _, words) => {
+            Zeros => false,
+            Ones => true,
+            Mixed(_, words) => {
                 let (word_index, mask) = chunk_word_index_and_mask(elem);
                 (words[word_index] & mask) != 0
             }
@@ -625,9 +631,10 @@ impl<T: Idx> ChunkedBitSet<T> {
     pub fn insert(&mut self, elem: T) -> bool {
         assert!(elem.index() < self.domain_size);
         let chunk_index = chunk_index(elem);
+        let chunk_domain_size = self.chunk_domain_size(chunk_index);
         let chunk = &mut self.chunks[chunk_index];
         match *chunk {
-            Zeros(chunk_domain_size) => {
+            Zeros => {
                 if chunk_domain_size > 1 {
                     #[cfg(feature = "nightly")]
                     let mut words = {
@@ -649,14 +656,14 @@ impl<T: Idx> ChunkedBitSet<T> {
 
                     let (word_index, mask) = chunk_word_index_and_mask(elem);
                     words_ref[word_index] |= mask;
-                    *chunk = Mixed(chunk_domain_size, 1, words);
+                    *chunk = Mixed(1, words);
                 } else {
-                    *chunk = Ones(chunk_domain_size);
+                    *chunk = Ones;
                 }
                 true
             }
-            Ones(_) => false,
-            Mixed(chunk_domain_size, ref mut count, ref mut words) => {
+            Ones => false,
+            Mixed(ref mut count, ref mut words) => {
                 // We skip all the work if the bit is already set.
                 let (word_index, mask) = chunk_word_index_and_mask(elem);
                 if (words[word_index] & mask) == 0 {
@@ -665,7 +672,7 @@ impl<T: Idx> ChunkedBitSet<T> {
                         let words = Rc::make_mut(words);
                         words[word_index] |= mask;
                     } else {
-                        *chunk = Ones(chunk_domain_size);
+                        *chunk = Ones;
                     }
                     true
                 } else {
@@ -678,11 +685,7 @@ impl<T: Idx> ChunkedBitSet<T> {
     /// Sets all bits to true.
     pub fn insert_all(&mut self) {
         for chunk in self.chunks.iter_mut() {
-            *chunk = match *chunk {
-                Zeros(chunk_domain_size)
-                | Ones(chunk_domain_size)
-                | Mixed(chunk_domain_size, ..) => Ones(chunk_domain_size),
-            }
+            *chunk = Ones;
         }
     }
 
@@ -690,10 +693,11 @@ impl<T: Idx> ChunkedBitSet<T> {
     pub fn remove(&mut self, elem: T) -> bool {
         assert!(elem.index() < self.domain_size);
         let chunk_index = chunk_index(elem);
+        let chunk_domain_size = self.chunk_domain_size(chunk_index);
         let chunk = &mut self.chunks[chunk_index];
         match *chunk {
-            Zeros(_) => false,
-            Ones(chunk_domain_size) => {
+            Zeros => false,
+            Ones => {
                 if chunk_domain_size > 1 {
                     #[cfg(feature = "nightly")]
                     let mut words = {
@@ -722,13 +726,13 @@ impl<T: Idx> ChunkedBitSet<T> {
                     );
                     let (word_index, mask) = chunk_word_index_and_mask(elem);
                     words_ref[word_index] &= !mask;
-                    *chunk = Mixed(chunk_domain_size, chunk_domain_size - 1, words);
+                    *chunk = Mixed(chunk_domain_size - 1, words);
                 } else {
-                    *chunk = Zeros(chunk_domain_size);
+                    *chunk = Zeros;
                 }
                 true
             }
-            Mixed(chunk_domain_size, ref mut count, ref mut words) => {
+            Mixed(ref mut count, ref mut words) => {
                 // We skip all the work if the bit is already clear.
                 let (word_index, mask) = chunk_word_index_and_mask(elem);
                 if (words[word_index] & mask) != 0 {
@@ -737,7 +741,7 @@ impl<T: Idx> ChunkedBitSet<T> {
                         let words = Rc::make_mut(words);
                         words[word_index] &= !mask;
                     } else {
-                        *chunk = Zeros(chunk_domain_size);
+                        *chunk = Zeros
                     }
                     true
                 } else {
@@ -748,11 +752,12 @@ impl<T: Idx> ChunkedBitSet<T> {
     }
 
     fn chunk_iter(&self, chunk_index: usize) -> ChunkIter<'_> {
+        let chunk_domain_size = self.chunk_domain_size(chunk_index);
         match self.chunks.get(chunk_index) {
-            Some(Zeros(_chunk_domain_size)) => ChunkIter::Zeros,
-            Some(Ones(chunk_domain_size)) => ChunkIter::Ones(0..*chunk_domain_size as usize),
-            Some(Mixed(chunk_domain_size, _, words)) => {
-                let num_words = num_words(*chunk_domain_size as usize);
+            Some(Zeros) => ChunkIter::Zeros,
+            Some(Ones) => ChunkIter::Ones(0..chunk_domain_size as usize),
+            Some(Mixed(_, words)) => {
+                let num_words = num_words(chunk_domain_size as usize);
                 ChunkIter::Mixed(BitIter::new(&words[0..num_words]))
             }
             None => ChunkIter::Finished,
@@ -765,23 +770,33 @@ impl<T: Idx> ChunkedBitSet<T> {
 impl<T: Idx> BitRelations<ChunkedBitSet<T>> for ChunkedBitSet<T> {
     fn union(&mut self, other: &ChunkedBitSet<T>) -> bool {
         assert_eq!(self.domain_size, other.domain_size);
-        debug_assert_eq!(self.chunks.len(), other.chunks.len());
+
+        let num_chunks = self.chunks.len();
+        debug_assert_eq!(num_chunks, other.chunks.len());
+
+        let last_chunk_size = self.last_chunk_size();
+        debug_assert_eq!(last_chunk_size, other.last_chunk_size());
 
         let mut changed = false;
-        for (mut self_chunk, other_chunk) in self.chunks.iter_mut().zip(other.chunks.iter()) {
+        for (chunk_index, (mut self_chunk, other_chunk)) in
+            self.chunks.iter_mut().zip(other.chunks.iter()).enumerate()
+        {
+            let chunk_domain_size = if chunk_index + 1 == num_chunks {
+                last_chunk_size
+            } else {
+                CHUNK_BITS as ChunkSize
+            };
+
             match (&mut self_chunk, &other_chunk) {
-                (_, Zeros(_)) | (Ones(_), _) => {}
-                (Zeros(self_chunk_domain_size), Ones(other_chunk_domain_size))
-                | (Mixed(self_chunk_domain_size, ..), Ones(other_chunk_domain_size))
-                | (Zeros(self_chunk_domain_size), Mixed(other_chunk_domain_size, ..)) => {
+                (_, Zeros) | (Ones, _) => {}
+                (Zeros, Ones) | (Mixed(..), Ones) | (Zeros, Mixed(..)) => {
                     // `other_chunk` fully overwrites `self_chunk`
-                    debug_assert_eq!(self_chunk_domain_size, other_chunk_domain_size);
                     *self_chunk = other_chunk.clone();
                     changed = true;
                 }
                 (
-                    Mixed(self_chunk_domain_size, self_chunk_count, self_chunk_words),
-                    Mixed(_other_chunk_domain_size, _other_chunk_count, other_chunk_words),
+                    Mixed(self_chunk_count, self_chunk_words),
+                    Mixed(_other_chunk_count, other_chunk_words),
                 ) => {
                     // First check if the operation would change
                     // `self_chunk.words`. If not, we can avoid allocating some
@@ -789,7 +804,7 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for ChunkedBitSet<T> {
                     // performance win. Also, we only need to operate on the
                     // in-use words, hence the slicing.
                     let op = |a, b| a | b;
-                    let num_words = num_words(*self_chunk_domain_size as usize);
+                    let num_words = num_words(chunk_domain_size as usize);
                     if bitwise_changes(
                         &self_chunk_words[0..num_words],
                         &other_chunk_words[0..num_words],
@@ -806,8 +821,8 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for ChunkedBitSet<T> {
                             .iter()
                             .map(|w| w.count_ones() as ChunkSize)
                             .sum();
-                        if *self_chunk_count == *self_chunk_domain_size {
-                            *self_chunk = Ones(*self_chunk_domain_size);
+                        if *self_chunk_count == chunk_domain_size {
+                            *self_chunk = Ones;
                         }
                         changed = true;
                     }
@@ -819,36 +834,41 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for ChunkedBitSet<T> {
 
     fn subtract(&mut self, other: &ChunkedBitSet<T>) -> bool {
         assert_eq!(self.domain_size, other.domain_size);
-        debug_assert_eq!(self.chunks.len(), other.chunks.len());
+
+        let num_chunks = self.chunks.len();
+        debug_assert_eq!(num_chunks, other.chunks.len());
+
+        let last_chunk_size = self.last_chunk_size();
+        debug_assert_eq!(last_chunk_size, other.last_chunk_size());
 
         let mut changed = false;
-        for (mut self_chunk, other_chunk) in self.chunks.iter_mut().zip(other.chunks.iter()) {
+        for (chunk_index, (mut self_chunk, other_chunk)) in
+            self.chunks.iter_mut().zip(other.chunks.iter()).enumerate()
+        {
+            let chunk_domain_size = if chunk_index + 1 == num_chunks {
+                last_chunk_size
+            } else {
+                CHUNK_BITS as ChunkSize
+            };
+
             match (&mut self_chunk, &other_chunk) {
-                (Zeros(..), _) | (_, Zeros(..)) => {}
-                (
-                    Ones(self_chunk_domain_size) | Mixed(self_chunk_domain_size, _, _),
-                    Ones(other_chunk_domain_size),
-                ) => {
-                    debug_assert_eq!(self_chunk_domain_size, other_chunk_domain_size);
+                (Zeros, _) | (_, Zeros) => {}
+                (Ones | Mixed(_, _), Ones) => {
                     changed = true;
-                    *self_chunk = Zeros(*self_chunk_domain_size);
+                    *self_chunk = Zeros;
                 }
-                (
-                    Ones(self_chunk_domain_size),
-                    Mixed(other_chunk_domain_size, other_chunk_count, other_chunk_words),
-                ) => {
-                    debug_assert_eq!(self_chunk_domain_size, other_chunk_domain_size);
+                (Ones, Mixed(other_chunk_count, other_chunk_words)) => {
                     changed = true;
-                    let num_words = num_words(*self_chunk_domain_size as usize);
+                    let num_words = num_words(chunk_domain_size as usize);
                     debug_assert!(num_words > 0 && num_words <= CHUNK_WORDS);
                     let mut tail_mask =
-                        1 << (*other_chunk_domain_size - ((num_words - 1) * WORD_BITS) as u16) - 1;
+                        1 << (chunk_domain_size - ((num_words - 1) * WORD_BITS) as u16) - 1;
                     let mut self_chunk_words = **other_chunk_words;
                     for word in self_chunk_words[0..num_words].iter_mut().rev() {
                         *word = !*word & tail_mask;
                         tail_mask = u64::MAX;
                     }
-                    let self_chunk_count = *self_chunk_domain_size - *other_chunk_count;
+                    let self_chunk_count = chunk_domain_size - *other_chunk_count;
                     debug_assert_eq!(
                         self_chunk_count,
                         self_chunk_words[0..num_words]
@@ -856,16 +876,15 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for ChunkedBitSet<T> {
                             .map(|w| w.count_ones() as ChunkSize)
                             .sum()
                     );
-                    *self_chunk =
-                        Mixed(*self_chunk_domain_size, self_chunk_count, Rc::new(self_chunk_words));
+                    *self_chunk = Mixed(self_chunk_count, Rc::new(self_chunk_words));
                 }
                 (
-                    Mixed(self_chunk_domain_size, self_chunk_count, self_chunk_words),
-                    Mixed(_other_chunk_domain_size, _other_chunk_count, other_chunk_words),
+                    Mixed(self_chunk_count, self_chunk_words),
+                    Mixed(_other_chunk_count, other_chunk_words),
                 ) => {
                     // See [`<Self as BitRelations<ChunkedBitSet<T>>>::union`] for the explanation
                     let op = |a: u64, b: u64| a & !b;
-                    let num_words = num_words(*self_chunk_domain_size as usize);
+                    let num_words = num_words(chunk_domain_size as usize);
                     if bitwise_changes(
                         &self_chunk_words[0..num_words],
                         &other_chunk_words[0..num_words],
@@ -883,7 +902,7 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for ChunkedBitSet<T> {
                             .map(|w| w.count_ones() as ChunkSize)
                             .sum();
                         if *self_chunk_count == 0 {
-                            *self_chunk = Zeros(*self_chunk_domain_size);
+                            *self_chunk = Zeros;
                         }
                         changed = true;
                     }
@@ -895,28 +914,36 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for ChunkedBitSet<T> {
 
     fn intersect(&mut self, other: &ChunkedBitSet<T>) -> bool {
         assert_eq!(self.domain_size, other.domain_size);
-        debug_assert_eq!(self.chunks.len(), other.chunks.len());
+
+        let num_chunks = self.chunks.len();
+        debug_assert_eq!(num_chunks, other.chunks.len());
+
+        let last_chunk_size = self.last_chunk_size();
+        debug_assert_eq!(last_chunk_size, other.last_chunk_size());
 
         let mut changed = false;
-        for (mut self_chunk, other_chunk) in self.chunks.iter_mut().zip(other.chunks.iter()) {
+        for (chunk_index, (mut self_chunk, other_chunk)) in
+            self.chunks.iter_mut().zip(other.chunks.iter()).enumerate()
+        {
+            let chunk_domain_size = if chunk_index + 1 == num_chunks {
+                last_chunk_size
+            } else {
+                CHUNK_BITS as ChunkSize
+            };
+
             match (&mut self_chunk, &other_chunk) {
-                (Zeros(..), _) | (_, Ones(..)) => {}
-                (
-                    Ones(self_chunk_domain_size),
-                    Zeros(other_chunk_domain_size) | Mixed(other_chunk_domain_size, ..),
-                )
-                | (Mixed(self_chunk_domain_size, ..), Zeros(other_chunk_domain_size)) => {
-                    debug_assert_eq!(self_chunk_domain_size, other_chunk_domain_size);
+                (Zeros, _) | (_, Ones) => {}
+                (Ones, Zeros | Mixed(..)) | (Mixed(..), Zeros) => {
                     changed = true;
                     *self_chunk = other_chunk.clone();
                 }
                 (
-                    Mixed(self_chunk_domain_size, self_chunk_count, self_chunk_words),
-                    Mixed(_other_chunk_domain_size, _other_chunk_count, other_chunk_words),
+                    Mixed(self_chunk_count, self_chunk_words),
+                    Mixed(_other_chunk_count, other_chunk_words),
                 ) => {
                     // See [`<Self as BitRelations<ChunkedBitSet<T>>>::union`] for the explanation
                     let op = |a, b| a & b;
-                    let num_words = num_words(*self_chunk_domain_size as usize);
+                    let num_words = num_words(chunk_domain_size as usize);
                     if bitwise_changes(
                         &self_chunk_words[0..num_words],
                         &other_chunk_words[0..num_words],
@@ -934,7 +961,7 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for ChunkedBitSet<T> {
                             .map(|w| w.count_ones() as ChunkSize)
                             .sum();
                         if *self_chunk_count == 0 {
-                            *self_chunk = Zeros(*self_chunk_domain_size);
+                            *self_chunk = Zeros;
                         }
                         changed = true;
                     }
@@ -964,7 +991,7 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for DenseBitSet<T> {
                 words = &mut words[..CHUNK_WORDS];
             }
             match chunk {
-                Zeros(..) => {
+                Zeros => {
                     for word in words {
                         if *word != 0 {
                             changed = true;
@@ -972,8 +999,8 @@ impl<T: Idx> BitRelations<ChunkedBitSet<T>> for DenseBitSet<T> {
                         }
                     }
                 }
-                Ones(..) => (),
-                Mixed(_, _, data) => {
+                Ones => (),
+                Mixed(_, data) => {
                     for (i, word) in words.iter_mut().enumerate() {
                         let new_val = *word & data[i];
                         if new_val != *word {
@@ -1053,13 +1080,11 @@ impl<'a, T: Idx> Iterator for ChunkedBitIter<'a, T> {
 
 impl Chunk {
     #[cfg(test)]
-    fn assert_valid(&self) {
+    fn assert_valid(&self, chunk_domain_size: ChunkSize) {
+        assert!(chunk_domain_size as usize <= CHUNK_BITS);
         match *self {
-            Zeros(chunk_domain_size) | Ones(chunk_domain_size) => {
-                assert!(chunk_domain_size as usize <= CHUNK_BITS);
-            }
-            Mixed(chunk_domain_size, count, ref words) => {
-                assert!(chunk_domain_size as usize <= CHUNK_BITS);
+            Zeros | Ones => {}
+            Mixed(count, ref words) => {
                 assert!(0 < count && count < chunk_domain_size);
 
                 // Check the number of set bits matches `count`.
@@ -1083,18 +1108,12 @@ impl Chunk {
         }
     }
 
-    fn new(chunk_domain_size: usize, is_empty: bool) -> Self {
-        debug_assert!(0 < chunk_domain_size && chunk_domain_size <= CHUNK_BITS);
-        let chunk_domain_size = chunk_domain_size as ChunkSize;
-        if is_empty { Zeros(chunk_domain_size) } else { Ones(chunk_domain_size) }
-    }
-
     /// Count the number of 1s in the chunk.
-    fn count(&self) -> usize {
+    fn count(&self, chunk_domain_size: ChunkSize) -> usize {
         match *self {
-            Zeros(_) => 0,
-            Ones(chunk_domain_size) => chunk_domain_size as usize,
-            Mixed(_, count, _) => count as usize,
+            Zeros => 0,
+            Ones => chunk_domain_size as usize,
+            Mixed(count, _) => count as usize,
         }
     }
 }
diff --git a/compiler/rustc_index/src/bit_set/tests.rs b/compiler/rustc_index/src/bit_set/tests.rs
index 9ce4cf4293f..deddc872614 100644
--- a/compiler/rustc_index/src/bit_set/tests.rs
+++ b/compiler/rustc_index/src/bit_set/tests.rs
@@ -120,8 +120,9 @@ fn chunked_bitset() {
     let mut b1 = ChunkedBitSet::<usize>::new_empty(1);
     assert_eq!(
         b1,
-        ChunkedBitSet { domain_size: 1, chunks: Box::new([Zeros(1)]), marker: PhantomData }
+        ChunkedBitSet { domain_size: 1, chunks: Box::new([Zeros]), marker: PhantomData }
     );
+    assert_eq!(b1.chunk_domain_size(0), 1);
 
     b1.assert_valid();
     assert!(!b1.contains(0));
@@ -129,12 +130,12 @@ fn chunked_bitset() {
     assert!(b1.insert(0));
     assert!(b1.contains(0));
     assert_eq!(b1.count(), 1);
-    assert_eq!(b1.chunks(), [Ones(1)]);
+    assert_eq!(b1.chunks(), [Ones]);
     assert!(!b1.insert(0));
     assert!(b1.remove(0));
     assert!(!b1.contains(0));
     assert_eq!(b1.count(), 0);
-    assert_eq!(b1.chunks(), [Zeros(1)]);
+    assert_eq!(b1.chunks(), [Zeros]);
     b1.assert_valid();
 
     //-----------------------------------------------------------------------
@@ -142,8 +143,9 @@ fn chunked_bitset() {
     let mut b100 = ChunkedBitSet::<usize>::new_filled(100);
     assert_eq!(
         b100,
-        ChunkedBitSet { domain_size: 100, chunks: Box::new([Ones(100)]), marker: PhantomData }
+        ChunkedBitSet { domain_size: 100, chunks: Box::new([Ones]), marker: PhantomData }
     );
+    assert_eq!(b100.chunk_domain_size(0), 100);
 
     b100.assert_valid();
     for i in 0..100 {
@@ -152,7 +154,7 @@ fn chunked_bitset() {
     assert_eq!(b100.count(), 100);
     assert!(b100.remove(3));
     assert!(b100.insert(3));
-    assert_eq!(b100.chunks(), vec![Ones(100)]);
+    assert_eq!(b100.chunks(), vec![Ones]);
     assert!(
         b100.remove(20) && b100.remove(30) && b100.remove(40) && b100.remove(99) && b100.insert(30)
     );
@@ -161,7 +163,6 @@ fn chunked_bitset() {
     assert_eq!(
         b100.chunks(),
         vec![Mixed(
-            100,
             97,
             #[rustfmt::skip]
             Rc::new([
@@ -180,7 +181,7 @@ fn chunked_bitset() {
         }
     }
     assert_eq!(num_removed, 97);
-    assert_eq!(b100.chunks(), vec![Zeros(100)]);
+    assert_eq!(b100.chunks(), vec![Zeros]);
     b100.assert_valid();
 
     //-----------------------------------------------------------------------
@@ -188,23 +189,21 @@ fn chunked_bitset() {
     let mut b2548 = ChunkedBitSet::<usize>::new_empty(2548);
     assert_eq!(
         b2548,
-        ChunkedBitSet {
-            domain_size: 2548,
-            chunks: Box::new([Zeros(2048), Zeros(500)]),
-            marker: PhantomData,
-        }
+        ChunkedBitSet { domain_size: 2548, chunks: Box::new([Zeros, Zeros]), marker: PhantomData }
     );
+    assert_eq!(b2548.chunk_domain_size(0), 2048);
+    assert_eq!(b2548.chunk_domain_size(1), 500);
 
     b2548.assert_valid();
     b2548.insert(14);
     b2548.remove(14);
-    assert_eq!(b2548.chunks(), vec![Zeros(2048), Zeros(500)]);
+    assert_eq!(b2548.chunks(), vec![Zeros, Zeros]);
     b2548.insert_all();
     for i in 0..2548 {
         assert!(b2548.contains(i));
     }
     assert_eq!(b2548.count(), 2548);
-    assert_eq!(b2548.chunks(), vec![Ones(2048), Ones(500)]);
+    assert_eq!(b2548.chunks(), vec![Ones, Ones]);
     b2548.assert_valid();
 
     //-----------------------------------------------------------------------
@@ -212,12 +211,10 @@ fn chunked_bitset() {
     let mut b4096 = ChunkedBitSet::<usize>::new_empty(4096);
     assert_eq!(
         b4096,
-        ChunkedBitSet {
-            domain_size: 4096,
-            chunks: Box::new([Zeros(2048), Zeros(2048)]),
-            marker: PhantomData,
-        }
+        ChunkedBitSet { domain_size: 4096, chunks: Box::new([Zeros, Zeros]), marker: PhantomData }
     );
+    assert_eq!(b4096.chunk_domain_size(0), 2048);
+    assert_eq!(b4096.chunk_domain_size(1), 2048);
 
     b4096.assert_valid();
     for i in 0..4096 {
@@ -231,11 +228,11 @@ fn chunked_bitset() {
         b4096.chunks(),
         #[rustfmt::skip]
         vec![
-            Mixed(2048, 1, Rc::new([
+            Mixed(1, Rc::new([
                 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
             ])),
-            Mixed(2048, 1, Rc::new([
+            Mixed(1, Rc::new([
                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x8000_0000_0000_0000
             ])),
@@ -251,10 +248,15 @@ fn chunked_bitset() {
         b10000,
         ChunkedBitSet {
             domain_size: 10000,
-            chunks: Box::new([Zeros(2048), Zeros(2048), Zeros(2048), Zeros(2048), Zeros(1808),]),
+            chunks: Box::new([Zeros, Zeros, Zeros, Zeros, Zeros,]),
             marker: PhantomData,
         }
     );
+    assert_eq!(b10000.chunk_domain_size(0), 2048);
+    assert_eq!(b10000.chunk_domain_size(1), 2048);
+    assert_eq!(b10000.chunk_domain_size(2), 2048);
+    assert_eq!(b10000.chunk_domain_size(3), 2048);
+    assert_eq!(b10000.chunk_domain_size(4), 1808);
 
     b10000.assert_valid();
     assert!(b10000.insert(3000) && b10000.insert(5000));
@@ -262,17 +264,17 @@ fn chunked_bitset() {
         b10000.chunks(),
         #[rustfmt::skip]
         vec![
-            Zeros(2048),
-            Mixed(2048, 1, Rc::new([
+            Zeros,
+            Mixed(1, Rc::new([
                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0100_0000_0000_0000, 0,
                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             ])),
-            Mixed(2048, 1, Rc::new([
+            Mixed(1, Rc::new([
                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x0100, 0,
                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
             ])),
-            Zeros(2048),
-            Zeros(1808),
+            Zeros,
+            Zeros,
         ],
     );
     let mut b10000b = ChunkedBitSet::<usize>::new_empty(10000);
diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml
index 08c03614884..6d97fa6af1f 100644
--- a/compiler/rustc_infer/Cargo.toml
+++ b/compiler/rustc_infer/Cargo.toml
@@ -18,6 +18,6 @@ rustc_middle = { path = "../rustc_middle" }
 rustc_span = { path = "../rustc_span" }
 rustc_type_ir = { path = "../rustc_type_ir" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.12"
-tracing = "0.1"
+thin-vec.workspace = true
+tracing.workspace = true
 # tidy-alphabetical-end
diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs
index 21e999b080d..bb9c8850093 100644
--- a/compiler/rustc_infer/src/infer/context.rs
+++ b/compiler/rustc_infer/src/infer/context.rs
@@ -22,10 +22,6 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
         self.next_trait_solver
     }
 
-    fn in_hir_typeck(&self) -> bool {
-        self.in_hir_typeck
-    }
-
     fn typing_mode(&self) -> ty::TypingMode<'tcx> {
         self.typing_mode()
     }
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index 9ff06bda89b..d1507f08c06 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -158,7 +158,8 @@ pub struct InferCtxtInner<'tcx> {
     region_assumptions: Vec<ty::ArgOutlivesPredicate<'tcx>>,
 
     /// `-Znext-solver`: Successfully proven goals during HIR typeck which
-    /// reference inference variables and get reproven after writeback.
+    /// reference inference variables and get reproven in case MIR type check
+    /// fails to prove something.
     ///
     /// See the documentation of `InferCtxt::in_hir_typeck` for more details.
     hir_typeck_potentially_region_dependent_goals: Vec<PredicateObligation<'tcx>>,
diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml
index 473ac5e0cea..40152e78f8a 100644
--- a/compiler/rustc_interface/Cargo.toml
+++ b/compiler/rustc_interface/Cargo.toml
@@ -46,7 +46,7 @@ rustc_thread_pool = { path = "../rustc_thread_pool" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
 rustc_traits = { path = "../rustc_traits" }
 rustc_ty_utils = { path = "../rustc_ty_utils" }
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
 
 [dev-dependencies]
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 90f7ae76387..bc5ef04079e 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -6,7 +6,7 @@ use std::sync::{Arc, LazyLock, OnceLock};
 use std::{env, fs, iter};
 
 use rustc_ast as ast;
-use rustc_attr_parsing::validate_attr;
+use rustc_attr_parsing::{AttributeParser, ShouldEmit, validate_attr};
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_data_structures::jobserver::Proxy;
 use rustc_data_structures::steal::Steal;
@@ -16,6 +16,7 @@ use rustc_errors::timings::TimingSection;
 use rustc_expand::base::{ExtCtxt, LintStoreExpand};
 use rustc_feature::Features;
 use rustc_fs_util::try_canonicalize;
+use rustc_hir::attrs::AttributeKind;
 use rustc_hir::def_id::{LOCAL_CRATE, StableCrateId, StableCrateIdMap};
 use rustc_hir::definitions::Definitions;
 use rustc_incremental::setup_dep_graph;
@@ -1244,8 +1245,7 @@ pub fn get_crate_name(sess: &Session, krate_attrs: &[ast::Attribute]) -> Symbol
     // in all code paths that require the crate name very early on, namely before
     // macro expansion.
 
-    let attr_crate_name =
-        validate_and_find_value_str_builtin_attr(sym::crate_name, sess, krate_attrs);
+    let attr_crate_name = parse_crate_name(sess, krate_attrs, ShouldEmit::EarlyFatal);
 
     let validate = |name, span| {
         rustc_session::output::validate_crate_name(sess, name, span);
@@ -1283,6 +1283,28 @@ pub fn get_crate_name(sess: &Session, krate_attrs: &[ast::Attribute]) -> Symbol
     sym::rust_out
 }
 
+pub(crate) fn parse_crate_name(
+    sess: &Session,
+    attrs: &[ast::Attribute],
+    emit_errors: ShouldEmit,
+) -> Option<(Symbol, Span)> {
+    let rustc_hir::Attribute::Parsed(AttributeKind::CrateName { name, name_span, .. }) =
+        AttributeParser::parse_limited_should_emit(
+            sess,
+            &attrs,
+            sym::crate_name,
+            DUMMY_SP,
+            rustc_ast::node_id::CRATE_NODE_ID,
+            None,
+            emit_errors,
+        )?
+    else {
+        unreachable!("crate_name is the only attr we could've parsed here");
+    };
+
+    Some((name, name_span))
+}
+
 fn get_recursion_limit(krate_attrs: &[ast::Attribute], sess: &Session) -> Limit {
     // We don't permit macro calls inside of the attribute (e.g., #![recursion_limit = `expand!()`])
     // because that would require expanding this while in the middle of expansion, which needs to
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 4425877308a..7730bddc0f1 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -8,6 +8,7 @@ use rustc_abi::Align;
 use rustc_data_structures::profiling::TimePassesFormat;
 use rustc_errors::emitter::HumanReadableErrorType;
 use rustc_errors::{ColorConfig, registry};
+use rustc_hir::attrs::NativeLibKind;
 use rustc_session::config::{
     AutoDiff, BranchProtection, CFGuard, Cfg, CollapseMacroDebuginfo, CoverageLevel,
     CoverageOptions, DebugInfo, DumpMonoStatsFormat, ErrorOutputType, ExternEntry, ExternLocation,
@@ -20,7 +21,7 @@ use rustc_session::config::{
 };
 use rustc_session::lint::Level;
 use rustc_session::search_paths::SearchPath;
-use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
+use rustc_session::utils::{CanonicalizedPath, NativeLib};
 use rustc_session::{CompilerIO, EarlyDiagCtxt, Session, build_session, getopts};
 use rustc_span::edition::{DEFAULT_EDITION, Edition};
 use rustc_span::source_map::{RealFileLoader, SourceMapInputs};
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index 9a432a60819..04006f3e446 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -5,7 +5,7 @@ use std::sync::{Arc, OnceLock};
 use std::{env, thread};
 
 use rustc_ast as ast;
-use rustc_attr_parsing::validate_attr;
+use rustc_attr_parsing::{ShouldEmit, validate_attr};
 use rustc_codegen_ssa::traits::CodegenBackend;
 use rustc_data_structures::jobserver::Proxy;
 use rustc_data_structures::sync;
@@ -24,6 +24,7 @@ use rustc_target::spec::Target;
 use tracing::info;
 
 use crate::errors;
+use crate::passes::parse_crate_name;
 
 /// Function pointer type that constructs a new CodegenBackend.
 type MakeBackendFn = fn() -> Box<dyn CodegenBackend>;
@@ -520,11 +521,10 @@ pub fn build_output_filenames(attrs: &[ast::Attribute], sess: &Session) -> Outpu
         sess.dcx().emit_fatal(errors::MultipleOutputTypesToStdout);
     }
 
-    let crate_name = sess
-        .opts
-        .crate_name
-        .clone()
-        .or_else(|| rustc_attr_parsing::find_crate_name(attrs).map(|n| n.to_string()));
+    let crate_name =
+        sess.opts.crate_name.clone().or_else(|| {
+            parse_crate_name(sess, attrs, ShouldEmit::Nothing).map(|i| i.0.to_string())
+        });
 
     match sess.io.output_file {
         None => {
diff --git a/compiler/rustc_lexer/Cargo.toml b/compiler/rustc_lexer/Cargo.toml
index 448a50faf45..e0019fb1821 100644
--- a/compiler/rustc_lexer/Cargo.toml
+++ b/compiler/rustc_lexer/Cargo.toml
@@ -14,13 +14,9 @@ Rust lexer used by rustc. No stability guarantees are provided.
 
 # Note that this crate purposefully does not depend on other rustc crates
 [dependencies]
-memchr = "2.7.4"
+memchr.workspace = true
+unicode-properties = { version = "0.1.0", default-features = false, features = ["emoji"] }
 unicode-xid = "0.2.0"
 
-[dependencies.unicode-properties]
-version = "0.1.0"
-default-features = false
-features = ["emoji"]
-
 [dev-dependencies]
 expect-test = "1.4.0"
diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml
index 7718f16984d..7900e4b9ab2 100644
--- a/compiler/rustc_lint/Cargo.toml
+++ b/compiler/rustc_lint/Cargo.toml
@@ -24,6 +24,6 @@ rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-tracing = "0.1"
+tracing.workspace = true
 unicode-security = "0.1.0"
 # tidy-alphabetical-end
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 940a07c94df..417e5a97069 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -462,6 +462,14 @@ lint_invalid_reference_casting_note_book = for more information, visit <https://
 
 lint_invalid_reference_casting_note_ty_has_interior_mutability = even for types with interior mutability, the only legal way to obtain a mutable pointer from a shared reference is through `UnsafeCell::get`
 
+lint_int_to_ptr_transmutes = transmuting an integer to a pointer creates a pointer without provenance
+    .note = this is dangerous because dereferencing the resulting pointer is undefined behavior
+    .note_exposed_provenance = exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+    .help_transmute = for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+    .help_exposed_provenance = for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+    .suggestion_with_exposed_provenance = use `std::ptr::with_exposed_provenance{$suffix}` instead to use a previously exposed provenance
+    .suggestion_without_provenance_mut = if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+
 lint_legacy_derive_helpers = derive helper attribute is used before it is introduced
     .label = the attribute is introduced here
 
diff --git a/compiler/rustc_lint/src/lifetime_syntax.rs b/compiler/rustc_lint/src/lifetime_syntax.rs
index 464f4fc34b9..413525eb6e5 100644
--- a/compiler/rustc_lint/src/lifetime_syntax.rs
+++ b/compiler/rustc_lint/src/lifetime_syntax.rs
@@ -214,9 +214,9 @@ impl<T> LifetimeSyntaxCategories<Vec<T>> {
         }
     }
 
-    pub fn flatten(&self) -> impl Iterator<Item = &T> {
-        let Self { hidden, elided, named } = self;
-        [hidden.iter(), elided.iter(), named.iter()].into_iter().flatten()
+    pub fn iter_unnamed(&self) -> impl Iterator<Item = &T> {
+        let Self { hidden, elided, named: _ } = self;
+        [hidden.iter(), elided.iter()].into_iter().flatten()
     }
 }
 
@@ -495,7 +495,7 @@ fn emit_mismatch_diagnostic<'tcx>(
 
     cx.emit_span_lint(
         MISMATCHED_LIFETIME_SYNTAXES,
-        inputs.flatten().copied().collect::<Vec<_>>(),
+        inputs.iter_unnamed().chain(outputs.iter_unnamed()).copied().collect::<Vec<_>>(),
         lints::MismatchedLifetimeSyntaxes { inputs, outputs, suggestions },
     );
 }
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 6c509734626..56d65ed08f9 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -1,3 +1,5 @@
+// ignore-tidy-filelength
+
 #![allow(rustc::untranslatable_diagnostic)]
 use std::num::NonZero;
 
@@ -1542,6 +1544,48 @@ impl<'a> LintDiagnostic<'a, ()> for DropGlue<'_> {
     }
 }
 
+// transmute.rs
+#[derive(LintDiagnostic)]
+#[diag(lint_int_to_ptr_transmutes)]
+#[note]
+#[note(lint_note_exposed_provenance)]
+#[help(lint_suggestion_without_provenance_mut)]
+#[help(lint_help_transmute)]
+#[help(lint_help_exposed_provenance)]
+pub(crate) struct IntegerToPtrTransmutes<'tcx> {
+    #[subdiagnostic]
+    pub suggestion: Option<IntegerToPtrTransmutesSuggestion<'tcx>>,
+}
+
+#[derive(Subdiagnostic)]
+pub(crate) enum IntegerToPtrTransmutesSuggestion<'tcx> {
+    #[multipart_suggestion(
+        lint_suggestion_with_exposed_provenance,
+        applicability = "machine-applicable",
+        style = "verbose"
+    )]
+    ToPtr {
+        dst: Ty<'tcx>,
+        suffix: &'static str,
+        #[suggestion_part(code = "std::ptr::with_exposed_provenance{suffix}::<{dst}>(")]
+        start_call: Span,
+    },
+    #[multipart_suggestion(
+        lint_suggestion_with_exposed_provenance,
+        applicability = "machine-applicable",
+        style = "verbose"
+    )]
+    ToRef {
+        dst: Ty<'tcx>,
+        suffix: &'static str,
+        ref_mutbl: &'static str,
+        #[suggestion_part(
+            code = "&{ref_mutbl}*std::ptr::with_exposed_provenance{suffix}::<{dst}>("
+        )]
+        start_call: Span,
+    },
+}
+
 // types.rs
 #[derive(LintDiagnostic)]
 #[diag(lint_range_endpoint_out_of_range)]
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index 8fafaa33d0c..65075cfecfa 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -5,7 +5,7 @@ use rustc_hir::attrs::{AttributeKind, ReprAttr};
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_hir::intravisit::{FnKind, Visitor};
-use rustc_hir::{AttrArgs, AttrItem, Attribute, GenericParamKind, PatExprKind, PatKind, find_attr};
+use rustc_hir::{Attribute, GenericParamKind, PatExprKind, PatKind, find_attr};
 use rustc_middle::hir::nested_filter::All;
 use rustc_middle::ty;
 use rustc_session::config::CrateType;
@@ -343,35 +343,27 @@ impl<'tcx> LateLintPass<'tcx> for NonSnakeCase {
         let crate_ident = if let Some(name) = &cx.tcx.sess.opts.crate_name {
             Some(Ident::from_str(name))
         } else {
-            ast::attr::find_by_name(cx.tcx.hir_attrs(hir::CRATE_HIR_ID), sym::crate_name).and_then(
-                |attr| {
-                    if let Attribute::Unparsed(n) = attr
-                        && let AttrItem { args: AttrArgs::Eq { eq_span: _, expr: lit }, .. } =
-                            n.as_ref()
-                        && let ast::LitKind::Str(name, ..) = lit.kind
-                    {
-                        // Discard the double quotes surrounding the literal.
-                        let sp = cx
-                            .sess()
-                            .source_map()
-                            .span_to_snippet(lit.span)
-                            .ok()
-                            .and_then(|snippet| {
-                                let left = snippet.find('"')?;
-                                let right = snippet.rfind('"').map(|pos| snippet.len() - pos)?;
-
-                                Some(
-                                    lit.span
-                                        .with_lo(lit.span.lo() + BytePos(left as u32 + 1))
-                                        .with_hi(lit.span.hi() - BytePos(right as u32)),
-                                )
-                            })
-                            .unwrap_or(lit.span);
-
-                        Some(Ident::new(name, sp))
-                    } else {
-                        None
-                    }
+            find_attr!(cx.tcx.hir_attrs(hir::CRATE_HIR_ID), AttributeKind::CrateName{name, name_span,..} => (name, name_span)).map(
+                |(&name, &span)| {
+                    // Discard the double quotes surrounding the literal.
+                    let sp = cx
+                        .sess()
+                        .source_map()
+                        .span_to_snippet(span)
+                        .ok()
+                        .and_then(|snippet| {
+                            let left = snippet.find('"')?;
+                            let right = snippet.rfind('"').map(|pos| snippet.len() - pos)?;
+
+                            Some(
+                                span
+                                    .with_lo(span.lo() + BytePos(left as u32 + 1))
+                                    .with_hi(span.hi() - BytePos(right as u32)),
+                            )
+                        })
+                        .unwrap_or(span);
+
+                    Ident::new(name, sp)
                 },
             )
         };
diff --git a/compiler/rustc_lint/src/transmute.rs b/compiler/rustc_lint/src/transmute.rs
index bc1d4587d07..98510eea73b 100644
--- a/compiler/rustc_lint/src/transmute.rs
+++ b/compiler/rustc_lint/src/transmute.rs
@@ -1,3 +1,4 @@
+use rustc_ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::LocalDefId;
@@ -7,6 +8,7 @@ use rustc_middle::ty::{self, Ty};
 use rustc_session::{declare_lint, impl_lint_pass};
 use rustc_span::sym;
 
+use crate::lints::{IntegerToPtrTransmutes, IntegerToPtrTransmutesSuggestion};
 use crate::{LateContext, LateLintPass};
 
 declare_lint! {
@@ -67,9 +69,44 @@ declare_lint! {
     "detects transmutes that can also be achieved by other operations"
 }
 
+declare_lint! {
+    /// The `integer_to_ptr_transmutes` lint detects integer to pointer
+    /// transmutes where the resulting pointers are undefined behavior to dereference.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// fn foo(a: usize) -> *const u8 {
+    ///    unsafe {
+    ///        std::mem::transmute::<usize, *const u8>(a)
+    ///    }
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Any attempt to use the resulting pointers are undefined behavior as the resulting
+    /// pointers won't have any provenance.
+    ///
+    /// Alternatively, [`std::ptr::with_exposed_provenance`] should be used, as they do not
+    /// carry the provenance requirement. If wanting to create pointers without provenance
+    /// [`std::ptr::without_provenance`] should be used instead.
+    ///
+    /// See [`std::mem::transmute`] in the reference for more details.
+    ///
+    /// [`std::mem::transmute`]: https://doc.rust-lang.org/std/mem/fn.transmute.html
+    /// [`std::ptr::with_exposed_provenance`]: https://doc.rust-lang.org/std/ptr/fn.with_exposed_provenance.html
+    /// [`std::ptr::without_provenance`]: https://doc.rust-lang.org/std/ptr/fn.without_provenance.html
+    pub INTEGER_TO_PTR_TRANSMUTES,
+    Warn,
+    "detects integer to pointer transmutes",
+}
+
 pub(crate) struct CheckTransmutes;
 
-impl_lint_pass!(CheckTransmutes => [PTR_TO_INTEGER_TRANSMUTE_IN_CONSTS, UNNECESSARY_TRANSMUTES]);
+impl_lint_pass!(CheckTransmutes => [PTR_TO_INTEGER_TRANSMUTE_IN_CONSTS, UNNECESSARY_TRANSMUTES, INTEGER_TO_PTR_TRANSMUTES]);
 
 impl<'tcx> LateLintPass<'tcx> for CheckTransmutes {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) {
@@ -94,9 +131,68 @@ impl<'tcx> LateLintPass<'tcx> for CheckTransmutes {
 
         check_ptr_transmute_in_const(cx, expr, body_owner_def_id, const_context, src, dst);
         check_unnecessary_transmute(cx, expr, callee, arg, const_context, src, dst);
+        check_int_to_ptr_transmute(cx, expr, arg, src, dst);
     }
 }
 
+/// Check for transmutes from integer to pointers (*const/*mut and &/&mut).
+///
+/// Using the resulting pointers would be undefined behavior.
+fn check_int_to_ptr_transmute<'tcx>(
+    cx: &LateContext<'tcx>,
+    expr: &'tcx hir::Expr<'tcx>,
+    arg: &'tcx hir::Expr<'tcx>,
+    src: Ty<'tcx>,
+    dst: Ty<'tcx>,
+) {
+    if !matches!(src.kind(), ty::Uint(_) | ty::Int(_)) {
+        return;
+    }
+    let (ty::Ref(_, inner_ty, mutbl) | ty::RawPtr(inner_ty, mutbl)) = dst.kind() else {
+        return;
+    };
+    // bail-out if the argument is literal 0 as we have other lints for those cases
+    if matches!(arg.kind, hir::ExprKind::Lit(hir::Lit { node: LitKind::Int(v, _), .. }) if v == 0) {
+        return;
+    }
+    // bail-out if the inner type is a ZST
+    let Ok(layout_inner_ty) = cx.tcx.layout_of(cx.typing_env().as_query_input(*inner_ty)) else {
+        return;
+    };
+    if layout_inner_ty.is_1zst() {
+        return;
+    }
+
+    let suffix = if mutbl.is_mut() { "_mut" } else { "" };
+    cx.tcx.emit_node_span_lint(
+        INTEGER_TO_PTR_TRANSMUTES,
+        expr.hir_id,
+        expr.span,
+        IntegerToPtrTransmutes {
+            suggestion: if layout_inner_ty.is_sized() {
+                Some(if dst.is_ref() {
+                    IntegerToPtrTransmutesSuggestion::ToRef {
+                        dst: *inner_ty,
+                        suffix,
+                        ref_mutbl: mutbl.prefix_str(),
+                        start_call: expr.span.shrink_to_lo().until(arg.span),
+                    }
+                } else {
+                    IntegerToPtrTransmutesSuggestion::ToPtr {
+                        dst: *inner_ty,
+                        suffix,
+                        start_call: expr.span.shrink_to_lo().until(arg.span),
+                    }
+                })
+            } else {
+                // We can't suggest using `with_exposed_provenance` for unsized type
+                // so don't suggest anything.
+                None
+            },
+        },
+    );
+}
+
 /// Check for transmutes that exhibit undefined behavior.
 /// For example, transmuting pointers to integers in a const context.
 ///
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index e699e4b9c13..361a5f76551 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -242,7 +242,7 @@ enum class LLVMRustAttributeKind {
   MinSize = 4,
   Naked = 5,
   NoAlias = 6,
-  NoCapture = 7,
+  CapturesAddress = 7,
   NoInline = 8,
   NonNull = 9,
   NoRedZone = 10,
@@ -297,12 +297,6 @@ static Attribute::AttrKind fromRust(LLVMRustAttributeKind Kind) {
     return Attribute::Naked;
   case LLVMRustAttributeKind::NoAlias:
     return Attribute::NoAlias;
-  case LLVMRustAttributeKind::NoCapture:
-#if LLVM_VERSION_GE(21, 0)
-    report_fatal_error("NoCapture doesn't exist in LLVM 21");
-#else
-    return Attribute::NoCapture;
-#endif
   case LLVMRustAttributeKind::NoCfCheck:
     return Attribute::NoCfCheck;
   case LLVMRustAttributeKind::NoInline:
@@ -377,6 +371,7 @@ static Attribute::AttrKind fromRust(LLVMRustAttributeKind Kind) {
 #else
     report_fatal_error("DeadOnReturn attribute requires LLVM 21 or later");
 #endif
+  case LLVMRustAttributeKind::CapturesAddress:
   case LLVMRustAttributeKind::CapturesReadOnly:
     report_fatal_error("Should be handled separately");
   }
@@ -429,9 +424,9 @@ extern "C" void LLVMRustEraseInstFromParent(LLVMValueRef Instr) {
 extern "C" LLVMAttributeRef
 LLVMRustCreateAttrNoValue(LLVMContextRef C, LLVMRustAttributeKind RustAttr) {
 #if LLVM_VERSION_GE(21, 0)
-  // LLVM 21 replaced the NoCapture attribute with Captures(none).
-  if (RustAttr == LLVMRustAttributeKind::NoCapture) {
-    return wrap(Attribute::getWithCaptureInfo(*unwrap(C), CaptureInfo::none()));
+  if (RustAttr == LLVMRustAttributeKind::CapturesAddress) {
+    return wrap(Attribute::getWithCaptureInfo(
+        *unwrap(C), CaptureInfo(CaptureComponents::Address)));
   }
   if (RustAttr == LLVMRustAttributeKind::CapturesReadOnly) {
     return wrap(Attribute::getWithCaptureInfo(
@@ -488,6 +483,9 @@ extern "C" LLVMAttributeRef
 LLVMRustCreateRangeAttribute(LLVMContextRef C, unsigned NumBits,
                              const uint64_t LowerWords[],
                              const uint64_t UpperWords[]) {
+  // FIXME(Zalathar): There appears to be no stable guarantee that C++
+  // `AttrKind` values correspond directly to the `unsigned KindID` values
+  // accepted by LLVM-C API functions, though in practice they currently do.
   return LLVMCreateConstantRangeAttribute(C, Attribute::Range, NumBits,
                                           LowerWords, UpperWords);
 }
diff --git a/compiler/rustc_log/Cargo.toml b/compiler/rustc_log/Cargo.toml
index c673d51a1d4..e9d7b4723f8 100644
--- a/compiler/rustc_log/Cargo.toml
+++ b/compiler/rustc_log/Cargo.toml
@@ -5,10 +5,10 @@ edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
-tracing = "0.1.28"
 tracing-core = "=0.1.30" # FIXME(Nilstrieb) tracing has a deadlock: https://github.com/tokio-rs/tracing/issues/2635
 tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
 tracing-tree = "0.3.1"
+tracing.workspace = true
 # tidy-alphabetical-end
 
 [features]
diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml
index 1b40d9f684e..4bb9e49ccce 100644
--- a/compiler/rustc_metadata/Cargo.toml
+++ b/compiler/rustc_metadata/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
-bitflags = "2.4.1"
+bitflags.workspace = true
 libloading = "0.8.0"
 odht = { version = "0.3.1", features = ["nightly"] }
 rustc_abi = { path = "../rustc_abi" }
@@ -31,7 +31,7 @@ rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 tempfile = "3.7.1"
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
 
 [target.'cfg(target_os = "aix")'.dependencies]
diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl
index 4d3e879a098..e104be2c466 100644
--- a/compiler/rustc_metadata/messages.ftl
+++ b/compiler/rustc_metadata/messages.ftl
@@ -1,6 +1,3 @@
-metadata_as_needed_compatibility =
-    linking modifier `as-needed` is only compatible with `dylib` and `framework` linking kinds
-
 metadata_async_drop_types_in_dependency =
     found async drop types in dependency `{$extern_crate}`, but async_drop feature is disabled for `{$local_crate}`
     .help = if async drop type will be dropped in a crate without `feature(async_drop)`, sync Drop will be used
@@ -11,9 +8,6 @@ metadata_bad_panic_strategy =
 metadata_binary_output_to_tty =
     option `-o` or `--emit` is used to write binary output type `metadata` to stdout, but stdout is a tty
 
-metadata_bundle_needs_static =
-    linking modifier `bundle` is only compatible with `static` linking kind
-
 metadata_cannot_find_crate =
     can't find crate for `{$crate_name}`{$add_info}
 
@@ -60,10 +54,6 @@ metadata_crate_not_panic_runtime =
 metadata_dl_error =
     {$path}{$err}
 
-metadata_empty_link_name =
-    link name must not be empty
-    .label = empty link name
-
 metadata_empty_renaming_target =
     an empty renaming target was specified for library `{$lib_name}`
 
@@ -108,15 +98,6 @@ metadata_full_metadata_not_found =
 metadata_global_alloc_required =
     no global memory allocator found but one is required; link to std or add `#[global_allocator]` to a static item that implements the GlobalAlloc trait
 
-metadata_import_name_type_form =
-    import name type must be of the form `import_name_type = "string"`
-
-metadata_import_name_type_raw =
-    import name type can only be used with link kind `raw-dylib`
-
-metadata_import_name_type_x86 =
-    import name type is only supported on x86
-
 metadata_incompatible_panic_in_drop_strategy =
     the crate `{$crate_name}` is compiled with the panic-in-drop strategy `{$found_strategy}` which is incompatible with this crate's strategy of `{$desired_strategy}`
 
@@ -143,15 +124,10 @@ metadata_incompatible_target_modifiers_r_missed =
     mixing `{$flag_name_prefixed}` will cause an ABI mismatch in crate `{$local_crate}`
     .note = `{$flag_name_prefixed}={$local_value}` in this crate is incompatible with unset `{$flag_name_prefixed}` in dependency `{$extern_crate}`
     .help = the `{$flag_name_prefixed}` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely
-metadata_incompatible_wasm_link =
-    `wasm_import_module` is incompatible with other arguments in `#[link]` attributes
 
 metadata_install_missing_components =
     maybe you need to install the missing components with: `rustup component add rust-src rustc-dev llvm-tools-preview`
 
-metadata_invalid_link_modifier =
-    invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
-
 metadata_invalid_meta_files =
     found invalid metadata files for crate `{$crate_name}`{$add_info}
 
@@ -164,67 +140,18 @@ metadata_lib_framework_apple =
 metadata_lib_required =
     crate `{$crate_name}` required to be available in {$kind} format, but was not found in this form
 
-metadata_link_arg_unstable =
-    link kind `link-arg` is unstable
-
-metadata_link_cfg_form =
-    link cfg must be of the form `cfg(/* predicate */)`
-
-metadata_link_cfg_single_predicate =
-    link cfg must have a single predicate argument
-
-metadata_link_cfg_unstable =
-    link cfg is unstable
-
-metadata_link_framework_apple =
-    link kind `framework` is only supported on Apple targets
-
-metadata_link_kind_form =
-    link kind must be of the form `kind = "string"`
-
-metadata_link_modifiers_form =
-    link modifiers must be of the form `modifiers = "string"`
-
-metadata_link_name_form =
-    link name must be of the form `name = "string"`
-
 metadata_link_ordinal_raw_dylib =
     `#[link_ordinal]` is only supported if link kind is `raw-dylib`
 
-metadata_link_requires_name =
-    `#[link]` attribute requires a `name = "string"` argument
-    .label = missing `name` argument
-
 metadata_missing_native_library =
     could not find native static library `{$libname}`, perhaps an -L flag is missing?
 
 metadata_multiple_candidates =
     multiple candidates for `{$flavor}` dependency `{$crate_name}` found
 
-metadata_multiple_cfgs =
-    multiple `cfg` arguments in a single `#[link]` attribute
-
-metadata_multiple_import_name_type =
-    multiple `import_name_type` arguments in a single `#[link]` attribute
-
-metadata_multiple_kinds_in_link =
-    multiple `kind` arguments in a single `#[link]` attribute
-
-metadata_multiple_link_modifiers =
-    multiple `modifiers` arguments in a single `#[link]` attribute
-
-metadata_multiple_modifiers =
-    multiple `{$modifier}` modifiers in a single `modifiers` argument
-
-metadata_multiple_names_in_link =
-    multiple `name` arguments in a single `#[link]` attribute
-
 metadata_multiple_renamings =
     multiple renamings were specified for library `{$lib_name}`
 
-metadata_multiple_wasm_import =
-    multiple `wasm_import_module` arguments in a single `#[link]` attribute
-
 metadata_newer_crate_version =
     found possibly newer version of crate `{$crate_name}`{$add_info}
     .note = perhaps that crate needs to be recompiled?
@@ -263,15 +190,6 @@ metadata_prev_alloc_error_handler =
 metadata_prev_global_alloc =
     previous global allocator defined here
 
-metadata_raw_dylib_elf_unstable =
-    link kind `raw-dylib` is unstable on ELF platforms
-
-metadata_raw_dylib_no_nul =
-    link name must not contain NUL characters if link kind is `raw-dylib`
-
-metadata_raw_dylib_only_windows =
-    link kind `raw-dylib` is only supported on Windows targets
-
 metadata_raw_dylib_unsupported_abi =
     ABI not supported by `#[link(kind = "raw-dylib")]` on this architecture
 
@@ -307,19 +225,6 @@ metadata_target_not_installed =
 metadata_two_panic_runtimes =
     cannot link together two panic runtimes: {$prev_name} and {$cur_name}
 
-metadata_unexpected_link_arg =
-    unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type
-
-metadata_unknown_import_name_type =
-    unknown import name type `{$import_name_type}`, expected one of: decorated, noprefix, undecorated
-
-metadata_unknown_link_kind =
-    unknown link kind `{$kind}`, expected one of: static, dylib, framework, raw-dylib, link-arg
-    .label = unknown link kind
-
-metadata_unknown_link_modifier =
-    unknown linking modifier `{$modifier}`, expected one of: bundle, verbatim, whole-archive, as-needed
-
 metadata_unknown_target_modifier_unsafe_allowed = unknown target modifier `{$flag_name}`, requested by `-Cunsafe-allow-abi-mismatch={$flag_name}`
 
 metadata_wasm_c_abi =
diff --git a/compiler/rustc_metadata/src/errors.rs b/compiler/rustc_metadata/src/errors.rs
index 0332dba1077..e5a4fd48353 100644
--- a/compiler/rustc_metadata/src/errors.rs
+++ b/compiler/rustc_metadata/src/errors.rs
@@ -84,187 +84,6 @@ pub struct IncompatiblePanicInDropStrategy {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata_multiple_names_in_link)]
-pub struct MultipleNamesInLink {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_multiple_kinds_in_link)]
-pub struct MultipleKindsInLink {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_link_name_form)]
-pub struct LinkNameForm {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_link_kind_form)]
-pub struct LinkKindForm {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_link_modifiers_form)]
-pub struct LinkModifiersForm {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_link_cfg_form)]
-pub struct LinkCfgForm {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_wasm_import_form)]
-pub struct WasmImportForm {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_empty_link_name, code = E0454)]
-pub struct EmptyLinkName {
-    #[primary_span]
-    #[label]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_link_framework_apple, code = E0455)]
-pub struct LinkFrameworkApple {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_raw_dylib_only_windows, code = E0455)]
-pub struct RawDylibOnlyWindows {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_unknown_link_kind, code = E0458)]
-pub struct UnknownLinkKind<'a> {
-    #[primary_span]
-    #[label]
-    pub span: Span,
-    pub kind: &'a str,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_multiple_link_modifiers)]
-pub struct MultipleLinkModifiers {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_multiple_cfgs)]
-pub struct MultipleCfgs {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_link_cfg_single_predicate)]
-pub struct LinkCfgSinglePredicate {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_multiple_wasm_import)]
-pub struct MultipleWasmImport {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_unexpected_link_arg)]
-pub struct UnexpectedLinkArg {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_invalid_link_modifier)]
-pub struct InvalidLinkModifier {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_multiple_modifiers)]
-pub struct MultipleModifiers<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub modifier: &'a str,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_bundle_needs_static)]
-pub struct BundleNeedsStatic {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_whole_archive_needs_static)]
-pub struct WholeArchiveNeedsStatic {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_as_needed_compatibility)]
-pub struct AsNeededCompatibility {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_unknown_link_modifier)]
-pub struct UnknownLinkModifier<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub modifier: &'a str,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_incompatible_wasm_link)]
-pub struct IncompatibleWasmLink {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_link_requires_name, code = E0459)]
-pub struct LinkRequiresName {
-    #[primary_span]
-    #[label]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_raw_dylib_no_nul)]
-pub struct RawDylibNoNul {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(metadata_link_ordinal_raw_dylib)]
 pub struct LinkOrdinalRawDylib {
     #[primary_span]
@@ -707,42 +526,6 @@ pub struct LibFilenameForm<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(metadata_multiple_import_name_type)]
-pub struct MultipleImportNameType {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_import_name_type_form)]
-pub struct ImportNameTypeForm {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_import_name_type_x86)]
-pub struct ImportNameTypeX86 {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_unknown_import_name_type)]
-pub struct UnknownImportNameType<'a> {
-    #[primary_span]
-    pub span: Span,
-    pub import_name_type: &'a str,
-}
-
-#[derive(Diagnostic)]
-#[diag(metadata_import_name_type_raw)]
-pub struct ImportNameTypeRaw {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(metadata_wasm_c_abi)]
 pub(crate) struct WasmCAbi {
     #[primary_span]
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 63f1b51df1c..82738c68c59 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -3,25 +3,21 @@ use std::path::{Path, PathBuf};
 
 use rustc_abi::ExternAbi;
 use rustc_ast::CRATE_NODE_ID;
-use rustc_attr_parsing as attr;
+use rustc_attr_parsing::{ShouldEmit, eval_config_entry};
 use rustc_data_structures::fx::FxHashSet;
-use rustc_hir::attrs::AttributeKind;
+use rustc_hir::attrs::{AttributeKind, NativeLibKind, PeImportNameType};
 use rustc_hir::find_attr;
 use rustc_middle::query::LocalCrate;
 use rustc_middle::ty::{self, List, Ty, TyCtxt};
 use rustc_session::Session;
 use rustc_session::config::CrateType;
-use rustc_session::cstore::{
-    DllCallingConvention, DllImport, ForeignModule, NativeLib, PeImportNameType,
-};
-use rustc_session::parse::feature_err;
+use rustc_session::cstore::{DllCallingConvention, DllImport, ForeignModule, NativeLib};
 use rustc_session::search_paths::PathKind;
-use rustc_session::utils::NativeLibKind;
+use rustc_span::Symbol;
 use rustc_span::def_id::{DefId, LOCAL_CRATE};
-use rustc_span::{Symbol, sym};
 use rustc_target::spec::{BinaryFormat, LinkSelfContainedComponents};
 
-use crate::{errors, fluent_generated};
+use crate::errors;
 
 /// The fallback directories are passed to linker, but not used when rustc does the search,
 /// because in the latter case the set of fallback directories cannot always be determined
@@ -192,7 +188,9 @@ pub(crate) fn collect(tcx: TyCtxt<'_>, LocalCrate: LocalCrate) -> Vec<NativeLib>
 
 pub(crate) fn relevant_lib(sess: &Session, lib: &NativeLib) -> bool {
     match lib.cfg {
-        Some(ref cfg) => attr::cfg_matches(cfg, sess, CRATE_NODE_ID, None),
+        Some(ref cfg) => {
+            eval_config_entry(sess, cfg, CRATE_NODE_ID, None, ShouldEmit::ErrorsAndLints).as_bool()
+        }
         None => true,
     }
 }
@@ -213,289 +211,23 @@ impl<'tcx> Collector<'tcx> {
             return;
         }
 
-        // Process all of the #[link(..)]-style arguments
-        let features = self.tcx.features();
-
-        for m in self.tcx.get_attrs(def_id, sym::link) {
-            let Some(items) = m.meta_item_list() else {
-                continue;
-            };
-
-            let mut name = None;
-            let mut kind = None;
-            let mut modifiers = None;
-            let mut cfg = None;
-            let mut wasm_import_module = None;
-            let mut import_name_type = None;
-            for item in items.iter() {
-                match item.name() {
-                    Some(sym::name) => {
-                        if name.is_some() {
-                            sess.dcx().emit_err(errors::MultipleNamesInLink { span: item.span() });
-                            continue;
-                        }
-                        let Some(link_name) = item.value_str() else {
-                            sess.dcx().emit_err(errors::LinkNameForm { span: item.span() });
-                            continue;
-                        };
-                        let span = item.name_value_literal_span().unwrap();
-                        if link_name.is_empty() {
-                            sess.dcx().emit_err(errors::EmptyLinkName { span });
-                        }
-                        name = Some((link_name, span));
-                    }
-                    Some(sym::kind) => {
-                        if kind.is_some() {
-                            sess.dcx().emit_err(errors::MultipleKindsInLink { span: item.span() });
-                            continue;
-                        }
-                        let Some(link_kind) = item.value_str() else {
-                            sess.dcx().emit_err(errors::LinkKindForm { span: item.span() });
-                            continue;
-                        };
-
-                        let span = item.name_value_literal_span().unwrap();
-                        let link_kind = match link_kind.as_str() {
-                            "static" => NativeLibKind::Static { bundle: None, whole_archive: None },
-                            "dylib" => NativeLibKind::Dylib { as_needed: None },
-                            "framework" => {
-                                if !sess.target.is_like_darwin {
-                                    sess.dcx().emit_err(errors::LinkFrameworkApple { span });
-                                }
-                                NativeLibKind::Framework { as_needed: None }
-                            }
-                            "raw-dylib" => {
-                                if sess.target.is_like_windows {
-                                    // raw-dylib is stable and working on Windows
-                                } else if sess.target.binary_format == BinaryFormat::Elf
-                                    && features.raw_dylib_elf()
-                                {
-                                    // raw-dylib is unstable on ELF, but the user opted in
-                                } else if sess.target.binary_format == BinaryFormat::Elf
-                                    && sess.is_nightly_build()
-                                {
-                                    feature_err(
-                                        sess,
-                                        sym::raw_dylib_elf,
-                                        span,
-                                        fluent_generated::metadata_raw_dylib_elf_unstable,
-                                    )
-                                    .emit();
-                                } else {
-                                    sess.dcx().emit_err(errors::RawDylibOnlyWindows { span });
-                                }
-
-                                NativeLibKind::RawDylib
-                            }
-                            "link-arg" => {
-                                if !features.link_arg_attribute() {
-                                    feature_err(
-                                        sess,
-                                        sym::link_arg_attribute,
-                                        span,
-                                        fluent_generated::metadata_link_arg_unstable,
-                                    )
-                                    .emit();
-                                }
-                                NativeLibKind::LinkArg
-                            }
-                            kind => {
-                                sess.dcx().emit_err(errors::UnknownLinkKind { span, kind });
-                                continue;
-                            }
-                        };
-                        kind = Some(link_kind);
-                    }
-                    Some(sym::modifiers) => {
-                        if modifiers.is_some() {
-                            sess.dcx()
-                                .emit_err(errors::MultipleLinkModifiers { span: item.span() });
-                            continue;
-                        }
-                        let Some(link_modifiers) = item.value_str() else {
-                            sess.dcx().emit_err(errors::LinkModifiersForm { span: item.span() });
-                            continue;
-                        };
-                        modifiers = Some((link_modifiers, item.name_value_literal_span().unwrap()));
-                    }
-                    Some(sym::cfg) => {
-                        if cfg.is_some() {
-                            sess.dcx().emit_err(errors::MultipleCfgs { span: item.span() });
-                            continue;
-                        }
-                        let Some(link_cfg) = item.meta_item_list() else {
-                            sess.dcx().emit_err(errors::LinkCfgForm { span: item.span() });
-                            continue;
-                        };
-                        let [link_cfg] = link_cfg else {
-                            sess.dcx()
-                                .emit_err(errors::LinkCfgSinglePredicate { span: item.span() });
-                            continue;
-                        };
-                        let Some(link_cfg) = link_cfg.meta_item_or_bool() else {
-                            sess.dcx()
-                                .emit_err(errors::LinkCfgSinglePredicate { span: item.span() });
-                            continue;
-                        };
-                        if !features.link_cfg() {
-                            feature_err(
-                                sess,
-                                sym::link_cfg,
-                                item.span(),
-                                fluent_generated::metadata_link_cfg_unstable,
-                            )
-                            .emit();
-                        }
-                        cfg = Some(link_cfg.clone());
-                    }
-                    Some(sym::wasm_import_module) => {
-                        if wasm_import_module.is_some() {
-                            sess.dcx().emit_err(errors::MultipleWasmImport { span: item.span() });
-                            continue;
-                        }
-                        let Some(link_wasm_import_module) = item.value_str() else {
-                            sess.dcx().emit_err(errors::WasmImportForm { span: item.span() });
-                            continue;
-                        };
-                        wasm_import_module = Some((link_wasm_import_module, item.span()));
-                    }
-                    Some(sym::import_name_type) => {
-                        if import_name_type.is_some() {
-                            sess.dcx()
-                                .emit_err(errors::MultipleImportNameType { span: item.span() });
-                            continue;
-                        }
-                        let Some(link_import_name_type) = item.value_str() else {
-                            sess.dcx().emit_err(errors::ImportNameTypeForm { span: item.span() });
-                            continue;
-                        };
-                        if self.tcx.sess.target.arch != "x86" {
-                            sess.dcx().emit_err(errors::ImportNameTypeX86 { span: item.span() });
-                            continue;
-                        }
-
-                        let link_import_name_type = match link_import_name_type.as_str() {
-                            "decorated" => PeImportNameType::Decorated,
-                            "noprefix" => PeImportNameType::NoPrefix,
-                            "undecorated" => PeImportNameType::Undecorated,
-                            import_name_type => {
-                                sess.dcx().emit_err(errors::UnknownImportNameType {
-                                    span: item.span(),
-                                    import_name_type,
-                                });
-                                continue;
-                            }
-                        };
-                        import_name_type = Some((link_import_name_type, item.span()));
-                    }
-                    _ => {
-                        sess.dcx().emit_err(errors::UnexpectedLinkArg { span: item.span() });
-                    }
-                }
-            }
-
-            // Do this outside the above loop so we don't depend on modifiers coming after kinds
-            let mut verbatim = None;
-            if let Some((modifiers, span)) = modifiers {
-                for modifier in modifiers.as_str().split(',') {
-                    let (modifier, value) = match modifier.strip_prefix(&['+', '-']) {
-                        Some(m) => (m, modifier.starts_with('+')),
-                        None => {
-                            sess.dcx().emit_err(errors::InvalidLinkModifier { span });
-                            continue;
-                        }
-                    };
-
-                    macro report_unstable_modifier($feature: ident) {
-                        if !features.$feature() {
-                            // FIXME: make this translatable
-                            #[expect(rustc::untranslatable_diagnostic)]
-                            feature_err(
-                                sess,
-                                sym::$feature,
-                                span,
-                                format!("linking modifier `{modifier}` is unstable"),
-                            )
-                            .emit();
-                        }
-                    }
-                    let assign_modifier = |dst: &mut Option<bool>| {
-                        if dst.is_some() {
-                            sess.dcx().emit_err(errors::MultipleModifiers { span, modifier });
-                        } else {
-                            *dst = Some(value);
-                        }
-                    };
-                    match (modifier, &mut kind) {
-                        ("bundle", Some(NativeLibKind::Static { bundle, .. })) => {
-                            assign_modifier(bundle)
-                        }
-                        ("bundle", _) => {
-                            sess.dcx().emit_err(errors::BundleNeedsStatic { span });
-                        }
-
-                        ("verbatim", _) => assign_modifier(&mut verbatim),
-
-                        ("whole-archive", Some(NativeLibKind::Static { whole_archive, .. })) => {
-                            assign_modifier(whole_archive)
-                        }
-                        ("whole-archive", _) => {
-                            sess.dcx().emit_err(errors::WholeArchiveNeedsStatic { span });
-                        }
-
-                        ("as-needed", Some(NativeLibKind::Dylib { as_needed }))
-                        | ("as-needed", Some(NativeLibKind::Framework { as_needed })) => {
-                            report_unstable_modifier!(native_link_modifiers_as_needed);
-                            assign_modifier(as_needed)
-                        }
-                        ("as-needed", _) => {
-                            sess.dcx().emit_err(errors::AsNeededCompatibility { span });
-                        }
-
-                        _ => {
-                            sess.dcx().emit_err(errors::UnknownLinkModifier { span, modifier });
-                        }
-                    }
-                }
-            }
-
-            if let Some((_, span)) = wasm_import_module {
-                if name.is_some() || kind.is_some() || modifiers.is_some() || cfg.is_some() {
-                    sess.dcx().emit_err(errors::IncompatibleWasmLink { span });
-                }
-            }
-
-            if wasm_import_module.is_some() {
-                (name, kind) = (wasm_import_module, Some(NativeLibKind::WasmImportModule));
-            }
-            let Some((name, name_span)) = name else {
-                sess.dcx().emit_err(errors::LinkRequiresName { span: m.span() });
-                continue;
-            };
-
-            // Do this outside of the loop so that `import_name_type` can be specified before `kind`.
-            if let Some((_, span)) = import_name_type {
-                if kind != Some(NativeLibKind::RawDylib) {
-                    sess.dcx().emit_err(errors::ImportNameTypeRaw { span });
-                }
-            }
-
-            let dll_imports = match kind {
-                Some(NativeLibKind::RawDylib) => {
-                    if name.as_str().contains('\0') {
-                        sess.dcx().emit_err(errors::RawDylibNoNul { span: name_span });
-                    }
-                    foreign_items
-                        .iter()
-                        .map(|&child_item| {
-                            self.build_dll_import(
-                                abi,
-                                import_name_type.map(|(import_name_type, _)| import_name_type),
-                                child_item,
-                            )
-                        })
-                        .collect()
-                }
+        for attr in
+            find_attr!(self.tcx.get_all_attrs(def_id), AttributeKind::Link(links, _) => links)
+                .iter()
+                .map(|v| v.iter())
+                .flatten()
+        {
+            let dll_imports = match attr.kind {
+                NativeLibKind::RawDylib => foreign_items
+                    .iter()
+                    .map(|&child_item| {
+                        self.build_dll_import(
+                            abi,
+                            attr.import_name_type.map(|(import_name_type, _)| import_name_type),
+                            child_item,
+                        )
+                    })
+                    .collect(),
                 _ => {
                     for &child_item in foreign_items {
                         if let Some(span) = find_attr!(self.tcx.get_all_attrs(child_item), AttributeKind::LinkOrdinal {span, ..} => *span)
@@ -508,15 +240,20 @@ impl<'tcx> Collector<'tcx> {
                 }
             };
 
-            let kind = kind.unwrap_or(NativeLibKind::Unspecified);
-            let filename = find_bundled_library(name, verbatim, kind, cfg.is_some(), self.tcx);
+            let filename = find_bundled_library(
+                attr.name,
+                attr.verbatim,
+                attr.kind,
+                attr.cfg.is_some(),
+                self.tcx,
+            );
             self.libs.push(NativeLib {
-                name,
+                name: attr.name,
                 filename,
-                kind,
-                cfg,
+                kind: attr.kind,
+                cfg: attr.cfg.clone(),
                 foreign_module: Some(def_id.to_def_id()),
-                verbatim,
+                verbatim: attr.verbatim,
                 dll_imports,
             });
         }
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index fbcce16cedc..782066981c9 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
-bitflags = "2.4.1"
+bitflags.workspace = true
 either = "1.5.0"
 gsgdt = "0.1.2"
 polonius-engine = "0.13.0"
@@ -34,8 +34,8 @@ rustc_target = { path = "../rustc_target" }
 rustc_thread_pool = { path = "../rustc_thread_pool" }
 rustc_type_ir = { path = "../rustc_type_ir" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.12"
-tracing = "0.1"
+thin-vec.workspace = true
+tracing.workspace = true
 # tidy-alphabetical-end
 
 [features]
diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
index 78cafe8566b..866736f74a0 100644
--- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
+++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs
@@ -2,7 +2,6 @@ use std::borrow::Cow;
 
 use rustc_abi::Align;
 use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, Linkage, OptimizeAttr};
-use rustc_hir::def_id::DefId;
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
 use rustc_span::Symbol;
 use rustc_target::spec::SanitizerSet;
@@ -161,6 +160,8 @@ bitflags::bitflags! {
         const ALLOCATOR_ZEROED          = 1 << 14;
         /// `#[no_builtins]`: indicates that disable implicit builtin knowledge of functions for the function.
         const NO_BUILTINS               = 1 << 15;
+        /// Marks foreign items, to make `contains_extern_indicator` cheaper.
+        const FOREIGN_ITEM              = 1 << 16;
     }
 }
 rustc_data_structures::external_bitflags_debug! { CodegenFnAttrFlags }
@@ -194,8 +195,8 @@ impl CodegenFnAttrs {
     /// * `#[linkage]` is present
     ///
     /// Keep this in sync with the logic for the unused_attributes for `#[inline]` lint.
-    pub fn contains_extern_indicator(&self, tcx: TyCtxt<'_>, did: DefId) -> bool {
-        if tcx.is_foreign_item(did) {
+    pub fn contains_extern_indicator(&self) -> bool {
+        if self.flags.contains(CodegenFnAttrFlags::FOREIGN_ITEM) {
             return false;
         }
 
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
index ea8596ea286..dbbd95408c8 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation/provenance_map.rs
@@ -120,6 +120,17 @@ impl<Prov: Provenance> ProvenanceMap<Prov> {
         }
     }
 
+    /// Gets the provenances of all bytes (including from pointers) in a range.
+    pub fn get_range(
+        &self,
+        cx: &impl HasDataLayout,
+        range: AllocRange,
+    ) -> impl Iterator<Item = Prov> {
+        let ptr_provs = self.range_ptrs_get(range, cx).iter().map(|(_, p)| *p);
+        let byte_provs = self.range_bytes_get(range).iter().map(|(_, (p, _))| *p);
+        ptr_provs.chain(byte_provs)
+    }
+
     /// Attempt to merge per-byte provenance back into ptr chunks, if the right fragments
     /// sit next to each other. Return `false` is that is not possible due to partial pointers.
     pub fn merge_bytes(&mut self, cx: &impl HasDataLayout) -> bool {
diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs
index 533066bdef9..6b45b2dc3ff 100644
--- a/compiler/rustc_middle/src/mir/mono.rs
+++ b/compiler/rustc_middle/src/mir/mono.rs
@@ -149,7 +149,7 @@ impl<'tcx> MonoItem<'tcx> {
         // instantiation:
         // We emit an unused_attributes lint for this case, which should be kept in sync if possible.
         let codegen_fn_attrs = tcx.codegen_instance_attrs(instance.def);
-        if codegen_fn_attrs.contains_extern_indicator(tcx, instance.def.def_id())
+        if codegen_fn_attrs.contains_extern_indicator()
             || codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED)
         {
             return InstantiationMode::GloballyShared { may_conflict: false };
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index a8a95c699d8..466b9c7a3c2 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -149,8 +149,15 @@ pub enum ConstraintCategory<'tcx> {
     /// A constraint that doesn't correspond to anything the user sees.
     Internal,
 
-    /// An internal constraint derived from an illegal universe relation.
-    IllegalUniverse,
+    /// An internal constraint added when a region outlives a placeholder
+    /// it cannot name and therefore has to outlive `'static`. The argument
+    /// is the unnameable placeholder and the constraint is always between
+    /// an SCC representative and `'static`.
+    OutlivesUnnameablePlaceholder(
+        #[type_foldable(identity)]
+        #[type_visitable(ignore)]
+        ty::RegionVid,
+    ),
 }
 
 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 6039a03aa29..3b8def67f92 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -1371,12 +1371,7 @@ pub enum Rvalue<'tcx> {
 
     /// Creates an array where each element is the value of the operand.
     ///
-    /// This is the cause of a bug in the case where the repetition count is zero because the value
-    /// is not dropped, see [#74836].
-    ///
     /// Corresponds to source code like `[x; 32]`.
-    ///
-    /// [#74836]: https://github.com/rust-lang/rust/issues/74836
     Repeat(Operand<'tcx>, ty::Const<'tcx>),
 
     /// Creates a reference of the indicated kind to the place.
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index d4f88c458a8..7bd8a0525a2 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -696,6 +696,22 @@ rustc_queries! {
         return_result_from_ensure_ok
     }
 
+    /// Used in case `mir_borrowck` fails to prove an obligation. We generally assume that
+    /// all goals we prove in MIR type check hold as we've already checked them in HIR typeck.
+    ///
+    /// However, we replace each free region in the MIR body with a unique region inference
+    /// variable. As we may rely on structural identity when proving goals this may cause a
+    /// goal to no longer hold. We store obligations for which this may happen during HIR
+    /// typeck in the `TypeckResults`. We then uniquify and reprove them in case MIR typeck
+    /// encounters an unexpected error. We expect this to result in an error when used and
+    /// delay a bug if it does not.
+    query check_potentially_region_dependent_goals(key: LocalDefId) -> Result<(), ErrorGuaranteed> {
+        desc {
+            |tcx| "reproving potentially region dependent HIR typeck goals for `{}",
+            tcx.def_path_str(key)
+        }
+    }
+
     /// MIR after our optimization passes have run. This is MIR that is ready
     /// for codegen. This is also the only query that can fetch non-local MIR, at present.
     query optimized_mir(key: DefId) -> &'tcx mir::Body<'tcx> {
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 49a4733de3b..4990a85466e 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -33,7 +33,7 @@ use rustc_errors::{
     Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, LintDiagnostic, LintEmitter, MultiSpan,
 };
 use rustc_hir::attrs::AttributeKind;
-use rustc_hir::def::{CtorKind, DefKind};
+use rustc_hir::def::{CtorKind, CtorOf, DefKind};
 use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
 use rustc_hir::definitions::{DefPathData, Definitions, DisambiguatorState};
 use rustc_hir::intravisit::VisitorExt;
@@ -445,7 +445,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
     }
 
     fn fn_is_const(self, def_id: DefId) -> bool {
-        debug_assert_matches!(self.def_kind(def_id), DefKind::Fn | DefKind::AssocFn);
+        debug_assert_matches!(
+            self.def_kind(def_id),
+            DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(CtorOf::Struct, CtorKind::Fn)
+        );
         self.is_conditionally_const(def_id)
     }
 
@@ -1418,6 +1421,8 @@ pub struct TyCtxt<'tcx> {
 }
 
 impl<'tcx> LintEmitter for TyCtxt<'tcx> {
+    type Id = HirId;
+
     fn emit_node_span_lint(
         self,
         lint: &'static Lint,
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index a7298af502e..e567ba05f61 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -829,14 +829,15 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
         // Convert the type from the function into a type valid outside by mapping generic
         // parameters to into the context of the opaque.
         //
-        // We erase regions when doing this during HIR typeck.
+        // We erase regions when doing this during HIR typeck. We manually use `fold_regions`
+        // here as we do not want to anonymize bound variables.
         let this = match defining_scope_kind {
-            DefiningScopeKind::HirTypeck => tcx.erase_regions(self),
+            DefiningScopeKind::HirTypeck => fold_regions(tcx, self, |_, _| tcx.lifetimes.re_erased),
             DefiningScopeKind::MirBorrowck => self,
         };
         let result = this.fold_with(&mut opaque_types::ReverseMapper::new(tcx, map, self.span));
         if cfg!(debug_assertions) && matches!(defining_scope_kind, DefiningScopeKind::HirTypeck) {
-            assert_eq!(result.ty, tcx.erase_regions(result.ty));
+            assert_eq!(result.ty, fold_regions(tcx, result.ty, |_, _| tcx.lifetimes.re_erased));
         }
         result
     }
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index 59e2b2a034d..4e38d969192 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -6,6 +6,7 @@ use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE};
 use rustc_macros::{Decodable, Encodable, HashStable};
+use rustc_span::symbol::sym;
 use tracing::debug;
 
 use crate::query::LocalCrate;
@@ -239,6 +240,12 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
 
 /// Query provider for `incoherent_impls`.
 pub(super) fn incoherent_impls_provider(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] {
+    if let Some(def_id) = simp.def()
+        && !tcx.has_attr(def_id, sym::rustc_has_incoherent_inherent_impls)
+    {
+        return &[];
+    }
+
     let mut impls = Vec::new();
     for cnum in iter::once(LOCAL_CRATE).chain(tcx.crates(()).iter().copied()) {
         for &impl_def_id in tcx.crate_incoherent_impls((cnum, simp)) {
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index f42dbbd2ac3..8dd80aab946 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -206,6 +206,16 @@ pub struct TypeckResults<'tcx> {
     /// formatting modified file tests/ui/coroutine/retain-resume-ref.rs
     pub coroutine_stalled_predicates: FxIndexSet<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>,
 
+    /// Goals proven during HIR typeck which may be potentially region dependent.
+    ///
+    /// Borrowck *uniquifies* regions which may cause these goal to be ambiguous in MIR
+    /// type check. We ICE if goals fail in borrowck to detect bugs during MIR building or
+    /// missed checks in HIR typeck. To avoid ICE due to region dependence we store all
+    /// goals which may be region dependent and reprove them in case borrowck encounters
+    /// an error.
+    pub potentially_region_dependent_goals:
+        FxIndexSet<(ty::Predicate<'tcx>, ObligationCause<'tcx>)>,
+
     /// Contains the data for evaluating the effect of feature `capture_disjoint_fields`
     /// on closure size.
     pub closure_size_eval: LocalDefIdMap<ClosureSizeProfileData<'tcx>>,
@@ -245,6 +255,7 @@ impl<'tcx> TypeckResults<'tcx> {
             closure_fake_reads: Default::default(),
             rvalue_scopes: Default::default(),
             coroutine_stalled_predicates: Default::default(),
+            potentially_region_dependent_goals: Default::default(),
             closure_size_eval: Default::default(),
             transmutes_to_check: Default::default(),
             offset_of_data: Default::default(),
diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml
index f756f0a19ee..c3f7fdfcb00 100644
--- a/compiler/rustc_mir_build/Cargo.toml
+++ b/compiler/rustc_mir_build/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
-itertools = "0.12"
+itertools.workspace = true
 rustc_abi = { path = "../rustc_abi" }
 rustc_apfloat = "0.2.0"
 rustc_arena = { path = "../rustc_arena" }
@@ -23,5 +23,5 @@ rustc_pattern_analysis = { path = "../rustc_pattern_analysis" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml
index 9621f9f20bd..e422f69c7ca 100644
--- a/compiler/rustc_mir_dataflow/Cargo.toml
+++ b/compiler/rustc_mir_dataflow/Cargo.toml
@@ -18,5 +18,5 @@ rustc_macros = { path = "../rustc_macros" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_span = { path = "../rustc_span" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml
index 08c43a4648c..16acec15e92 100644
--- a/compiler/rustc_mir_transform/Cargo.toml
+++ b/compiler/rustc_mir_transform/Cargo.toml
@@ -6,7 +6,7 @@ edition = "2024"
 [dependencies]
 # tidy-alphabetical-start
 either = "1"
-itertools = "0.12"
+itertools.workspace = true
 rustc_abi = { path = "../rustc_abi" }
 rustc_arena = { path = "../rustc_arena" }
 rustc_ast = { path = "../rustc_ast" }
@@ -26,5 +26,5 @@ rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
diff --git a/compiler/rustc_mir_transform/src/check_enums.rs b/compiler/rustc_mir_transform/src/check_enums.rs
index 33a87cb9873..12447dc7cbb 100644
--- a/compiler/rustc_mir_transform/src/check_enums.rs
+++ b/compiler/rustc_mir_transform/src/check_enums.rs
@@ -48,6 +48,21 @@ impl<'tcx> crate::MirPass<'tcx> for CheckEnums {
                     let new_block = split_block(basic_blocks, location);
 
                     match check {
+                        EnumCheckType::Direct { op_size, .. }
+                        | EnumCheckType::WithNiche { op_size, .. }
+                            if op_size.bytes() == 0 =>
+                        {
+                            // It is never valid to use a ZST as a discriminant for an inhabited enum, but that will
+                            // have been caught by the type checker. Do nothing but ensure that a bug has been signaled.
+                            tcx.dcx().span_delayed_bug(
+                                source_info.span,
+                                "cannot build enum discriminant from zero-sized type",
+                            );
+                            basic_blocks[block].terminator = Some(Terminator {
+                                source_info,
+                                kind: TerminatorKind::Goto { target: new_block },
+                            });
+                        }
                         EnumCheckType::Direct { source_op, discr, op_size, valid_discrs } => {
                             insert_direct_enum_check(
                                 tcx,
diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs
index 03fdf9fbac5..b186c2bd775 100644
--- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs
+++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs
@@ -18,7 +18,7 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
     let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id);
     // If this has an extern indicator, then this function is globally shared and thus will not
     // generate cgu-internal copies which would make it cross-crate inlinable.
-    if codegen_fn_attrs.contains_extern_indicator(tcx, def_id.into()) {
+    if codegen_fn_attrs.contains_extern_indicator() {
         return false;
     }
 
diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml
index 09a55f0b5f8..b11084cf169 100644
--- a/compiler/rustc_monomorphize/Cargo.toml
+++ b/compiler/rustc_monomorphize/Cargo.toml
@@ -17,5 +17,5 @@ rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 serde = "1"
 serde_json = "1"
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
diff --git a/compiler/rustc_next_trait_solver/Cargo.toml b/compiler/rustc_next_trait_solver/Cargo.toml
index 05bcabad02f..8b66f30cf0e 100644
--- a/compiler/rustc_next_trait_solver/Cargo.toml
+++ b/compiler/rustc_next_trait_solver/Cargo.toml
@@ -11,7 +11,7 @@ rustc_index = { path = "../rustc_index", default-features = false }
 rustc_macros = { path = "../rustc_macros", optional = true }
 rustc_type_ir = { path = "../rustc_type_ir", default-features = false }
 rustc_type_ir_macros = { path = "../rustc_type_ir_macros" }
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
 
 [features]
diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
index 3e1f48610ff..da05c49756f 100644
--- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs
+++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs
@@ -25,12 +25,8 @@ enum CanonicalizeInputKind {
     /// trait candidates relies on it when deciding whether a where-bound
     /// is trivial.
     ParamEnv,
-    /// When canonicalizing predicates, we don't keep `'static`. If we're
-    /// currently outside of the trait solver and canonicalize the root goal
-    /// during HIR typeck, we replace each occurrence of a region with a
-    /// unique region variable. See the comment on `InferCtxt::in_hir_typeck`
-    /// for more details.
-    Predicate { is_hir_typeck_root_goal: bool },
+    /// When canonicalizing predicates, we don't keep `'static`.
+    Predicate,
 }
 
 /// Whether we're canonicalizing a query input or the query response.
@@ -191,7 +187,6 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
     pub fn canonicalize_input<P: TypeFoldable<I>>(
         delegate: &'a D,
         variables: &'a mut Vec<I::GenericArg>,
-        is_hir_typeck_root_goal: bool,
         input: QueryInput<I, P>,
     ) -> ty::Canonical<I, QueryInput<I, P>> {
         // First canonicalize the `param_env` while keeping `'static`
@@ -201,9 +196,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
         // while *mostly* reusing the canonicalizer from above.
         let mut rest_canonicalizer = Canonicalizer {
             delegate,
-            canonicalize_mode: CanonicalizeMode::Input(CanonicalizeInputKind::Predicate {
-                is_hir_typeck_root_goal,
-            }),
+            canonicalize_mode: CanonicalizeMode::Input(CanonicalizeInputKind::Predicate),
 
             variables,
             variable_lookup_table,
@@ -481,31 +474,13 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
             }
         };
 
-        let var = if let CanonicalizeMode::Input(CanonicalizeInputKind::Predicate {
-            is_hir_typeck_root_goal: true,
-        }) = self.canonicalize_mode
-        {
-            let var = ty::BoundVar::from(self.variables.len());
-            self.variables.push(r.into());
-            self.var_kinds.push(kind);
-            var
-        } else {
-            self.get_or_insert_bound_var(r, kind)
-        };
+        let var = self.get_or_insert_bound_var(r, kind);
 
         Region::new_anon_bound(self.cx(), self.binder_index, var)
     }
 
     fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
-        if let CanonicalizeMode::Input(CanonicalizeInputKind::Predicate {
-            is_hir_typeck_root_goal: true,
-        }) = self.canonicalize_mode
-        {
-            // If we're canonicalizing a root goal during HIR typeck, we
-            // must not use the `cache` as we want to map each occurrence
-            // of a region to a unique existential variable.
-            self.inner_fold_ty(t)
-        } else if let Some(&ty) = self.cache.get(&(self.binder_index, t)) {
+        if let Some(&ty) = self.cache.get(&(self.binder_index, t)) {
             ty
         } else {
             let res = self.inner_fold_ty(t);
diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
index 9a22bf58c03..b7ae9994c62 100644
--- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs
@@ -6,7 +6,7 @@ use rustc_type_ir::inherent::*;
 use rustc_type_ir::lang_items::TraitSolverLangItem;
 use rustc_type_ir::solve::SizedTraitKind;
 use rustc_type_ir::solve::inspect::ProbeKind;
-use rustc_type_ir::{self as ty, Interner, elaborate};
+use rustc_type_ir::{self as ty, Interner, TypingMode, elaborate};
 use tracing::instrument;
 
 use super::assembly::{Candidate, structural_traits};
@@ -135,12 +135,16 @@ where
         }
 
         let impl_polarity = cx.impl_polarity(impl_def_id);
-        match impl_polarity {
+        let certainty = match impl_polarity {
             ty::ImplPolarity::Negative => return Err(NoSolution),
-            ty::ImplPolarity::Reservation => {
-                unimplemented!("reservation impl for const trait: {:?}", goal)
-            }
-            ty::ImplPolarity::Positive => {}
+            ty::ImplPolarity::Reservation => match ecx.typing_mode() {
+                TypingMode::Coherence => Certainty::AMBIGUOUS,
+                TypingMode::Analysis { .. }
+                | TypingMode::Borrowck { .. }
+                | TypingMode::PostBorrowckAnalysis { .. }
+                | TypingMode::PostAnalysis => return Err(NoSolution),
+            },
+            ty::ImplPolarity::Positive => Certainty::Yes,
         };
 
         if !cx.impl_is_const(impl_def_id) {
@@ -171,7 +175,7 @@ where
                 });
             ecx.add_goals(GoalSource::ImplWhereBound, const_conditions);
 
-            ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
+            ecx.evaluate_added_goals_and_make_canonical_response(certainty)
         })
     }
 
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 74c5b49ea92..4644b145b18 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
@@ -57,7 +57,6 @@ where
     /// This expects `goal` and `opaque_types` to be eager resolved.
     pub(super) fn canonicalize_goal(
         &self,
-        is_hir_typeck_root_goal: bool,
         goal: Goal<I, I::Predicate>,
         opaque_types: Vec<(ty::OpaqueTypeKey<I>, I::Ty)>,
     ) -> (Vec<I::GenericArg>, CanonicalInput<I, I::Predicate>) {
@@ -65,7 +64,6 @@ where
         let canonical = Canonicalizer::canonicalize_input(
             self.delegate,
             &mut orig_values,
-            is_hir_typeck_root_goal,
             QueryInput {
                 goal,
                 predefined_opaques_in_body: self
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
index a4738306181..4f87902e46e 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
@@ -4,7 +4,6 @@ use std::ops::ControlFlow;
 #[cfg(feature = "nightly")]
 use rustc_macros::HashStable_NoContext;
 use rustc_type_ir::data_structures::{HashMap, HashSet};
-use rustc_type_ir::fast_reject::DeepRejectCtxt;
 use rustc_type_ir::inherent::*;
 use rustc_type_ir::relate::Relate;
 use rustc_type_ir::relate::solver_relating::RelateExt;
@@ -459,10 +458,7 @@ where
         let opaque_types = self.delegate.clone_opaque_types_lookup_table();
         let (goal, opaque_types) = eager_resolve_vars(self.delegate, (goal, opaque_types));
 
-        let is_hir_typeck_root_goal = matches!(goal_evaluation_kind, GoalEvaluationKind::Root)
-            && self.delegate.in_hir_typeck();
-        let (orig_values, canonical_goal) =
-            self.canonicalize_goal(is_hir_typeck_root_goal, goal, opaque_types);
+        let (orig_values, canonical_goal) = self.canonicalize_goal(goal, opaque_types);
         let mut goal_evaluation =
             self.inspect.new_goal_evaluation(goal, &orig_values, goal_evaluation_kind);
         let canonical_result = self.search_graph.evaluate_goal(
@@ -1131,6 +1127,7 @@ where
         self.delegate.fetch_eligible_assoc_item(goal_trait_ref, trait_assoc_def_id, impl_def_id)
     }
 
+    #[instrument(level = "debug", skip(self), ret)]
     pub(super) fn register_hidden_type_in_storage(
         &mut self,
         opaque_type_key: ty::OpaqueTypeKey<I>,
@@ -1157,29 +1154,6 @@ where
         self.add_goals(GoalSource::AliasWellFormed, goals);
     }
 
-    // Do something for each opaque/hidden pair defined with `def_id` in the
-    // current inference context.
-    pub(super) fn probe_existing_opaque_ty(
-        &mut self,
-        key: ty::OpaqueTypeKey<I>,
-    ) -> Option<(ty::OpaqueTypeKey<I>, I::Ty)> {
-        // We shouldn't have any duplicate entries when using
-        // this function during `TypingMode::Analysis`.
-        let duplicate_entries = self.delegate.clone_duplicate_opaque_types();
-        assert!(duplicate_entries.is_empty(), "unexpected duplicates: {duplicate_entries:?}");
-        let mut matching = self.delegate.clone_opaque_types_lookup_table().into_iter().filter(
-            |(candidate_key, _)| {
-                candidate_key.def_id == key.def_id
-                    && DeepRejectCtxt::relate_rigid_rigid(self.cx())
-                        .args_may_unify(candidate_key.args, key.args)
-            },
-        );
-        let first = matching.next();
-        let second = matching.next();
-        assert_eq!(second, None);
-        first
-    }
-
     // Try to evaluate a const, or return `None` if the const is too generic.
     // This doesn't mean the const isn't evaluatable, though, and should be treated
     // as an ambiguity rather than no-solution.
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
index df3ad1e468b..a5f857a1dd8 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs
@@ -1,13 +1,12 @@
 //! Computes a normalizes-to (projection) goal for opaque types. This goal
 //! behaves differently depending on the current `TypingMode`.
 
-use rustc_index::bit_set::GrowableBitSet;
 use rustc_type_ir::inherent::*;
 use rustc_type_ir::solve::GoalSource;
 use rustc_type_ir::{self as ty, Interner, TypingMode, fold_regions};
 
 use crate::delegate::SolverDelegate;
-use crate::solve::{Certainty, EvalCtxt, Goal, NoSolution, QueryResult, inspect};
+use crate::solve::{Certainty, EvalCtxt, Goal, QueryResult};
 
 impl<D, I> EvalCtxt<'_, D>
 where
@@ -39,100 +38,68 @@ where
                 self.add_goal(GoalSource::Misc, goal.with(cx, ty::PredicateKind::Ambiguous));
                 self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
             }
-            TypingMode::Analysis { defining_opaque_types_and_generators } => {
+            TypingMode::Analysis {
+                defining_opaque_types_and_generators: defining_opaque_types,
+            }
+            | TypingMode::Borrowck { defining_opaque_types } => {
                 let Some(def_id) = opaque_ty
                     .def_id
                     .as_local()
-                    .filter(|&def_id| defining_opaque_types_and_generators.contains(&def_id))
+                    .filter(|&def_id| defining_opaque_types.contains(&def_id))
                 else {
+                    // If we're not in the defining scope, treat the alias as rigid.
                     self.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
                     return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
                 };
 
-                // FIXME: This may have issues when the args contain aliases...
-                match uses_unique_placeholders_ignoring_regions(self.cx(), opaque_ty.args) {
-                    Err(NotUniqueParam::NotParam(param)) if param.is_non_region_infer() => {
-                        return self.evaluate_added_goals_and_make_canonical_response(
-                            Certainty::AMBIGUOUS,
-                        );
-                    }
-                    Err(_) => {
-                        return Err(NoSolution);
-                    }
-                    Ok(()) => {}
-                }
-                // Prefer opaques registered already.
-                let opaque_type_key = ty::OpaqueTypeKey { def_id, args: opaque_ty.args };
-                // FIXME: This also unifies the previous hidden type with the expected.
+                // We structurally normalize the args so that we're able to detect defining uses
+                // later on.
                 //
-                // If that fails, we insert `expected` as a new hidden type instead of
-                // eagerly emitting an error.
-                let existing = self.probe_existing_opaque_ty(opaque_type_key);
-                if let Some((candidate_key, candidate_ty)) = existing {
-                    return self
-                        .probe(|result| inspect::ProbeKind::OpaqueTypeStorageLookup {
-                            result: *result,
-                        })
-                        .enter(|ecx| {
-                            for (a, b) in std::iter::zip(
-                                candidate_key.args.iter(),
-                                opaque_type_key.args.iter(),
-                            ) {
-                                ecx.eq(goal.param_env, a, b)?;
-                            }
-                            ecx.eq(goal.param_env, candidate_ty, expected)?;
-                            ecx.add_item_bounds_for_hidden_type(
-                                def_id.into(),
-                                candidate_key.args,
-                                goal.param_env,
-                                candidate_ty,
-                            );
-                            ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
-                        });
-                }
+                // This reduces the amount of duplicate definitions in the `opaque_type_storage` and
+                // strengthens inference. This causes us to subtly depend on the normalization behavior
+                // when inferring the hidden type of opaques.
+                //
+                // E.g. it's observable that we don't normalize nested aliases with bound vars in
+                // `structurally_normalize` and because we use structural lookup, we also don't
+                // reuse an entry for `Tait<for<'a> fn(&'a ())>` for `Tait<for<'b> fn(&'b ())>`.
+                let normalized_args =
+                    cx.mk_args_from_iter(opaque_ty.args.iter().map(|arg| match arg.kind() {
+                        ty::GenericArgKind::Lifetime(lt) => Ok(lt.into()),
+                        ty::GenericArgKind::Type(ty) => {
+                            self.structurally_normalize_ty(goal.param_env, ty).map(Into::into)
+                        }
+                        ty::GenericArgKind::Const(ct) => {
+                            self.structurally_normalize_const(goal.param_env, ct).map(Into::into)
+                        }
+                    }))?;
 
-                // Otherwise, define a new opaque type
-                let prev = self.register_hidden_type_in_storage(opaque_type_key, expected);
-                assert_eq!(prev, None);
-                self.add_item_bounds_for_hidden_type(
-                    def_id.into(),
-                    opaque_ty.args,
-                    goal.param_env,
-                    expected,
-                );
-                self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
-            }
-            // Very similar to `TypingMode::Analysis` with some notably differences:
-            // - we accept opaque types even if they have non-universal arguments
-            // - we do a structural lookup instead of semantically unifying regions
-            // - the hidden type starts out as the type from HIR typeck with fresh region
-            //   variables instead of a fully unconstrained inference variable
-            TypingMode::Borrowck { defining_opaque_types } => {
-                let Some(def_id) = opaque_ty
-                    .def_id
-                    .as_local()
-                    .filter(|&def_id| defining_opaque_types.contains(&def_id))
-                else {
-                    self.structurally_instantiate_normalizes_to_term(goal, goal.predicate.alias);
-                    return self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
-                };
+                let opaque_type_key = ty::OpaqueTypeKey { def_id, args: normalized_args };
+                if let Some(prev) = self.register_hidden_type_in_storage(opaque_type_key, expected)
+                {
+                    self.eq(goal.param_env, expected, prev)?;
+                } else {
+                    // During HIR typeck, opaque types start out as unconstrained
+                    // inference variables. In borrowck we instead use the type
+                    // computed in HIR typeck as the initial value.
+                    match self.typing_mode() {
+                        TypingMode::Analysis { .. } => {}
+                        TypingMode::Borrowck { .. } => {
+                            let actual = cx
+                                .type_of_opaque_hir_typeck(def_id)
+                                .instantiate(cx, opaque_ty.args);
+                            let actual = fold_regions(cx, actual, |re, _dbi| match re.kind() {
+                                ty::ReErased => self.next_region_var(),
+                                _ => re,
+                            });
+                            self.eq(goal.param_env, expected, actual)?;
+                        }
+                        _ => unreachable!(),
+                    }
+                }
 
-                let opaque_type_key = ty::OpaqueTypeKey { def_id, args: opaque_ty.args };
-                let actual = self
-                    .register_hidden_type_in_storage(opaque_type_key, expected)
-                    .unwrap_or_else(|| {
-                        let actual =
-                            cx.type_of_opaque_hir_typeck(def_id).instantiate(cx, opaque_ty.args);
-                        let actual = fold_regions(cx, actual, |re, _dbi| match re.kind() {
-                            ty::ReErased => self.next_region_var(),
-                            _ => re,
-                        });
-                        actual
-                    });
-                self.eq(goal.param_env, expected, actual)?;
                 self.add_item_bounds_for_hidden_type(
                     def_id.into(),
-                    opaque_ty.args,
+                    normalized_args,
                     goal.param_env,
                     expected,
                 );
@@ -168,44 +135,3 @@ where
         }
     }
 }
-
-/// Checks whether each generic argument is simply a unique generic placeholder.
-///
-/// FIXME: Interner argument is needed to constrain the `I` parameter.
-fn uses_unique_placeholders_ignoring_regions<I: Interner>(
-    _cx: I,
-    args: I::GenericArgs,
-) -> Result<(), NotUniqueParam<I>> {
-    let mut seen = GrowableBitSet::default();
-    for arg in args.iter() {
-        match arg.kind() {
-            // Ignore regions, since we can't resolve those in a canonicalized
-            // query in the trait solver.
-            ty::GenericArgKind::Lifetime(_) => {}
-            ty::GenericArgKind::Type(t) => match t.kind() {
-                ty::Placeholder(p) => {
-                    if !seen.insert(p.var()) {
-                        return Err(NotUniqueParam::DuplicateParam(t.into()));
-                    }
-                }
-                _ => return Err(NotUniqueParam::NotParam(t.into())),
-            },
-            ty::GenericArgKind::Const(c) => match c.kind() {
-                ty::ConstKind::Placeholder(p) => {
-                    if !seen.insert(p.var()) {
-                        return Err(NotUniqueParam::DuplicateParam(c.into()));
-                    }
-                }
-                _ => return Err(NotUniqueParam::NotParam(c.into())),
-            },
-        }
-    }
-
-    Ok(())
-}
-
-// FIXME: This should check for dupes and non-params first, then infer vars.
-enum NotUniqueParam<I: Interner> {
-    DuplicateParam(I::GenericArg),
-    NotParam(I::GenericArg),
-}
diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml
index 6d738a10371..7cb4ae7ff5f 100644
--- a/compiler/rustc_parse/Cargo.toml
+++ b/compiler/rustc_parse/Cargo.toml
@@ -5,8 +5,8 @@ edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
-bitflags = "2.4.1"
-rustc-literal-escaper = "0.0.5"
+bitflags.workspace = true
+rustc-literal-escaper.workspace = true
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_data_structures = { path = "../rustc_data_structures" }
@@ -18,8 +18,8 @@ rustc_lexer = { path = "../rustc_lexer" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
-thin-vec = "0.2.12"
-tracing = "0.1"
+thin-vec.workspace = true
+tracing.workspace = true
 unicode-normalization = "0.1.11"
 unicode-width = "0.2.0"
 # tidy-alphabetical-end
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 220e4ac18fc..a28af7833c3 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -463,8 +463,8 @@ impl<'a> Parser<'a> {
 
     pub(super) fn expected_one_of_not_found(
         &mut self,
-        edible: &[ExpTokenPair<'_>],
-        inedible: &[ExpTokenPair<'_>],
+        edible: &[ExpTokenPair],
+        inedible: &[ExpTokenPair],
     ) -> PResult<'a, ErrorGuaranteed> {
         debug!("expected_one_of_not_found(edible: {:?}, inedible: {:?})", edible, inedible);
         fn tokens_to_string(tokens: &[TokenType]) -> String {
@@ -1092,7 +1092,7 @@ impl<'a> Parser<'a> {
 
     /// Eats and discards tokens until one of `closes` is encountered. Respects token trees,
     /// passes through any errors encountered. Used for error recovery.
-    pub(super) fn eat_to_tokens(&mut self, closes: &[ExpTokenPair<'_>]) {
+    pub(super) fn eat_to_tokens(&mut self, closes: &[ExpTokenPair]) {
         if let Err(err) = self
             .parse_seq_to_before_tokens(closes, &[], SeqSep::none(), |p| Ok(p.parse_token_tree()))
         {
@@ -1113,7 +1113,7 @@ impl<'a> Parser<'a> {
     pub(super) fn check_trailing_angle_brackets(
         &mut self,
         segment: &PathSegment,
-        end: &[ExpTokenPair<'_>],
+        end: &[ExpTokenPair],
     ) -> Option<ErrorGuaranteed> {
         if !self.may_recover() {
             return None;
@@ -1196,7 +1196,7 @@ impl<'a> Parser<'a> {
         // second case.
         if self.look_ahead(position, |t| {
             trace!("check_trailing_angle_brackets: t={:?}", t);
-            end.iter().any(|exp| exp.tok == &t.kind)
+            end.iter().any(|exp| exp.tok == t.kind)
         }) {
             // Eat from where we started until the end token so that parsing can continue
             // as if we didn't have those extra angle brackets.
@@ -2120,8 +2120,8 @@ impl<'a> Parser<'a> {
 
     pub(super) fn recover_seq_parse_error(
         &mut self,
-        open: ExpTokenPair<'_>,
-        close: ExpTokenPair<'_>,
+        open: ExpTokenPair,
+        close: ExpTokenPair,
         lo: Span,
         err: Diag<'a>,
     ) -> Box<Expr> {
@@ -2386,8 +2386,8 @@ impl<'a> Parser<'a> {
 
     pub(super) fn consume_block(
         &mut self,
-        open: ExpTokenPair<'_>,
-        close: ExpTokenPair<'_>,
+        open: ExpTokenPair,
+        close: ExpTokenPair,
         consume_close: ConsumeClosingDelim,
     ) {
         let mut brace_depth = 0;
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 1499808966c..f0f58e901a9 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1598,7 +1598,7 @@ impl<'a> Parser<'a> {
         self.maybe_recover_from_bad_qpath(expr)
     }
 
-    fn parse_expr_array_or_repeat(&mut self, close: ExpTokenPair<'_>) -> PResult<'a, Box<Expr>> {
+    fn parse_expr_array_or_repeat(&mut self, close: ExpTokenPair) -> PResult<'a, Box<Expr>> {
         let lo = self.token.span;
         self.bump(); // `[` or other open delim
 
@@ -3661,7 +3661,7 @@ impl<'a> Parser<'a> {
         &mut self,
         pth: ast::Path,
         recover: bool,
-        close: ExpTokenPair<'_>,
+        close: ExpTokenPair,
     ) -> PResult<
         'a,
         (
@@ -3680,8 +3680,8 @@ impl<'a> Parser<'a> {
             errors::HelpUseLatestEdition::new().add_to_diag(e);
         };
 
-        while self.token != *close.tok {
-            if self.eat(exp!(DotDot)) || self.recover_struct_field_dots(close.tok) {
+        while self.token != close.tok {
+            if self.eat(exp!(DotDot)) || self.recover_struct_field_dots(&close.tok) {
                 let exp_span = self.prev_token.span;
                 // We permit `.. }` on the left-hand side of a destructuring assignment.
                 if self.check(close) {
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index fd9fb65417c..eb264f59fed 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -54,7 +54,7 @@ impl<'a> Parser<'a> {
     /// - `}` for mod items
     pub fn parse_mod(
         &mut self,
-        term: ExpTokenPair<'_>,
+        term: ExpTokenPair,
     ) -> PResult<'a, (AttrVec, ThinVec<Box<Item>>, ModSpans)> {
         let lo = self.token.span;
         let attrs = self.parse_inner_attributes()?;
@@ -1201,7 +1201,7 @@ impl<'a> Parser<'a> {
         }?;
 
         let dash = exp!(Minus);
-        if self.token != *dash.tok {
+        if self.token != dash.tok {
             return Ok(ident);
         }
 
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index d19114df812..15598f32429 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -261,19 +261,19 @@ struct CaptureState {
 
 /// A sequence separator.
 #[derive(Debug)]
-struct SeqSep<'a> {
+struct SeqSep {
     /// The separator token.
-    sep: Option<ExpTokenPair<'a>>,
+    sep: Option<ExpTokenPair>,
     /// `true` if a trailing separator is allowed.
     trailing_sep_allowed: bool,
 }
 
-impl<'a> SeqSep<'a> {
-    fn trailing_allowed(sep: ExpTokenPair<'a>) -> SeqSep<'a> {
+impl SeqSep {
+    fn trailing_allowed(sep: ExpTokenPair) -> SeqSep {
         SeqSep { sep: Some(sep), trailing_sep_allowed: true }
     }
 
-    fn none() -> SeqSep<'a> {
+    fn none() -> SeqSep {
         SeqSep { sep: None, trailing_sep_allowed: false }
     }
 }
@@ -425,13 +425,13 @@ impl<'a> Parser<'a> {
     }
 
     /// Expects and consumes the token `t`. Signals an error if the next token is not `t`.
-    pub fn expect(&mut self, exp: ExpTokenPair<'_>) -> PResult<'a, Recovered> {
+    pub fn expect(&mut self, exp: ExpTokenPair) -> PResult<'a, Recovered> {
         if self.expected_token_types.is_empty() {
-            if self.token == *exp.tok {
+            if self.token == exp.tok {
                 self.bump();
                 Ok(Recovered::No)
             } else {
-                self.unexpected_try_recover(exp.tok)
+                self.unexpected_try_recover(&exp.tok)
             }
         } else {
             self.expect_one_of(slice::from_ref(&exp), &[])
@@ -443,13 +443,13 @@ impl<'a> Parser<'a> {
     /// anything. Signal a fatal error if next token is unexpected.
     fn expect_one_of(
         &mut self,
-        edible: &[ExpTokenPair<'_>],
-        inedible: &[ExpTokenPair<'_>],
+        edible: &[ExpTokenPair],
+        inedible: &[ExpTokenPair],
     ) -> PResult<'a, Recovered> {
-        if edible.iter().any(|exp| exp.tok == &self.token.kind) {
+        if edible.iter().any(|exp| exp.tok == self.token.kind) {
             self.bump();
             Ok(Recovered::No)
-        } else if inedible.iter().any(|exp| exp.tok == &self.token.kind) {
+        } else if inedible.iter().any(|exp| exp.tok == self.token.kind) {
             // leave it in the input
             Ok(Recovered::No)
         } else if self.token != token::Eof
@@ -494,8 +494,8 @@ impl<'a> Parser<'a> {
     /// This method will automatically add `tok` to `expected_token_types` if `tok` is not
     /// encountered.
     #[inline]
-    pub fn check(&mut self, exp: ExpTokenPair<'_>) -> bool {
-        let is_present = self.token == *exp.tok;
+    pub fn check(&mut self, exp: ExpTokenPair) -> bool {
+        let is_present = self.token == exp.tok;
         if !is_present {
             self.expected_token_types.insert(exp.token_type);
         }
@@ -542,7 +542,7 @@ impl<'a> Parser<'a> {
     /// Consumes a token 'tok' if it exists. Returns whether the given token was present.
     #[inline]
     #[must_use]
-    pub fn eat(&mut self, exp: ExpTokenPair<'_>) -> bool {
+    pub fn eat(&mut self, exp: ExpTokenPair) -> bool {
         let is_present = self.check(exp);
         if is_present {
             self.bump()
@@ -745,13 +745,13 @@ impl<'a> Parser<'a> {
     /// Eats the expected token if it's present possibly breaking
     /// compound tokens like multi-character operators in process.
     /// Returns `true` if the token was eaten.
-    fn break_and_eat(&mut self, exp: ExpTokenPair<'_>) -> bool {
-        if self.token == *exp.tok {
+    fn break_and_eat(&mut self, exp: ExpTokenPair) -> bool {
+        if self.token == exp.tok {
             self.bump();
             return true;
         }
         match self.token.kind.break_two_token_op(1) {
-            Some((first, second)) if first == *exp.tok => {
+            Some((first, second)) if first == exp.tok => {
                 let first_span = self.psess.source_map().start_point(self.token.span);
                 let second_span = self.token.span.with_lo(first_span.hi());
                 self.token = Token::new(first, first_span);
@@ -826,7 +826,7 @@ impl<'a> Parser<'a> {
     /// Checks if the next token is contained within `closes`, and returns `true` if so.
     fn expect_any_with_type(
         &mut self,
-        closes_expected: &[ExpTokenPair<'_>],
+        closes_expected: &[ExpTokenPair],
         closes_not_expected: &[&TokenKind],
     ) -> bool {
         closes_expected.iter().any(|&close| self.check(close))
@@ -838,9 +838,9 @@ impl<'a> Parser<'a> {
     /// closing bracket.
     fn parse_seq_to_before_tokens<T>(
         &mut self,
-        closes_expected: &[ExpTokenPair<'_>],
+        closes_expected: &[ExpTokenPair],
         closes_not_expected: &[&TokenKind],
-        sep: SeqSep<'_>,
+        sep: SeqSep,
         mut f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
     ) -> PResult<'a, (ThinVec<T>, Trailing, Recovered)> {
         let mut first = true;
@@ -869,7 +869,7 @@ impl<'a> Parser<'a> {
                         }
                         Err(mut expect_err) => {
                             let sp = self.prev_token.span.shrink_to_hi();
-                            let token_str = pprust::token_kind_to_string(exp.tok);
+                            let token_str = pprust::token_kind_to_string(&exp.tok);
 
                             match self.current_closure.take() {
                                 Some(closure_spans) if self.token == TokenKind::Semi => {
@@ -1039,8 +1039,8 @@ impl<'a> Parser<'a> {
     /// closing bracket.
     fn parse_seq_to_before_end<T>(
         &mut self,
-        close: ExpTokenPair<'_>,
-        sep: SeqSep<'_>,
+        close: ExpTokenPair,
+        sep: SeqSep,
         f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
     ) -> PResult<'a, (ThinVec<T>, Trailing, Recovered)> {
         self.parse_seq_to_before_tokens(&[close], &[], sep, f)
@@ -1051,8 +1051,8 @@ impl<'a> Parser<'a> {
     /// closing bracket.
     fn parse_seq_to_end<T>(
         &mut self,
-        close: ExpTokenPair<'_>,
-        sep: SeqSep<'_>,
+        close: ExpTokenPair,
+        sep: SeqSep,
         f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
     ) -> PResult<'a, (ThinVec<T>, Trailing)> {
         let (val, trailing, recovered) = self.parse_seq_to_before_end(close, sep, f)?;
@@ -1070,9 +1070,9 @@ impl<'a> Parser<'a> {
     /// closing bracket.
     fn parse_unspanned_seq<T>(
         &mut self,
-        open: ExpTokenPair<'_>,
-        close: ExpTokenPair<'_>,
-        sep: SeqSep<'_>,
+        open: ExpTokenPair,
+        close: ExpTokenPair,
+        sep: SeqSep,
         f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
     ) -> PResult<'a, (ThinVec<T>, Trailing)> {
         self.expect(open)?;
@@ -1084,8 +1084,8 @@ impl<'a> Parser<'a> {
     /// closing bracket.
     fn parse_delim_comma_seq<T>(
         &mut self,
-        open: ExpTokenPair<'_>,
-        close: ExpTokenPair<'_>,
+        open: ExpTokenPair,
+        close: ExpTokenPair,
         f: impl FnMut(&mut Parser<'a>) -> PResult<'a, T>,
     ) -> PResult<'a, (ThinVec<T>, Trailing)> {
         self.parse_unspanned_seq(open, close, SeqSep::trailing_allowed(exp!(Comma)), f)
diff --git a/compiler/rustc_parse/src/parser/token_type.rs b/compiler/rustc_parse/src/parser/token_type.rs
index b91548196a3..bd4bb368df0 100644
--- a/compiler/rustc_parse/src/parser/token_type.rs
+++ b/compiler/rustc_parse/src/parser/token_type.rs
@@ -416,8 +416,8 @@ impl TokenType {
 /// is always by used those methods. The second field is only used when the
 /// first field doesn't match.
 #[derive(Clone, Copy, Debug)]
-pub struct ExpTokenPair<'a> {
-    pub tok: &'a TokenKind,
+pub struct ExpTokenPair {
+    pub tok: TokenKind,
     pub token_type: TokenType,
 }
 
@@ -444,7 +444,7 @@ macro_rules! exp {
     // `ExpTokenPair` helper rules.
     (@tok, $tok:ident) => {
         $crate::parser::token_type::ExpTokenPair {
-            tok: &rustc_ast::token::$tok,
+            tok: rustc_ast::token::$tok,
             token_type: $crate::parser::token_type::TokenType::$tok
         }
     };
diff --git a/compiler/rustc_parse_format/Cargo.toml b/compiler/rustc_parse_format/Cargo.toml
index d178fcda1fb..645e34b6e32 100644
--- a/compiler/rustc_parse_format/Cargo.toml
+++ b/compiler/rustc_parse_format/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
-rustc-literal-escaper = "0.0.5"
+rustc-literal-escaper.workspace = true
 rustc_lexer = { path = "../rustc_lexer" }
 # tidy-alphabetical-end
 
diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml
index ba81ef3103b..c74608a6146 100644
--- a/compiler/rustc_passes/Cargo.toml
+++ b/compiler/rustc_passes/Cargo.toml
@@ -24,5 +24,5 @@ rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl
index 00a41e31a02..3be06a3704c 100644
--- a/compiler/rustc_passes/messages.ftl
+++ b/compiler/rustc_passes/messages.ftl
@@ -462,8 +462,10 @@ passes_object_lifetime_err =
     {$repr}
 
 passes_outer_crate_level_attr =
-    crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+    crate-level attribute should be an inner attribute
 
+passes_outer_crate_level_attr_suggestion =
+    add a `!`
 
 passes_panic_unwind_without_std =
     unwinding panics are not supported without std
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 077afd6dd23..c47b488465b 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -18,7 +18,7 @@ use rustc_feature::{
     ACCEPTED_LANG_FEATURES, AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP,
     BuiltinAttribute,
 };
-use rustc_hir::attrs::{AttributeKind, InlineAttr, MirDialect, MirPhase, ReprAttr};
+use rustc_hir::attrs::{AttributeKind, InlineAttr, MirDialect, MirPhase, ReprAttr, SanitizerSet};
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalModDefId;
 use rustc_hir::intravisit::{self, Visitor};
@@ -197,6 +197,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                 &Attribute::Parsed(AttributeKind::CustomMir(dialect, phase, attr_span)) => {
                     self.check_custom_mir(dialect, phase, attr_span)
                 }
+                &Attribute::Parsed(AttributeKind::Sanitize { on_set, off_set, span: attr_span}) => {
+                    self.check_sanitize(attr_span, on_set | off_set, span, target);
+                },
+                Attribute::Parsed(AttributeKind::Link(_, attr_span)) => {
+                    self.check_link(hir_id, *attr_span, span, target)
+                }
                 Attribute::Parsed(
                     AttributeKind::BodyStability { .. }
                     | AttributeKind::ConstStabilityIndirect
@@ -247,7 +253,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                     | AttributeKind::ShouldPanic { .. }
                     | AttributeKind::Coroutine(..)
                     | AttributeKind::Linkage(..)
-                    | AttributeKind::MustUse { .. },
+                    | AttributeKind::MustUse { .. }
+                    | AttributeKind::CrateName { .. }
                 ) => { /* do nothing  */ }
                 Attribute::Unparsed(attr_item) => {
                     style = Some(attr_item.style);
@@ -258,9 +265,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                         [sym::diagnostic, sym::on_unimplemented, ..] => {
                             self.check_diagnostic_on_unimplemented(attr.span(), hir_id, target)
                         }
-                        [sym::sanitize, ..] => {
-                            self.check_sanitize(attr, span, target)
-                        }
                         [sym::thread_local, ..] => self.check_thread_local(attr, span, target),
                         [sym::doc, ..] => self.check_doc_attrs(
                             attr,
@@ -304,7 +308,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                         [sym::rustc_has_incoherent_inherent_impls, ..] => {
                             self.check_has_incoherent_inherent_impls(attr, span, target)
                         }
-                        [sym::link, ..] => self.check_link(hir_id, attr, span, target),
                         [sym::macro_export, ..] => self.check_macro_export(hir_id, attr, target),
                         [sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => {
                             self.check_autodiff(hir_id, attr, span, target)
@@ -367,22 +370,46 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
             let builtin = attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name));
 
             if hir_id != CRATE_HIR_ID {
-                if let Some(BuiltinAttribute { type_: AttributeType::CrateLevel, .. }) =
-                    attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name))
-                {
-                    match style {
-                        Some(ast::AttrStyle::Outer) => self.tcx.emit_node_span_lint(
-                            UNUSED_ATTRIBUTES,
-                            hir_id,
-                            attr.span(),
-                            errors::OuterCrateLevelAttr,
-                        ),
-                        Some(ast::AttrStyle::Inner) | None => self.tcx.emit_node_span_lint(
-                            UNUSED_ATTRIBUTES,
-                            hir_id,
-                            attr.span(),
-                            errors::InnerCrateLevelAttr,
-                        ),
+                match attr {
+                    Attribute::Parsed(_) => { /* Already validated. */ }
+                    Attribute::Unparsed(attr) => {
+                        // FIXME(jdonszelmann): remove once all crate-level attrs are parsed and caught by
+                        // the above
+                        if let Some(BuiltinAttribute { type_: AttributeType::CrateLevel, .. }) =
+                            attr.path
+                                .segments
+                                .first()
+                                .and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name))
+                        {
+                            match attr.style {
+                                ast::AttrStyle::Outer => {
+                                    let attr_span = attr.span;
+                                    let bang_position = self
+                                        .tcx
+                                        .sess
+                                        .source_map()
+                                        .span_until_char(attr_span, '[')
+                                        .shrink_to_hi();
+
+                                    self.tcx.emit_node_span_lint(
+                                        UNUSED_ATTRIBUTES,
+                                        hir_id,
+                                        attr.span,
+                                        errors::OuterCrateLevelAttr {
+                                            suggestion: errors::OuterCrateLevelAttrSuggestion {
+                                                bang_position,
+                                            },
+                                        },
+                                    )
+                                }
+                                ast::AttrStyle::Inner => self.tcx.emit_node_span_lint(
+                                    UNUSED_ATTRIBUTES,
+                                    hir_id,
+                                    attr.span,
+                                    errors::InnerCrateLevelAttr,
+                                ),
+                            }
+                        }
                     }
                 }
             }
@@ -467,7 +494,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                 {
                     let attrs = self.tcx.codegen_fn_attrs(did);
                     // Not checking naked as `#[inline]` is forbidden for naked functions anyways.
-                    if attrs.contains_extern_indicator(self.tcx, did.into()) {
+                    if attrs.contains_extern_indicator() {
                         self.tcx.emit_node_span_lint(
                             UNUSED_ATTRIBUTES,
                             hir_id,
@@ -483,42 +510,48 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
 
     /// Checks that the `#[sanitize(..)]` attribute is applied to a
     /// function/closure/method, or to an impl block or module.
-    fn check_sanitize(&self, attr: &Attribute, target_span: Span, target: Target) {
+    fn check_sanitize(
+        &self,
+        attr_span: Span,
+        set: SanitizerSet,
+        target_span: Span,
+        target: Target,
+    ) {
         let mut not_fn_impl_mod = None;
         let mut no_body = None;
 
-        if let Some(list) = attr.meta_item_list() {
-            for item in list.iter() {
-                let MetaItemInner::MetaItem(set) = item else {
-                    return;
-                };
-                let segments = set.path.segments.iter().map(|x| x.ident.name).collect::<Vec<_>>();
-                match target {
-                    Target::Fn
-                    | Target::Closure
-                    | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent)
-                    | Target::Impl { .. }
-                    | Target::Mod => return,
-                    Target::Static if matches!(segments.as_slice(), [sym::address]) => return,
-
-                    // These are "functions", but they aren't allowed because they don't
-                    // have a body, so the usual explanation would be confusing.
-                    Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
-                        no_body = Some(target_span);
-                    }
+        match target {
+            Target::Fn
+            | Target::Closure
+            | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent)
+            | Target::Impl { .. }
+            | Target::Mod => return,
+            Target::Static
+                // if we mask out the address bits, i.e. *only* address was set,
+                // we allow it
+                if set & !(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS)
+                    == SanitizerSet::empty() =>
+            {
+                return;
+            }
 
-                    _ => {
-                        not_fn_impl_mod = Some(target_span);
-                    }
-                }
+            // These are "functions", but they aren't allowed because they don't
+            // have a body, so the usual explanation would be confusing.
+            Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
+                no_body = Some(target_span);
+            }
+
+            _ => {
+                not_fn_impl_mod = Some(target_span);
             }
-            self.dcx().emit_err(errors::SanitizeAttributeNotAllowed {
-                attr_span: attr.span(),
-                not_fn_impl_mod,
-                no_body,
-                help: (),
-            });
         }
+
+        self.dcx().emit_err(errors::SanitizeAttributeNotAllowed {
+            attr_span,
+            not_fn_impl_mod,
+            no_body,
+            help: (),
+        });
     }
 
     /// Checks if `#[naked]` is applied to a function definition.
@@ -1293,7 +1326,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
     }
 
     /// Checks if `#[link]` is applied to an item other than a foreign module.
-    fn check_link(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
+    fn check_link(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) {
         if target == Target::ForeignMod
             && let hir::Node::Item(item) = self.tcx.hir_node(hir_id)
             && let Item { kind: ItemKind::ForeignMod { abi, .. }, .. } = item
@@ -1305,7 +1338,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         self.tcx.emit_node_span_lint(
             UNUSED_ATTRIBUTES,
             hir_id,
-            attr.span(),
+            attr_span,
             errors::Link { span: (target != Target::ForeignMod).then_some(span) },
         );
     }
@@ -1817,12 +1850,24 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         {
             if hir_id != CRATE_HIR_ID {
                 match style {
-                    Some(ast::AttrStyle::Outer) => self.tcx.emit_node_span_lint(
-                        UNUSED_ATTRIBUTES,
-                        hir_id,
-                        attr.span(),
-                        errors::OuterCrateLevelAttr,
-                    ),
+                    Some(ast::AttrStyle::Outer) => {
+                        let attr_span = attr.span();
+                        let bang_position = self
+                            .tcx
+                            .sess
+                            .source_map()
+                            .span_until_char(attr_span, '[')
+                            .shrink_to_hi();
+
+                        self.tcx.emit_node_span_lint(
+                            UNUSED_ATTRIBUTES,
+                            hir_id,
+                            attr_span,
+                            errors::OuterCrateLevelAttr {
+                                suggestion: errors::OuterCrateLevelAttrSuggestion { bang_position },
+                            },
+                        )
+                    }
                     Some(ast::AttrStyle::Inner) | None => self.tcx.emit_node_span_lint(
                         UNUSED_ATTRIBUTES,
                         hir_id,
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index 10cd9df4816..fc33405d455 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -706,7 +706,7 @@ fn has_allow_dead_code_or_lang_attr(
 
             // #[used], #[no_mangle], #[export_name], etc also keeps the item alive
             // forcefully, e.g., for placing it in a specific section.
-            cg_attrs.contains_extern_indicator(tcx, def_id.into())
+            cg_attrs.contains_extern_indicator()
                 || cg_attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER)
                 || cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
         }
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index 4fec6b0798a..01972067978 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -64,7 +64,17 @@ pub(crate) struct MixedExportNameAndNoMangle {
 
 #[derive(LintDiagnostic)]
 #[diag(passes_outer_crate_level_attr)]
-pub(crate) struct OuterCrateLevelAttr;
+pub(crate) struct OuterCrateLevelAttr {
+    #[subdiagnostic]
+    pub suggestion: OuterCrateLevelAttrSuggestion,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(passes_outer_crate_level_attr_suggestion, style = "verbose")]
+pub(crate) struct OuterCrateLevelAttrSuggestion {
+    #[suggestion_part(code = "!")]
+    pub bang_position: Span,
+}
 
 #[derive(LintDiagnostic)]
 #[diag(passes_inner_crate_level_attr)]
diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs
index 6cd8a54ecf4..d1a703fc5d8 100644
--- a/compiler/rustc_passes/src/reachable.rs
+++ b/compiler/rustc_passes/src/reachable.rs
@@ -183,7 +183,7 @@ impl<'tcx> ReachableContext<'tcx> {
             } else {
                 CodegenFnAttrs::EMPTY
             };
-            let is_extern = codegen_attrs.contains_extern_indicator(self.tcx, search_item.into());
+            let is_extern = codegen_attrs.contains_extern_indicator();
             if is_extern {
                 self.reachable_symbols.insert(search_item);
             }
@@ -425,7 +425,7 @@ fn has_custom_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
     }
 
     let codegen_attrs = tcx.codegen_fn_attrs(def_id);
-    codegen_attrs.contains_extern_indicator(tcx, def_id.into())
+    codegen_attrs.contains_extern_indicator()
         // FIXME(nbdd0121): `#[used]` are marked as reachable here so it's picked up by
         // `linked_symbols` in cg_ssa. They won't be exported in binary or cdylib due to their
         // `SymbolExportLevel::Rust` export level but may end up being exported in dylibs.
diff --git a/compiler/rustc_pattern_analysis/Cargo.toml b/compiler/rustc_pattern_analysis/Cargo.toml
index a59f7bbeb9e..39f660c8771 100644
--- a/compiler/rustc_pattern_analysis/Cargo.toml
+++ b/compiler/rustc_pattern_analysis/Cargo.toml
@@ -19,7 +19,7 @@ rustc_middle = { path = "../rustc_middle", optional = true }
 rustc_session = { path = "../rustc_session", optional = true }
 rustc_span = { path = "../rustc_span", optional = true }
 smallvec = { version = "1.8.1", features = ["union"] }
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
 
 [dev-dependencies]
diff --git a/compiler/rustc_pattern_analysis/src/rustc/print.rs b/compiler/rustc_pattern_analysis/src/rustc/print.rs
index 7649f72f868..cdf62c2553d 100644
--- a/compiler/rustc_pattern_analysis/src/rustc/print.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc/print.rs
@@ -101,23 +101,11 @@ pub(crate) fn write_struct_like<'tcx>(
     let num_fields = variant_and_name.as_ref().map_or(subpatterns.len(), |(v, _)| v.fields.len());
     if num_fields != 0 || variant_and_name.is_none() {
         write!(f, "(")?;
-        for i in 0..num_fields {
-            write!(f, "{}", start_or_comma())?;
-
-            // Common case: the field is where we expect it.
-            if let Some(p) = subpatterns.get(i) {
-                if p.field.index() == i {
-                    write!(f, "{}", p.pattern)?;
-                    continue;
-                }
-            }
-
-            // Otherwise, we have to go looking for it.
-            if let Some(p) = subpatterns.iter().find(|p| p.field.index() == i) {
-                write!(f, "{}", p.pattern)?;
-            } else {
-                write!(f, "_")?;
-            }
+        for FieldPat { pattern, .. } in subpatterns {
+            write!(f, "{}{pattern}", start_or_comma())?;
+        }
+        if matches!(ty.kind(), ty::Tuple(..)) && num_fields == 1 {
+            write!(f, ",")?;
         }
         write!(f, ")")?;
     }
diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml
index c8bfdb91304..7de58132e13 100644
--- a/compiler/rustc_privacy/Cargo.toml
+++ b/compiler/rustc_privacy/Cargo.toml
@@ -15,5 +15,5 @@ rustc_middle = { path = "../rustc_middle" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_ty_utils = { path = "../rustc_ty_utils" }
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
diff --git a/compiler/rustc_proc_macro/Cargo.toml b/compiler/rustc_proc_macro/Cargo.toml
index beb95aa3b52..99e7fc7abc6 100644
--- a/compiler/rustc_proc_macro/Cargo.toml
+++ b/compiler/rustc_proc_macro/Cargo.toml
@@ -16,7 +16,7 @@ doctest = false
 
 [dependencies]
 # tidy-alphabetical-start
-rustc-literal-escaper = "0.0.5"
+rustc-literal-escaper.workspace = true
 # tidy-alphabetical-end
 
 [features]
diff --git a/compiler/rustc_public/Cargo.toml b/compiler/rustc_public/Cargo.toml
index 70af30c1a5f..71d339b5792 100644
--- a/compiler/rustc_public/Cargo.toml
+++ b/compiler/rustc_public/Cargo.toml
@@ -14,7 +14,7 @@ rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 scoped-tls = "1.0"
 serde = { version = "1.0.125", features = [ "derive" ] }
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
 
 [features]
diff --git a/compiler/rustc_query_impl/Cargo.toml b/compiler/rustc_query_impl/Cargo.toml
index e5cceacf15d..2005b8b9eca 100644
--- a/compiler/rustc_query_impl/Cargo.toml
+++ b/compiler/rustc_query_impl/Cargo.toml
@@ -15,5 +15,5 @@ rustc_query_system = { path = "../rustc_query_system" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
diff --git a/compiler/rustc_query_system/Cargo.toml b/compiler/rustc_query_system/Cargo.toml
index 7480ba03474..0df933bc81c 100644
--- a/compiler/rustc_query_system/Cargo.toml
+++ b/compiler/rustc_query_system/Cargo.toml
@@ -21,7 +21,7 @@ rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_thread_pool = { path = "../rustc_thread_pool" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
 
 [dependencies.hashbrown]
diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml
index eb98a6e85c0..7c5332c1662 100644
--- a/compiler/rustc_resolve/Cargo.toml
+++ b/compiler/rustc_resolve/Cargo.toml
@@ -5,9 +5,9 @@ edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
-bitflags = "2.4.1"
+bitflags.workspace = true
 indexmap = "2.4.0"
-itertools = "0.12"
+itertools.workspace = true
 pulldown-cmark = { version = "0.11", features = ["html"], default-features = false }
 rustc_arena = { path = "../rustc_arena" }
 rustc_ast = { path = "../rustc_ast" }
@@ -27,6 +27,6 @@ rustc_query_system = { path = "../rustc_query_system" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.12"
-tracing = "0.1"
+thin-vec.workspace = true
+tracing.workspace = true
 # tidy-alphabetical-end
diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs
index 6450f63472c..f9f2f84bc50 100644
--- a/compiler/rustc_resolve/src/rustdoc.rs
+++ b/compiler/rustc_resolve/src/rustdoc.rs
@@ -207,8 +207,10 @@ pub fn attrs_to_doc_fragments<'a, A: AttributeExt + Clone + 'a>(
     attrs: impl Iterator<Item = (&'a A, Option<DefId>)>,
     doc_only: bool,
 ) -> (Vec<DocFragment>, ThinVec<A>) {
-    let mut doc_fragments = Vec::new();
-    let mut other_attrs = ThinVec::<A>::new();
+    let (min_size, max_size) = attrs.size_hint();
+    let size_hint = max_size.unwrap_or(min_size);
+    let mut doc_fragments = Vec::with_capacity(size_hint);
+    let mut other_attrs = ThinVec::<A>::with_capacity(if doc_only { 0 } else { size_hint });
     for (attr, item_id) in attrs {
         if let Some((doc_str, comment_kind)) = attr.doc_str_and_comment_kind() {
             let doc = beautify_doc_string(doc_str, comment_kind);
@@ -230,6 +232,9 @@ pub fn attrs_to_doc_fragments<'a, A: AttributeExt + Clone + 'a>(
         }
     }
 
+    doc_fragments.shrink_to_fit();
+    other_attrs.shrink_to_fit();
+
     unindent_doc_fragments(&mut doc_fragments);
 
     (doc_fragments, other_attrs)
diff --git a/compiler/rustc_sanitizers/Cargo.toml b/compiler/rustc_sanitizers/Cargo.toml
index 9069d2c233d..3dbeaa435f3 100644
--- a/compiler/rustc_sanitizers/Cargo.toml
+++ b/compiler/rustc_sanitizers/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
-bitflags = "2.5.0"
+bitflags.workspace = true
 rustc_abi = { path = "../rustc_abi" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_hir = { path = "../rustc_hir" }
@@ -13,6 +13,6 @@ rustc_middle = { path = "../rustc_middle" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
-tracing = "0.1"
+tracing.workspace = true
 twox-hash = "1.6.3"
 # tidy-alphabetical-end
diff --git a/compiler/rustc_serialize/Cargo.toml b/compiler/rustc_serialize/Cargo.toml
index 948242352e7..e9959735f9f 100644
--- a/compiler/rustc_serialize/Cargo.toml
+++ b/compiler/rustc_serialize/Cargo.toml
@@ -8,7 +8,7 @@ edition = "2024"
 indexmap = "2.0.0"
 rustc_hashes = { path = "../rustc_hashes" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2.12"
+thin-vec.workspace = true
 # tidy-alphabetical-end
 
 [dev-dependencies]
diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml
index 60d56b1b808..97789b198a4 100644
--- a/compiler/rustc_session/Cargo.toml
+++ b/compiler/rustc_session/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
-bitflags = "2.4.1"
+bitflags.workspace = true
 getopts = "0.2"
 rand = "0.9.0"
 rustc_abi = { path = "../rustc_abi" }
@@ -23,7 +23,7 @@ rustc_serialize = { path = "../rustc_serialize" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 termize = "0.2"
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
 
 [target.'cfg(unix)'.dependencies]
diff --git a/compiler/rustc_session/src/config/native_libs.rs b/compiler/rustc_session/src/config/native_libs.rs
index f1f0aeb5e59..50a0593f887 100644
--- a/compiler/rustc_session/src/config/native_libs.rs
+++ b/compiler/rustc_session/src/config/native_libs.rs
@@ -5,10 +5,11 @@
 //! which have their own parser in `rustc_metadata`.)
 
 use rustc_feature::UnstableFeatures;
+use rustc_hir::attrs::NativeLibKind;
 
 use crate::EarlyDiagCtxt;
 use crate::config::UnstableOptions;
-use crate::utils::{NativeLib, NativeLibKind};
+use crate::utils::NativeLib;
 
 #[cfg(test)]
 mod tests;
diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs
index 4cfc745dec2..30f6256a75e 100644
--- a/compiler/rustc_session/src/cstore.rs
+++ b/compiler/rustc_session/src/cstore.rs
@@ -6,8 +6,8 @@ use std::any::Any;
 use std::path::PathBuf;
 
 use rustc_abi::ExternAbi;
-use rustc_ast as ast;
 use rustc_data_structures::sync::{self, AppendOnlyIndexVec, FreezeLock};
+use rustc_hir::attrs::{CfgEntry, NativeLibKind, PeImportNameType};
 use rustc_hir::def_id::{
     CrateNum, DefId, LOCAL_CRATE, LocalDefId, StableCrateId, StableCrateIdMap,
 };
@@ -16,7 +16,6 @@ use rustc_macros::{Decodable, Encodable, HashStable_Generic};
 use rustc_span::{Span, Symbol};
 
 use crate::search_paths::PathKind;
-use crate::utils::NativeLibKind;
 
 // lonely orphan structs and enums looking for a better home
 
@@ -72,7 +71,7 @@ pub struct NativeLib {
     pub name: Symbol,
     /// If packed_bundled_libs enabled, actual filename of library is stored.
     pub filename: Option<Symbol>,
-    pub cfg: Option<ast::MetaItemInner>,
+    pub cfg: Option<CfgEntry>,
     pub foreign_module: Option<DefId>,
     pub verbatim: Option<bool>,
     pub dll_imports: Vec<DllImport>,
@@ -88,25 +87,6 @@ impl NativeLib {
     }
 }
 
-/// Different ways that the PE Format can decorate a symbol name.
-/// From <https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#import-name-type>
-#[derive(Copy, Clone, Debug, Encodable, Decodable, HashStable_Generic, PartialEq, Eq)]
-pub enum PeImportNameType {
-    /// IMPORT_ORDINAL
-    /// Uses the ordinal (i.e., a number) rather than the name.
-    Ordinal(u16),
-    /// Same as IMPORT_NAME
-    /// Name is decorated with all prefixes and suffixes.
-    Decorated,
-    /// Same as IMPORT_NAME_NOPREFIX
-    /// Prefix (e.g., the leading `_` or `@`) is skipped, but suffix is kept.
-    NoPrefix,
-    /// Same as IMPORT_NAME_UNDECORATE
-    /// Prefix (e.g., the leading `_` or `@`) and suffix (the first `@` and all
-    /// trailing characters) are skipped.
-    Undecorated,
-}
-
 #[derive(Clone, Debug, Encodable, Decodable, HashStable_Generic)]
 pub struct DllImport {
     pub name: Symbol,
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index bb7ffa2a85d..96767d05439 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -7,6 +7,7 @@ use std::sync::atomic::AtomicBool;
 use std::{env, fmt, io};
 
 use rand::{RngCore, rng};
+use rustc_ast::NodeId;
 use rustc_data_structures::base_n::{CASE_INSENSITIVE, ToBaseN};
 use rustc_data_structures::flock;
 use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
@@ -22,7 +23,7 @@ use rustc_errors::timings::TimingSectionHandler;
 use rustc_errors::translation::Translator;
 use rustc_errors::{
     Diag, DiagCtxt, DiagCtxtHandle, DiagMessage, Diagnostic, ErrorGuaranteed, FatalAbort,
-    TerminalUrl, fallback_fluent_bundle,
+    LintEmitter, TerminalUrl, fallback_fluent_bundle,
 };
 use rustc_macros::HashStable_Generic;
 pub use rustc_span::def_id::StableCrateId;
@@ -223,6 +224,20 @@ pub struct Session {
     pub invocation_temp: Option<String>,
 }
 
+impl LintEmitter for &'_ Session {
+    type Id = NodeId;
+
+    fn emit_node_span_lint(
+        self,
+        lint: &'static rustc_lint_defs::Lint,
+        node_id: Self::Id,
+        span: impl Into<rustc_errors::MultiSpan>,
+        decorator: impl for<'a> rustc_errors::LintDiagnostic<'a, ()> + DynSend + 'static,
+    ) {
+        self.psess.buffer_lint(lint, span, node_id, decorator);
+    }
+}
+
 #[derive(Clone, Copy)]
 pub enum CodegenUnits {
     /// Specified by the user. In this case we try fairly hard to produce the
diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs
index e9ddd66b5e8..c64d9bc1efe 100644
--- a/compiler/rustc_session/src/utils.rs
+++ b/compiler/rustc_session/src/utils.rs
@@ -3,6 +3,7 @@ use std::sync::OnceLock;
 
 use rustc_data_structures::profiling::VerboseTimingGuard;
 use rustc_fs_util::try_canonicalize;
+use rustc_hir::attrs::NativeLibKind;
 use rustc_macros::{Decodable, Encodable, HashStable_Generic};
 
 use crate::session::Session;
@@ -17,69 +18,6 @@ impl Session {
     }
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
-#[derive(HashStable_Generic)]
-pub enum NativeLibKind {
-    /// Static library (e.g. `libfoo.a` on Linux or `foo.lib` on Windows/MSVC)
-    Static {
-        /// Whether to bundle objects from static library into produced rlib
-        bundle: Option<bool>,
-        /// Whether to link static library without throwing any object files away
-        whole_archive: Option<bool>,
-    },
-    /// Dynamic library (e.g. `libfoo.so` on Linux)
-    /// or an import library corresponding to a dynamic library (e.g. `foo.lib` on Windows/MSVC).
-    Dylib {
-        /// Whether the dynamic library will be linked only if it satisfies some undefined symbols
-        as_needed: Option<bool>,
-    },
-    /// Dynamic library (e.g. `foo.dll` on Windows) without a corresponding import library.
-    /// On Linux, it refers to a generated shared library stub.
-    RawDylib,
-    /// A macOS-specific kind of dynamic libraries.
-    Framework {
-        /// Whether the framework will be linked only if it satisfies some undefined symbols
-        as_needed: Option<bool>,
-    },
-    /// Argument which is passed to linker, relative order with libraries and other arguments
-    /// is preserved
-    LinkArg,
-
-    /// Module imported from WebAssembly
-    WasmImportModule,
-
-    /// The library kind wasn't specified, `Dylib` is currently used as a default.
-    Unspecified,
-}
-
-impl NativeLibKind {
-    pub fn has_modifiers(&self) -> bool {
-        match self {
-            NativeLibKind::Static { bundle, whole_archive } => {
-                bundle.is_some() || whole_archive.is_some()
-            }
-            NativeLibKind::Dylib { as_needed } | NativeLibKind::Framework { as_needed } => {
-                as_needed.is_some()
-            }
-            NativeLibKind::RawDylib
-            | NativeLibKind::Unspecified
-            | NativeLibKind::LinkArg
-            | NativeLibKind::WasmImportModule => false,
-        }
-    }
-
-    pub fn is_statically_included(&self) -> bool {
-        matches!(self, NativeLibKind::Static { .. })
-    }
-
-    pub fn is_dllimport(&self) -> bool {
-        matches!(
-            self,
-            NativeLibKind::Dylib { .. } | NativeLibKind::RawDylib | NativeLibKind::Unspecified
-        )
-    }
-}
-
 #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
 #[derive(HashStable_Generic)]
 pub struct NativeLib {
diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml
index 43a2d692577..2e45177e3b7 100644
--- a/compiler/rustc_span/Cargo.toml
+++ b/compiler/rustc_span/Cargo.toml
@@ -19,6 +19,6 @@ rustc_serialize = { path = "../rustc_serialize" }
 scoped-tls = "1.0"
 sha1 = "0.10.0"
 sha2 = "0.10.1"
-tracing = "0.1"
+tracing.workspace = true
 unicode-width = "0.2.0"
 # tidy-alphabetical-end
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 8270de1e917..166842e374b 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -9,6 +9,7 @@
 //! within the `SourceMap`, which upon request can be converted to line and column
 //! information, source code snippets, etc.
 
+use std::fs::File;
 use std::io::{self, BorrowedBuf, Read};
 use std::{fs, path};
 
@@ -115,13 +116,18 @@ impl FileLoader for RealFileLoader {
     }
 
     fn read_file(&self, path: &Path) -> io::Result<String> {
-        if path.metadata().is_ok_and(|metadata| metadata.len() > SourceFile::MAX_FILE_SIZE.into()) {
+        let mut file = File::open(path)?;
+        let size = file.metadata().map(|metadata| metadata.len()).ok().unwrap_or(0);
+
+        if size > SourceFile::MAX_FILE_SIZE.into() {
             return Err(io::Error::other(format!(
                 "text files larger than {} bytes are unsupported",
                 SourceFile::MAX_FILE_SIZE
             )));
         }
-        fs::read_to_string(path)
+        let mut contents = String::new();
+        file.read_to_string(&mut contents)?;
+        Ok(contents)
     }
 
     fn read_binary_file(&self, path: &Path) -> io::Result<Arc<[u8]>> {
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 5d140cc6117..89b07dba5c8 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -466,6 +466,7 @@ symbols! {
         arm,
         arm_target_feature,
         array,
+        as_dash_needed: "as-needed",
         as_ptr,
         as_ref,
         as_str,
@@ -592,6 +593,7 @@ symbols! {
         btreeset_iter,
         built,
         builtin_syntax,
+        bundle,
         c,
         c_dash_variadic,
         c_str,
@@ -817,6 +819,7 @@ symbols! {
         decl_macro,
         declare_lint_pass,
         decode,
+        decorated,
         default_alloc_error_handler,
         default_field_values,
         default_fn,
@@ -1075,6 +1078,7 @@ symbols! {
         format_macro,
         format_placeholder,
         format_unsafe_arg,
+        framework,
         freeze,
         freeze_impls,
         freg,
@@ -1295,6 +1299,7 @@ symbols! {
         link_arg_attribute,
         link_args,
         link_cfg,
+        link_dash_arg: "link-arg",
         link_llvm_intrinsics,
         link_name,
         link_ordinal,
@@ -1528,6 +1533,7 @@ symbols! {
         noop_method_borrow,
         noop_method_clone,
         noop_method_deref,
+        noprefix,
         noreturn,
         nostack,
         not,
@@ -1741,6 +1747,7 @@ symbols! {
         quote,
         range_inclusive_new,
         range_step,
+        raw_dash_dylib: "raw-dylib",
         raw_dylib,
         raw_dylib_elf,
         raw_eq,
@@ -2277,6 +2284,7 @@ symbols! {
         unchecked_shl,
         unchecked_shr,
         unchecked_sub,
+        undecorated,
         underscore_const_names,
         underscore_imports,
         underscore_lifetimes,
@@ -2365,6 +2373,7 @@ symbols! {
         vecdeque_iter,
         vecdeque_reserve,
         vector,
+        verbatim,
         version,
         vfp2,
         vis,
@@ -2389,6 +2398,7 @@ symbols! {
         weak_odr,
         where_clause_attrs,
         while_let,
+        whole_dash_archive: "whole-archive",
         width,
         windows,
         windows_subsystem,
@@ -2419,9 +2429,11 @@ symbols! {
         yield_expr,
         ymm_reg,
         yreg,
+        zca,
         zfh,
         zfhmin,
         zmm_reg,
+        ztso,
         // tidy-alphabetical-end
     }
 }
diff --git a/compiler/rustc_symbol_mangling/Cargo.toml b/compiler/rustc_symbol_mangling/Cargo.toml
index 0df9c7682bf..48e02dabdde 100644
--- a/compiler/rustc_symbol_mangling/Cargo.toml
+++ b/compiler/rustc_symbol_mangling/Cargo.toml
@@ -15,5 +15,5 @@ rustc_hir = { path = "../rustc_hir" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
diff --git a/compiler/rustc_target/Cargo.toml b/compiler/rustc_target/Cargo.toml
index 57c90a703f1..3c257bf38a5 100644
--- a/compiler/rustc_target/Cargo.toml
+++ b/compiler/rustc_target/Cargo.toml
@@ -5,7 +5,8 @@ edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
-bitflags = "2.4.1"
+bitflags.workspace = true
+object = { version = "0.37.0", default-features = false, features = ["elf", "macho"] }
 rustc_abi = { path = "../rustc_abi" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_error_messages = { path = "../rustc_error_messages" }
@@ -17,12 +18,6 @@ serde = "1.0.219"
 serde_derive = "1.0.219"
 serde_json = "1.0.59"
 serde_path_to_error = "0.1.17"
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
 
-[dependencies.object]
-# tidy-alphabetical-start
-default-features = false
-features = ["elf", "macho"]
-version = "0.37.0"
-# tidy-alphabetical-end
diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs
index 5f2a6f7ba38..7a7c63c475b 100644
--- a/compiler/rustc_target/src/callconv/mod.rs
+++ b/compiler/rustc_target/src/callconv/mod.rs
@@ -114,7 +114,7 @@ mod attr_impl {
     bitflags::bitflags! {
         impl ArgAttribute: u8 {
             const NoAlias   = 1 << 1;
-            const NoCapture = 1 << 2;
+            const CapturesAddress = 1 << 2;
             const NonNull   = 1 << 3;
             const ReadOnly  = 1 << 4;
             const InReg     = 1 << 5;
@@ -400,11 +400,11 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
         let mut attrs = ArgAttributes::new();
 
         // For non-immediate arguments the callee gets its own copy of
-        // the value on the stack, so there are no aliases. It's also
-        // program-invisible so can't possibly capture
+        // the value on the stack, so there are no aliases. The function
+        // can capture the address of the argument, but not the provenance.
         attrs
             .set(ArgAttribute::NoAlias)
-            .set(ArgAttribute::NoCapture)
+            .set(ArgAttribute::CapturesAddress)
             .set(ArgAttribute::NonNull)
             .set(ArgAttribute::NoUndef);
         attrs.pointee_size = layout.size;
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index a67795e3e93..c53d92bee9d 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1954,6 +1954,7 @@ supported_targets! {
     ("armv7-unknown-linux-musleabihf", armv7_unknown_linux_musleabihf),
     ("aarch64-unknown-linux-gnu", aarch64_unknown_linux_gnu),
     ("aarch64-unknown-linux-musl", aarch64_unknown_linux_musl),
+    ("aarch64_be-unknown-linux-musl", aarch64_be_unknown_linux_musl),
     ("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl),
     ("i686-unknown-linux-musl", i686_unknown_linux_musl),
     ("i586-unknown-linux-musl", i586_unknown_linux_musl),
@@ -2149,6 +2150,7 @@ supported_targets! {
     ("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf),
     ("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu),
     ("riscv64gc-unknown-linux-musl", riscv64gc_unknown_linux_musl),
+    ("riscv64a23-unknown-linux-gnu", riscv64a23_unknown_linux_gnu),
 
     ("sparc-unknown-none-elf", sparc_unknown_none_elf),
 
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_musl.rs
new file mode 100644
index 00000000000..be5ac4a843b
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/aarch64_be_unknown_linux_musl.rs
@@ -0,0 +1,40 @@
+use rustc_abi::Endian;
+
+use crate::spec::{
+    FramePointer, SanitizerSet, StackProbeType, Target, TargetMetadata, TargetOptions, base,
+};
+
+pub(crate) fn target() -> Target {
+    let mut base = base::linux_musl::opts();
+    base.max_atomic_width = Some(128);
+    base.supports_xray = true;
+    base.features = "+v8a,+outline-atomics".into();
+    base.stack_probes = StackProbeType::Inline;
+    base.supported_sanitizers = SanitizerSet::ADDRESS
+        | SanitizerSet::CFI
+        | SanitizerSet::LEAK
+        | SanitizerSet::MEMORY
+        | SanitizerSet::THREAD;
+
+    Target {
+        llvm_target: "aarch64_be-unknown-linux-musl".into(),
+        metadata: TargetMetadata {
+            description: Some("ARM64 Linux (big-endian) with musl-libc 1.2.5".into()),
+            tier: Some(3),
+            host_tools: Some(false),
+            std: Some(true),
+        },
+        pointer_width: 64,
+        data_layout: "E-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
+        arch: "aarch64".into(),
+        options: TargetOptions {
+            // the AAPCS64 expects use of non-leaf frame pointers per
+            // https://github.com/ARM-software/abi-aa/blob/4492d1570eb70c8fd146623e0db65b2d241f12e7/aapcs64/aapcs64.rst#the-frame-pointer
+            // and we tend to encounter interesting bugs in AArch64 unwinding code if we do not
+            frame_pointer: FramePointer::NonLeaf,
+            mcount: "\u{1}_mcount".into(),
+            endian: Endian::Big,
+            ..base
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/spec/targets/riscv64a23_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/riscv64a23_unknown_linux_gnu.rs
new file mode 100644
index 00000000000..60f2e7da042
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/riscv64a23_unknown_linux_gnu.rs
@@ -0,0 +1,27 @@
+use std::borrow::Cow;
+
+use crate::spec::{CodeModel, SplitDebuginfo, Target, TargetMetadata, TargetOptions, base};
+
+pub(crate) fn target() -> Target {
+    Target {
+        llvm_target: "riscv64-unknown-linux-gnu".into(),
+        metadata: TargetMetadata {
+            description: Some("RISC-V Linux (kernel 6.8.0, glibc 2.39)".into()),
+            tier: Some(3),
+            host_tools: Some(true),
+            std: Some(true),
+        },
+        pointer_width: 64,
+        data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(),
+        arch: "riscv64".into(),
+        options: TargetOptions {
+            code_model: Some(CodeModel::Medium),
+            cpu: "generic-rv64".into(),
+            features: "+rva23u64".into(),
+            llvm_abiname: "lp64d".into(),
+            max_atomic_width: Some(64),
+            supported_split_debuginfo: Cow::Borrowed(&[SplitDebuginfo::Off]),
+            ..base::linux_gnu::opts()
+        },
+    }
+}
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index e45300b59cc..4c1b8c99426 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -601,6 +601,49 @@ static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     ),
     ("m", Stable, &[]),
     ("relax", Unstable(sym::riscv_target_feature), &[]),
+    (
+        "rva23u64",
+        Unstable(sym::riscv_target_feature),
+        &[
+            "m",
+            "a",
+            "f",
+            "d",
+            "c",
+            "b",
+            "v",
+            "zicsr",
+            "zicntr",
+            "zihpm",
+            "ziccif",
+            "ziccrse",
+            "ziccamoa",
+            "zicclsm",
+            "zic64b",
+            "za64rs",
+            "zihintpause",
+            "zba",
+            "zbb",
+            "zbs",
+            "zicbom",
+            "zicbop",
+            "zicboz",
+            "zfhmin",
+            "zkt",
+            "zvfhmin",
+            "zvbb",
+            "zvkt",
+            "zihintntl",
+            "zicond",
+            "zimop",
+            "zcmop",
+            "zcb",
+            "zfa",
+            "zawrs",
+            "supm",
+        ],
+    ),
+    ("supm", Unstable(sym::riscv_target_feature), &[]),
     ("unaligned-scalar-mem", Unstable(sym::riscv_target_feature), &[]),
     ("unaligned-vector-mem", Unstable(sym::riscv_target_feature), &[]),
     ("v", Unstable(sym::riscv_target_feature), &["zvl128b", "zve64d"]),
diff --git a/compiler/rustc_thread_pool/src/lib.rs b/compiler/rustc_thread_pool/src/lib.rs
index 34252d919e3..7ce7fbc27ea 100644
--- a/compiler/rustc_thread_pool/src/lib.rs
+++ b/compiler/rustc_thread_pool/src/lib.rs
@@ -787,18 +787,7 @@ impl ThreadPoolBuildError {
     }
 }
 
-const GLOBAL_POOL_ALREADY_INITIALIZED: &str =
-    "The global thread pool has already been initialized.";
-
 impl Error for ThreadPoolBuildError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        match self.kind {
-            ErrorKind::GlobalPoolAlreadyInitialized => GLOBAL_POOL_ALREADY_INITIALIZED,
-            ErrorKind::IOError(ref e) => e.description(),
-        }
-    }
-
     fn source(&self) -> Option<&(dyn Error + 'static)> {
         match &self.kind {
             ErrorKind::GlobalPoolAlreadyInitialized => None,
@@ -810,7 +799,9 @@ impl Error for ThreadPoolBuildError {
 impl fmt::Display for ThreadPoolBuildError {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match &self.kind {
-            ErrorKind::GlobalPoolAlreadyInitialized => GLOBAL_POOL_ALREADY_INITIALIZED.fmt(f),
+            ErrorKind::GlobalPoolAlreadyInitialized => {
+                "The global thread pool has already been initialized.".fmt(f)
+            }
             ErrorKind::IOError(e) => e.fmt(f),
         }
     }
diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml
index 1071105522d..6b79b98d1bf 100644
--- a/compiler/rustc_trait_selection/Cargo.toml
+++ b/compiler/rustc_trait_selection/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
-itertools = "0.12"
+itertools.workspace = true
 rustc_abi = { path = "../rustc_abi" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_data_structures = { path = "../rustc_data_structures" }
@@ -21,6 +21,6 @@ rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_transmute = { path = "../rustc_transmute", features = ["rustc"] }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
-thin-vec = "0.2"
-tracing = "0.1"
+thin-vec.workspace = true
+tracing.workspace = true
 # tidy-alphabetical-end
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index e31ff8b8729..aa153d3607b 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -820,16 +820,20 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         if matches!(obligation.cause.code(), ObligationCauseCode::FunctionArg { .. })
             && obligation.cause.span.can_be_used_for_suggestions()
         {
+            let (span, sugg) = if let Some(snippet) =
+                self.tcx.sess.source_map().span_to_snippet(obligation.cause.span).ok()
+                && snippet.starts_with("|")
+            {
+                (obligation.cause.span, format!("({snippet})({args})"))
+            } else {
+                (obligation.cause.span.shrink_to_hi(), format!("({args})"))
+            };
+
             // When the obligation error has been ensured to have been caused by
             // an argument, the `obligation.cause.span` points at the expression
             // of the argument, so we can provide a suggestion. Otherwise, we give
             // a more general note.
-            err.span_suggestion_verbose(
-                obligation.cause.span.shrink_to_hi(),
-                msg,
-                format!("({args})"),
-                Applicability::HasPlaceholders,
-            );
+            err.span_suggestion_verbose(span, msg, sugg, Applicability::HasPlaceholders);
         } else if let DefIdOrName::DefId(def_id) = def_id_or_name {
             let name = match self.tcx.hir_get_if_local(def_id) {
                 Some(hir::Node::Expr(hir::Expr {
diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs
index 70a08f34f33..bc7bdd372ba 100644
--- a/compiler/rustc_trait_selection/src/opaque_types.rs
+++ b/compiler/rustc_trait_selection/src/opaque_types.rs
@@ -4,8 +4,8 @@ use rustc_hir::def_id::LocalDefId;
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_middle::ty::{
-    self, DefiningScopeKind, GenericArgKind, GenericArgs, OpaqueTypeKey, TyCtxt, TypeVisitableExt,
-    TypingMode, fold_regions,
+    self, DefiningScopeKind, GenericArgKind, GenericArgs, OpaqueTypeKey, Ty, TyCtxt,
+    TypeVisitableExt, TypingMode, fold_regions,
 };
 use rustc_span::{ErrorGuaranteed, Span};
 
@@ -14,22 +14,22 @@ use crate::regions::OutlivesEnvironmentBuildExt;
 use crate::traits::ObligationCtxt;
 
 #[derive(Debug)]
-pub enum InvalidOpaqueTypeArgs<'tcx> {
-    AlreadyReported(ErrorGuaranteed),
+pub enum NonDefiningUseReason<'tcx> {
+    Tainted(ErrorGuaranteed),
     NotAParam { opaque_type_key: OpaqueTypeKey<'tcx>, param_index: usize, span: Span },
     DuplicateParam { opaque_type_key: OpaqueTypeKey<'tcx>, param_indices: Vec<usize>, span: Span },
 }
-impl From<ErrorGuaranteed> for InvalidOpaqueTypeArgs<'_> {
+impl From<ErrorGuaranteed> for NonDefiningUseReason<'_> {
     fn from(guar: ErrorGuaranteed) -> Self {
-        InvalidOpaqueTypeArgs::AlreadyReported(guar)
+        NonDefiningUseReason::Tainted(guar)
     }
 }
-impl<'tcx> InvalidOpaqueTypeArgs<'tcx> {
+impl<'tcx> NonDefiningUseReason<'tcx> {
     pub fn report(self, infcx: &InferCtxt<'tcx>) -> ErrorGuaranteed {
         let tcx = infcx.tcx;
         match self {
-            InvalidOpaqueTypeArgs::AlreadyReported(guar) => guar,
-            InvalidOpaqueTypeArgs::NotAParam { opaque_type_key, param_index, span } => {
+            NonDefiningUseReason::Tainted(guar) => guar,
+            NonDefiningUseReason::NotAParam { opaque_type_key, param_index, span } => {
                 let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
                 let opaque_param = opaque_generics.param_at(param_index, tcx);
                 let kind = opaque_param.kind.descr();
@@ -40,7 +40,7 @@ impl<'tcx> InvalidOpaqueTypeArgs<'tcx> {
                     param_span: tcx.def_span(opaque_param.def_id),
                 })
             }
-            InvalidOpaqueTypeArgs::DuplicateParam { opaque_type_key, param_indices, span } => {
+            NonDefiningUseReason::DuplicateParam { opaque_type_key, param_indices, span } => {
                 let opaque_generics = tcx.generics_of(opaque_type_key.def_id);
                 let descr = opaque_generics.param_at(param_indices[0], tcx).kind.descr();
                 let spans: Vec<_> = param_indices
@@ -58,15 +58,17 @@ impl<'tcx> InvalidOpaqueTypeArgs<'tcx> {
 }
 
 /// Opaque type parameter validity check as documented in the [rustc-dev-guide chapter].
+/// With the new solver, uses which fail this check are simply treated as non-defining
+/// and we only emit an error if no defining use exists.
 ///
 /// [rustc-dev-guide chapter]:
 /// https://rustc-dev-guide.rust-lang.org/opaque-types-region-infer-restrictions.html
-pub fn check_opaque_type_parameter_valid<'tcx>(
+pub fn opaque_type_has_defining_use_args<'tcx>(
     infcx: &InferCtxt<'tcx>,
     opaque_type_key: OpaqueTypeKey<'tcx>,
     span: Span,
     defining_scope_kind: DefiningScopeKind,
-) -> Result<(), InvalidOpaqueTypeArgs<'tcx>> {
+) -> Result<(), NonDefiningUseReason<'tcx>> {
     let tcx = infcx.tcx;
     let opaque_env = LazyOpaqueTyEnv::new(tcx, opaque_type_key.def_id);
     let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default();
@@ -105,13 +107,13 @@ pub fn check_opaque_type_parameter_valid<'tcx>(
         } else {
             // Prevent `fn foo() -> Foo<u32>` from being defining.
             opaque_env.param_is_error(i)?;
-            return Err(InvalidOpaqueTypeArgs::NotAParam { opaque_type_key, param_index: i, span });
+            return Err(NonDefiningUseReason::NotAParam { opaque_type_key, param_index: i, span });
         }
     }
 
     for (_, param_indices) in seen_params {
         if param_indices.len() > 1 {
-            return Err(InvalidOpaqueTypeArgs::DuplicateParam {
+            return Err(NonDefiningUseReason::DuplicateParam {
                 opaque_type_key,
                 param_indices,
                 span,
@@ -206,3 +208,27 @@ impl<'tcx> LazyOpaqueTyEnv<'tcx> {
         canonical_args
     }
 }
+
+pub fn report_item_does_not_constrain_error<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    item_def_id: LocalDefId,
+    def_id: LocalDefId,
+    non_defining_use: Option<(OpaqueTypeKey<'tcx>, Span)>,
+) -> ErrorGuaranteed {
+    let span = tcx.def_ident_span(item_def_id).unwrap_or_else(|| tcx.def_span(item_def_id));
+    let opaque_type_span = tcx.def_span(def_id);
+    let opaque_type_name = tcx.def_path_str(def_id);
+
+    let mut err =
+        tcx.dcx().struct_span_err(span, format!("item does not constrain `{opaque_type_name}`"));
+    err.note("consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`");
+    err.span_note(opaque_type_span, "this opaque type is supposed to be constrained");
+    if let Some((key, span)) = non_defining_use {
+        let opaque_ty = Ty::new_opaque(tcx, key.def_id.into(), key.args);
+        err.span_note(
+            span,
+            format!("this use of `{opaque_ty}` does not have unique universal generic arguments"),
+        );
+    }
+    err.emit()
+}
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 3f628d80662..575e0472e0e 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -252,7 +252,9 @@ where
                         // inside of an opaque type, e.g. if there's `Opaque = (?x, ?x)` in the
                         // storage, we can also rely on structural identity of `?x` even if we
                         // later uniquify it in MIR borrowck.
-                        if infcx.in_hir_typeck && obligation.has_non_region_infer() {
+                        if infcx.in_hir_typeck
+                            && (obligation.has_non_region_infer() || obligation.has_free_regions())
+                        {
                             infcx.push_hir_typeck_potentially_region_dependent_goal(obligation);
                         }
                     }
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
index 0ca2d216228..6ce68507d65 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/custom.rs
@@ -1,6 +1,7 @@
 use std::fmt;
 
 use rustc_errors::ErrorGuaranteed;
+use rustc_hir::def_id::LocalDefId;
 use rustc_infer::infer::region_constraints::RegionConstraintData;
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::{TyCtxt, TypeFoldable};
@@ -42,13 +43,14 @@ where
     fn fully_perform(
         self,
         infcx: &InferCtxt<'tcx>,
+        root_def_id: LocalDefId,
         span: Span,
     ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
         if cfg!(debug_assertions) {
             info!("fully_perform({:?})", self);
         }
 
-        Ok(scrape_region_constraints(infcx, self.closure, self.description, span)?.0)
+        Ok(scrape_region_constraints(infcx, root_def_id, self.description, span, self.closure)?.0)
     }
 }
 
@@ -62,9 +64,10 @@ impl<F> fmt::Debug for CustomTypeOp<F> {
 /// constraints that result, creating query-region-constraints.
 pub fn scrape_region_constraints<'tcx, Op, R>(
     infcx: &InferCtxt<'tcx>,
-    op: impl FnOnce(&ObligationCtxt<'_, 'tcx>) -> Result<R, NoSolution>,
+    root_def_id: LocalDefId,
     name: &'static str,
     span: Span,
+    op: impl FnOnce(&ObligationCtxt<'_, 'tcx>) -> Result<R, NoSolution>,
 ) -> Result<(TypeOpOutput<'tcx, Op>, RegionConstraintData<'tcx>), ErrorGuaranteed>
 where
     R: TypeFoldable<TyCtxt<'tcx>>,
@@ -94,6 +97,8 @@ where
         let errors = ocx.select_all_or_error();
         if errors.is_empty() {
             Ok(value)
+        } else if let Err(guar) = infcx.tcx.check_potentially_region_dependent_goals(root_def_id) {
+            Err(guar)
         } else {
             Err(infcx
                 .dcx()
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
index 018e9748cf0..4b8bf868123 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/mod.rs
@@ -1,6 +1,7 @@
 use std::fmt;
 
 use rustc_errors::ErrorGuaranteed;
+use rustc_hir::def_id::LocalDefId;
 use rustc_infer::traits::PredicateObligations;
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::ty::{ParamEnvAnd, TyCtxt, TypeFoldable};
@@ -37,6 +38,7 @@ pub trait TypeOp<'tcx>: Sized + fmt::Debug {
     fn fully_perform(
         self,
         infcx: &InferCtxt<'tcx>,
+        root_def_id: LocalDefId,
         span: Span,
     ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed>;
 }
@@ -140,6 +142,7 @@ where
     fn fully_perform(
         self,
         infcx: &InferCtxt<'tcx>,
+        root_def_id: LocalDefId,
         span: Span,
     ) -> Result<TypeOpOutput<'tcx, Self>, ErrorGuaranteed> {
         // In the new trait solver, query type ops are performed locally. This
@@ -152,9 +155,10 @@ where
         if infcx.next_trait_solver() {
             return Ok(scrape_region_constraints(
                 infcx,
-                |ocx| QueryTypeOp::perform_locally_with_next_solver(ocx, self, span),
+                root_def_id,
                 "query type op",
                 span,
+                |ocx| QueryTypeOp::perform_locally_with_next_solver(ocx, self, span),
             )?
             .0);
         }
@@ -166,19 +170,15 @@ where
         // we sometimes end up with `Opaque<'a> = Opaque<'b>` instead of an actual hidden type. In that case we don't register a
         // hidden type but just equate the lifetimes. Thus we need to scrape the region constraints even though we're also manually
         // collecting region constraints via `region_constraints`.
-        let (mut output, _) = scrape_region_constraints(
-            infcx,
-            |ocx| {
+        let (mut output, _) =
+            scrape_region_constraints(infcx, root_def_id, "fully_perform", span, |ocx| {
                 let (output, ei, obligations, _) =
                     Q::fully_perform_into(self, infcx, &mut region_constraints, span)?;
                 error_info = ei;
 
                 ocx.register_obligations(obligations);
                 Ok(output)
-            },
-            "fully_perform",
-            span,
-        )?;
+            })?;
         output.error_info = error_info;
         if let Some(QueryRegionConstraints { outlives, assumptions }) = output.constraints {
             region_constraints.outlives.extend(outlives.iter().cloned());
diff --git a/compiler/rustc_traits/Cargo.toml b/compiler/rustc_traits/Cargo.toml
index 9f40f4d5c23..24360a94cc7 100644
--- a/compiler/rustc_traits/Cargo.toml
+++ b/compiler/rustc_traits/Cargo.toml
@@ -10,5 +10,5 @@ rustc_infer = { path = "../rustc_infer" }
 rustc_middle = { path = "../rustc_middle" }
 rustc_span = { path = "../rustc_span" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
diff --git a/compiler/rustc_transmute/Cargo.toml b/compiler/rustc_transmute/Cargo.toml
index e61717e5e9c..2ac2b46cc58 100644
--- a/compiler/rustc_transmute/Cargo.toml
+++ b/compiler/rustc_transmute/Cargo.toml
@@ -11,12 +11,12 @@ rustc_hir = { path = "../rustc_hir", optional = true }
 rustc_middle = { path = "../rustc_middle", optional = true }
 rustc_span = { path = "../rustc_span", optional = true }
 smallvec = "1.8.1"
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
 
 [dev-dependencies]
 # tidy-alphabetical-start
-itertools = "0.12"
+itertools.workspace = true
 # tidy-alphabetical-end
 
 [features]
diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml
index ce08b300cc8..394cde5a323 100644
--- a/compiler/rustc_ty_utils/Cargo.toml
+++ b/compiler/rustc_ty_utils/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
-itertools = "0.12"
+itertools.workspace = true
 rustc_abi = { path = "../rustc_abi" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
@@ -20,5 +20,5 @@ rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
 rustc_target = { path = "../rustc_target" }
 rustc_trait_selection = { path = "../rustc_trait_selection" }
-tracing = "0.1"
+tracing.workspace = true
 # tidy-alphabetical-end
diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml
index d55e9b3b1be..1dba7fe4269 100644
--- a/compiler/rustc_type_ir/Cargo.toml
+++ b/compiler/rustc_type_ir/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
-bitflags = "2.4.1"
+bitflags.workspace = true
 derive-where = "1.2.7"
 ena = "0.14.3"
 indexmap = "2.0.0"
@@ -19,8 +19,8 @@ rustc_serialize = { path = "../rustc_serialize", optional = true }
 rustc_span = { path = "../rustc_span", optional = true }
 rustc_type_ir_macros = { path = "../rustc_type_ir_macros" }
 smallvec = { version = "1.8.1", default-features = false, features = ["const_generics"] }
-thin-vec = "0.2.12"
-tracing = "0.1"
+thin-vec.workspace = true
+tracing.workspace = true
 # tidy-alphabetical-end
 
 [features]
diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs
index e39b99e992b..b4462294700 100644
--- a/compiler/rustc_type_ir/src/infer_ctxt.rs
+++ b/compiler/rustc_type_ir/src/infer_ctxt.rs
@@ -148,10 +148,6 @@ pub trait InferCtxtLike: Sized {
         true
     }
 
-    fn in_hir_typeck(&self) -> bool {
-        false
-    }
-
     fn typing_mode(&self) -> TypingMode<Self::Interner>;
 
     fn universe(&self) -> ty::UniverseIndex;
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index fa12d379c8c..98c9f6b51ab 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -2128,11 +2128,6 @@ impl<F: ?Sized + Future + Unpin, A: Allocator> Future for Box<F, A> {
 
 #[stable(feature = "box_error", since = "1.8.0")]
 impl<E: Error> Error for Box<E> {
-    #[allow(deprecated, deprecated_in_future)]
-    fn description(&self) -> &str {
-        Error::description(&**self)
-    }
-
     #[allow(deprecated)]
     fn cause(&self) -> Option<&dyn Error> {
         Error::cause(&**self)
diff --git a/library/alloc/src/boxed/convert.rs b/library/alloc/src/boxed/convert.rs
index 80626580202..45c46fb5263 100644
--- a/library/alloc/src/boxed/convert.rs
+++ b/library/alloc/src/boxed/convert.rs
@@ -608,12 +608,7 @@ impl<'a> From<String> for Box<dyn Error + Send + Sync + 'a> {
     fn from(err: String) -> Box<dyn Error + Send + Sync + 'a> {
         struct StringError(String);
 
-        impl Error for StringError {
-            #[allow(deprecated)]
-            fn description(&self) -> &str {
-                &self.0
-            }
-        }
+        impl Error for StringError {}
 
         impl fmt::Display for StringError {
             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index c4e599222e5..8b6d86a2888 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -40,30 +40,15 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT;
 
 /// An ordered map based on a [B-Tree].
 ///
-/// B-Trees represent a fundamental compromise between cache-efficiency and actually minimizing
-/// the amount of work performed in a search. In theory, a binary search tree (BST) is the optimal
-/// choice for a sorted map, as a perfectly balanced BST performs the theoretical minimum amount of
-/// comparisons necessary to find an element (log<sub>2</sub>n). However, in practice the way this
-/// is done is *very* inefficient for modern computer architectures. In particular, every element
-/// is stored in its own individually heap-allocated node. This means that every single insertion
-/// triggers a heap-allocation, and every single comparison should be a cache-miss. Since these
-/// are both notably expensive things to do in practice, we are forced to, at the very least,
-/// reconsider the BST strategy.
-///
-/// A B-Tree instead makes each node contain B-1 to 2B-1 elements in a contiguous array. By doing
-/// this, we reduce the number of allocations by a factor of B, and improve cache efficiency in
-/// searches. However, this does mean that searches will have to do *more* comparisons on average.
-/// The precise number of comparisons depends on the node search strategy used. For optimal cache
-/// efficiency, one could search the nodes linearly. For optimal comparisons, one could search
-/// the node using binary search. As a compromise, one could also perform a linear search
-/// that initially only checks every i<sup>th</sup> element for some choice of i.
+/// Given a key type with a [total order], an ordered map stores its entries in key order.
+/// That means that keys must be of a type that implements the [`Ord`] trait,
+/// such that two keys can always be compared to determine their [`Ordering`].
+/// Examples of keys with a total order are strings with lexicographical order,
+/// and numbers with their natural order.
 ///
-/// Currently, our implementation simply performs naive linear search. This provides excellent
-/// performance on *small* nodes of elements which are cheap to compare. However in the future we
-/// would like to further explore choosing the optimal search strategy based on the choice of B,
-/// and possibly other factors. Using linear search, searching for a random element is expected
-/// to take B * log(n) comparisons, which is generally worse than a BST. In practice,
-/// however, performance is excellent.
+/// Iterators obtained from functions such as [`BTreeMap::iter`], [`BTreeMap::into_iter`], [`BTreeMap::values`], or
+/// [`BTreeMap::keys`] produce their items in key order, and take worst-case logarithmic and
+/// amortized constant time per item returned.
 ///
 /// It is a logic error for a key to be modified in such a way that the key's ordering relative to
 /// any other key, as determined by the [`Ord`] trait, changes while it is in the map. This is
@@ -72,14 +57,6 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT;
 /// `BTreeMap` that observed the logic error and not result in undefined behavior. This could
 /// include panics, incorrect results, aborts, memory leaks, and non-termination.
 ///
-/// Iterators obtained from functions such as [`BTreeMap::iter`], [`BTreeMap::into_iter`], [`BTreeMap::values`], or
-/// [`BTreeMap::keys`] produce their items in order by key, and take worst-case logarithmic and
-/// amortized constant time per item returned.
-///
-/// [B-Tree]: https://en.wikipedia.org/wiki/B-tree
-/// [`Cell`]: core::cell::Cell
-/// [`RefCell`]: core::cell::RefCell
-///
 /// # Examples
 ///
 /// ```
@@ -169,6 +146,43 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT;
 /// // modify an entry before an insert with in-place mutation
 /// player_stats.entry("mana").and_modify(|mana| *mana += 200).or_insert(100);
 /// ```
+///
+/// # Background
+///
+/// A B-tree is (like) a [binary search tree], but adapted to the natural granularity that modern
+/// machines like to consume data at. This means that each node contains an entire array of elements,
+/// instead of just a single element.
+///
+/// B-Trees represent a fundamental compromise between cache-efficiency and actually minimizing
+/// the amount of work performed in a search. In theory, a binary search tree (BST) is the optimal
+/// choice for a sorted map, as a perfectly balanced BST performs the theoretical minimum number of
+/// comparisons necessary to find an element (log<sub>2</sub>n). However, in practice the way this
+/// is done is *very* inefficient for modern computer architectures. In particular, every element
+/// is stored in its own individually heap-allocated node. This means that every single insertion
+/// triggers a heap-allocation, and every comparison is a potential cache-miss due to the indirection.
+/// Since both heap-allocations and cache-misses are notably expensive in practice, we are forced to,
+/// at the very least, reconsider the BST strategy.
+///
+/// A B-Tree instead makes each node contain B-1 to 2B-1 elements in a contiguous array. By doing
+/// this, we reduce the number of allocations by a factor of B, and improve cache efficiency in
+/// searches. However, this does mean that searches will have to do *more* comparisons on average.
+/// The precise number of comparisons depends on the node search strategy used. For optimal cache
+/// efficiency, one could search the nodes linearly. For optimal comparisons, one could search
+/// the node using binary search. As a compromise, one could also perform a linear search
+/// that initially only checks every i<sup>th</sup> element for some choice of i.
+///
+/// Currently, our implementation simply performs naive linear search. This provides excellent
+/// performance on *small* nodes of elements which are cheap to compare. However in the future we
+/// would like to further explore choosing the optimal search strategy based on the choice of B,
+/// and possibly other factors. Using linear search, searching for a random element is expected
+/// to take B * log(n) comparisons, which is generally worse than a BST. In practice,
+/// however, performance is excellent.
+///
+/// [B-Tree]: https://en.wikipedia.org/wiki/B-tree
+/// [binary search tree]: https://en.wikipedia.org/wiki/Binary_search_tree
+/// [total order]: https://en.wikipedia.org/wiki/Total_order
+/// [`Cell`]: core::cell::Cell
+/// [`RefCell`]: core::cell::RefCell
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "BTreeMap")]
 #[rustc_insignificant_dtor]
diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs
index ea8fa363c38..ec9b774c308 100644
--- a/library/alloc/src/collections/btree/map/entry.rs
+++ b/library/alloc/src/collections/btree/map/entry.rs
@@ -136,10 +136,6 @@ impl<'a, K: Debug + Ord, V: Debug, A: Allocator + Clone> fmt::Display
 impl<'a, K: core::fmt::Debug + Ord, V: core::fmt::Debug> core::error::Error
     for crate::collections::btree_map::OccupiedError<'a, K, V>
 {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "key already exists"
-    }
 }
 
 impl<'a, K: Ord, V, A: Allocator + Clone> Entry<'a, K, V, A> {
diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs
index fe6c89a3094..b0c8c4b1ca4 100644
--- a/library/alloc/src/ffi/c_str.rs
+++ b/library/alloc/src/ffi/c_str.rs
@@ -1061,17 +1061,10 @@ impl IntoStringError {
     }
 }
 
-impl IntoStringError {
-    fn description(&self) -> &str {
-        "C string contained non-utf8 bytes"
-    }
-}
-
 #[stable(feature = "cstring_into", since = "1.7.0")]
 impl fmt::Display for IntoStringError {
-    #[allow(deprecated, deprecated_in_future)]
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.description().fmt(f)
+        "C string contained non-utf8 bytes".fmt(f)
     }
 }
 
@@ -1291,23 +1284,13 @@ impl PartialEq<CString> for Cow<'_, CStr> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl core::error::Error for NulError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "nul byte found in data"
-    }
-}
+impl core::error::Error for NulError {}
 
 #[stable(feature = "cstring_from_vec_with_nul", since = "1.58.0")]
 impl core::error::Error for FromVecWithNulError {}
 
 #[stable(feature = "cstring_into", since = "1.7.0")]
 impl core::error::Error for IntoStringError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "C string contained non-utf8 bytes"
-    }
-
     fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
         Some(&self.error)
     }
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 639c5d4c930..711092ae8eb 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -159,6 +159,7 @@
 #![feature(unicode_internals)]
 #![feature(unsize)]
 #![feature(unwrap_infallible)]
+#![feature(wtf8_internals)]
 // tidy-alphabetical-end
 //
 // Language features:
@@ -232,6 +233,8 @@ pub mod sync;
 #[cfg(all(not(no_global_oom_handling), not(no_rc), not(no_sync)))]
 pub mod task;
 pub mod vec;
+#[cfg(all(not(no_rc), not(no_sync), not(no_global_oom_handling)))]
+pub mod wtf8;
 
 #[doc(hidden)]
 #[unstable(feature = "liballoc_internals", issue = "none", reason = "implementation detail")]
diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs
index 40716755aad..fd05f9ca464 100644
--- a/library/alloc/src/raw_vec/mod.rs
+++ b/library/alloc/src/raw_vec/mod.rs
@@ -155,7 +155,7 @@ impl RawVecInner<Global> {
 }
 
 // Tiny Vecs are dumb. Skip to:
-// - 8 if the element size is 1, because any heap allocators is likely
+// - 8 if the element size is 1, because any heap allocator is likely
 //   to round up a request of less than 8 bytes to at least 8 bytes.
 // - 4 if elements are moderate-sized (<= 1 KiB).
 // - 1 otherwise, to avoid wasting too much space for very short Vecs.
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index 9eacbf00e42..1d0dd4be1b6 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -2285,20 +2285,10 @@ impl fmt::Display for FromUtf16Error {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl Error for FromUtf8Error {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "invalid utf-8"
-    }
-}
+impl Error for FromUtf8Error {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl Error for FromUtf16Error {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "invalid utf-16"
-    }
-}
+impl Error for FromUtf16Error {}
 
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -2949,68 +2939,41 @@ impl SpecToString for i8 {
     }
 }
 
-// Generic/generated code can sometimes have multiple, nested references
-// for strings, including `&&&str`s that would never be written
-// by hand. This macro generates twelve layers of nested `&`-impl
-// for primitive strings.
-#[cfg(not(no_global_oom_handling))]
-macro_rules! to_string_str_wrap_in_ref {
-    {x $($x:ident)*} => {
-        &to_string_str_wrap_in_ref! { $($x)* }
-    };
-    {} => { str };
-}
-#[cfg(not(no_global_oom_handling))]
-macro_rules! to_string_expr_wrap_in_deref {
-    {$self:expr ; x $($x:ident)*} => {
-        *(to_string_expr_wrap_in_deref! { $self ; $($x)* })
-    };
-    {$self:expr ;} => { $self };
-}
 #[cfg(not(no_global_oom_handling))]
 macro_rules! to_string_str {
-    {$($($x:ident)*),+} => {
+    {$($type:ty,)*} => {
         $(
-            impl SpecToString for to_string_str_wrap_in_ref!($($x)*) {
+            impl SpecToString for $type {
                 #[inline]
                 fn spec_to_string(&self) -> String {
-                    String::from(to_string_expr_wrap_in_deref!(self ; $($x)*))
+                    let s: &str = self;
+                    String::from(s)
                 }
             }
-        )+
+        )*
     };
 }
 
 #[cfg(not(no_global_oom_handling))]
 to_string_str! {
-    x x x x x x x x x x x x,
-    x x x x x x x x x x x,
-    x x x x x x x x x x,
-    x x x x x x x x x,
-    x x x x x x x x,
-    x x x x x x x,
-    x x x x x x,
-    x x x x x,
-    x x x x,
-    x x x,
-    x x,
-    x,
-}
-
-#[cfg(not(no_global_oom_handling))]
-impl SpecToString for Cow<'_, str> {
-    #[inline]
-    fn spec_to_string(&self) -> String {
-        self[..].to_owned()
-    }
-}
-
-#[cfg(not(no_global_oom_handling))]
-impl SpecToString for String {
-    #[inline]
-    fn spec_to_string(&self) -> String {
-        self.to_owned()
-    }
+    Cow<'_, str>,
+    String,
+    // Generic/generated code can sometimes have multiple, nested references
+    // for strings, including `&&&str`s that would never be written
+    // by hand.
+    &&&&&&&&&&&&str,
+    &&&&&&&&&&&str,
+    &&&&&&&&&&str,
+    &&&&&&&&&str,
+    &&&&&&&&str,
+    &&&&&&&str,
+    &&&&&&str,
+    &&&&&str,
+    &&&&str,
+    &&&str,
+    &&str,
+    &str,
+    str,
 }
 
 #[cfg(not(no_global_oom_handling))]
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 29caa7bc539..a21b6880674 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -4113,11 +4113,6 @@ impl<T: ?Sized, A: Allocator> Drop for UniqueArcUninit<T, A> {
 
 #[stable(feature = "arc_error", since = "1.52.0")]
 impl<T: core::error::Error + ?Sized> core::error::Error for Arc<T> {
-    #[allow(deprecated, deprecated_in_future)]
-    fn description(&self) -> &str {
-        core::error::Error::description(&**self)
-    }
-
     #[allow(deprecated)]
     fn cause(&self) -> Option<&dyn core::error::Error> {
         core::error::Error::cause(&**self)
diff --git a/library/alloc/src/wtf8/mod.rs b/library/alloc/src/wtf8/mod.rs
new file mode 100644
index 00000000000..047994adc44
--- /dev/null
+++ b/library/alloc/src/wtf8/mod.rs
@@ -0,0 +1,562 @@
+//! Heap-allocated counterpart to core `wtf8` module.
+#![unstable(
+    feature = "wtf8_internals",
+    issue = "none",
+    reason = "this is internal code for representing OsStr on some platforms and not a public API"
+)]
+// rustdoc bug: doc(hidden) on the module won't stop types in the module from showing up in trait
+// implementations, so, we'll have to add more doc(hidden)s anyway
+#![doc(hidden)]
+
+// Note: This module is also included in the alloctests crate using #[path] to
+// run the tests. See the comment there for an explanation why this is the case.
+
+#[cfg(test)]
+mod tests;
+
+use core::char::{MAX_LEN_UTF8, encode_utf8_raw};
+use core::hash::{Hash, Hasher};
+pub use core::wtf8::{CodePoint, Wtf8};
+#[cfg(not(test))]
+pub use core::wtf8::{EncodeWide, Wtf8CodePoints};
+use core::{fmt, mem, ops, str};
+
+use crate::borrow::{Cow, ToOwned};
+use crate::boxed::Box;
+use crate::collections::TryReserveError;
+#[cfg(not(test))]
+use crate::rc::Rc;
+use crate::string::String;
+#[cfg(all(not(test), target_has_atomic = "ptr"))]
+use crate::sync::Arc;
+use crate::vec::Vec;
+
+/// An owned, growable string of well-formed WTF-8 data.
+///
+/// Similar to `String`, but can additionally contain surrogate code points
+/// if they’re not in a surrogate pair.
+#[derive(Eq, PartialEq, Ord, PartialOrd, Clone)]
+#[doc(hidden)]
+pub struct Wtf8Buf {
+    bytes: Vec<u8>,
+
+    /// Do we know that `bytes` holds a valid UTF-8 encoding? We can easily
+    /// know this if we're constructed from a `String` or `&str`.
+    ///
+    /// It is possible for `bytes` to have valid UTF-8 without this being
+    /// set, such as when we're concatenating `&Wtf8`'s and surrogates become
+    /// paired, as we don't bother to rescan the entire string.
+    is_known_utf8: bool,
+}
+
+impl ops::Deref for Wtf8Buf {
+    type Target = Wtf8;
+
+    fn deref(&self) -> &Wtf8 {
+        self.as_slice()
+    }
+}
+
+impl ops::DerefMut for Wtf8Buf {
+    fn deref_mut(&mut self) -> &mut Wtf8 {
+        self.as_mut_slice()
+    }
+}
+
+/// Formats the string in double quotes, with characters escaped according to
+/// [`char::escape_debug`] and unpaired surrogates represented as `\u{xxxx}`,
+/// where each `x` is a hexadecimal digit.
+///
+/// For example, the code units [U+0061, U+D800, U+000A] are formatted as
+/// `"a\u{D800}\n"`.
+impl fmt::Debug for Wtf8Buf {
+    #[inline]
+    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Debug::fmt(&**self, formatter)
+    }
+}
+
+/// Formats the string with unpaired surrogates substituted with the replacement
+/// character, U+FFFD.
+impl fmt::Display for Wtf8Buf {
+    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+        if let Some(s) = self.as_known_utf8() {
+            fmt::Display::fmt(s, formatter)
+        } else {
+            fmt::Display::fmt(&**self, formatter)
+        }
+    }
+}
+
+#[cfg_attr(test, allow(dead_code))]
+impl Wtf8Buf {
+    /// Creates a new, empty WTF-8 string.
+    #[inline]
+    pub fn new() -> Wtf8Buf {
+        Wtf8Buf { bytes: Vec::new(), is_known_utf8: true }
+    }
+
+    /// Creates a new, empty WTF-8 string with pre-allocated capacity for `capacity` bytes.
+    #[inline]
+    pub fn with_capacity(capacity: usize) -> Wtf8Buf {
+        Wtf8Buf { bytes: Vec::with_capacity(capacity), is_known_utf8: true }
+    }
+
+    /// Creates a WTF-8 string from a WTF-8 byte vec.
+    ///
+    /// Since the byte vec is not checked for valid WTF-8, this function is
+    /// marked unsafe.
+    #[inline]
+    pub unsafe fn from_bytes_unchecked(value: Vec<u8>) -> Wtf8Buf {
+        Wtf8Buf { bytes: value, is_known_utf8: false }
+    }
+
+    /// Creates a WTF-8 string from a UTF-8 `String`.
+    ///
+    /// This takes ownership of the `String` and does not copy.
+    ///
+    /// Since WTF-8 is a superset of UTF-8, this always succeeds.
+    #[inline]
+    pub const fn from_string(string: String) -> Wtf8Buf {
+        Wtf8Buf { bytes: string.into_bytes(), is_known_utf8: true }
+    }
+
+    /// Creates a WTF-8 string from a UTF-8 `&str` slice.
+    ///
+    /// This copies the content of the slice.
+    ///
+    /// Since WTF-8 is a superset of UTF-8, this always succeeds.
+    #[inline]
+    pub fn from_str(s: &str) -> Wtf8Buf {
+        Wtf8Buf { bytes: s.as_bytes().to_vec(), is_known_utf8: true }
+    }
+
+    pub fn clear(&mut self) {
+        self.bytes.clear();
+        self.is_known_utf8 = true;
+    }
+
+    /// Creates a WTF-8 string from a potentially ill-formed UTF-16 slice of 16-bit code units.
+    ///
+    /// This is lossless: calling `.encode_wide()` on the resulting string
+    /// will always return the original code units.
+    pub fn from_wide(v: &[u16]) -> Wtf8Buf {
+        let mut string = Wtf8Buf::with_capacity(v.len());
+        for item in char::decode_utf16(v.iter().cloned()) {
+            match item {
+                Ok(ch) => string.push_char(ch),
+                Err(surrogate) => {
+                    let surrogate = surrogate.unpaired_surrogate();
+                    // Surrogates are known to be in the code point range.
+                    let code_point = unsafe { CodePoint::from_u32_unchecked(surrogate as u32) };
+                    // The string will now contain an unpaired surrogate.
+                    string.is_known_utf8 = false;
+                    // Skip the WTF-8 concatenation check,
+                    // surrogate pairs are already decoded by decode_utf16
+                    unsafe {
+                        string.push_code_point_unchecked(code_point);
+                    }
+                }
+            }
+        }
+        string
+    }
+
+    /// Appends the given `char` to the end of this string.
+    /// This does **not** include the WTF-8 concatenation check or `is_known_utf8` check.
+    /// Copied from String::push.
+    unsafe fn push_code_point_unchecked(&mut self, code_point: CodePoint) {
+        let mut bytes = [0; MAX_LEN_UTF8];
+        let bytes = encode_utf8_raw(code_point.to_u32(), &mut bytes);
+        self.bytes.extend_from_slice(bytes)
+    }
+
+    #[inline]
+    pub fn as_slice(&self) -> &Wtf8 {
+        unsafe { Wtf8::from_bytes_unchecked(&self.bytes) }
+    }
+
+    #[inline]
+    pub fn as_mut_slice(&mut self) -> &mut Wtf8 {
+        // Safety: `Wtf8` doesn't expose any way to mutate the bytes that would
+        // cause them to change from well-formed UTF-8 to ill-formed UTF-8,
+        // which would break the assumptions of the `is_known_utf8` field.
+        unsafe { Wtf8::from_mut_bytes_unchecked(&mut self.bytes) }
+    }
+
+    /// Converts the string to UTF-8 without validation, if it was created from
+    /// valid UTF-8.
+    #[inline]
+    fn as_known_utf8(&self) -> Option<&str> {
+        if self.is_known_utf8 {
+            // SAFETY: The buffer is known to be valid UTF-8.
+            Some(unsafe { str::from_utf8_unchecked(self.as_bytes()) })
+        } else {
+            None
+        }
+    }
+
+    /// Reserves capacity for at least `additional` more bytes to be inserted
+    /// in the given `Wtf8Buf`.
+    /// The collection may reserve more space to avoid frequent reallocations.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the new capacity exceeds `isize::MAX` bytes.
+    #[inline]
+    pub fn reserve(&mut self, additional: usize) {
+        self.bytes.reserve(additional)
+    }
+
+    /// Tries to reserve capacity for at least `additional` more bytes to be
+    /// inserted in the given `Wtf8Buf`. The `Wtf8Buf` may reserve more space to
+    /// avoid frequent reallocations. After calling `try_reserve`, capacity will
+    /// be greater than or equal to `self.len() + additional`. Does nothing if
+    /// capacity is already sufficient. This method preserves the contents even
+    /// if an error occurs.
+    ///
+    /// # Errors
+    ///
+    /// If the capacity overflows, or the allocator reports a failure, then an error
+    /// is returned.
+    #[inline]
+    pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
+        self.bytes.try_reserve(additional)
+    }
+
+    #[inline]
+    pub fn reserve_exact(&mut self, additional: usize) {
+        self.bytes.reserve_exact(additional)
+    }
+
+    /// Tries to reserve the minimum capacity for exactly `additional` more
+    /// bytes to be inserted in the given `Wtf8Buf`. After calling
+    /// `try_reserve_exact`, capacity will be greater than or equal to
+    /// `self.len() + additional` if it returns `Ok(())`.
+    /// Does nothing if the capacity is already sufficient.
+    ///
+    /// Note that the allocator may give the `Wtf8Buf` more space than it
+    /// requests. Therefore, capacity can not be relied upon to be precisely
+    /// minimal. Prefer [`try_reserve`] if future insertions are expected.
+    ///
+    /// [`try_reserve`]: Wtf8Buf::try_reserve
+    ///
+    /// # Errors
+    ///
+    /// If the capacity overflows, or the allocator reports a failure, then an error
+    /// is returned.
+    #[inline]
+    pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
+        self.bytes.try_reserve_exact(additional)
+    }
+
+    #[inline]
+    pub fn shrink_to_fit(&mut self) {
+        self.bytes.shrink_to_fit()
+    }
+
+    #[inline]
+    pub fn shrink_to(&mut self, min_capacity: usize) {
+        self.bytes.shrink_to(min_capacity)
+    }
+
+    #[inline]
+    pub fn leak<'a>(self) -> &'a mut Wtf8 {
+        unsafe { Wtf8::from_mut_bytes_unchecked(self.bytes.leak()) }
+    }
+
+    /// Returns the number of bytes that this string buffer can hold without reallocating.
+    #[inline]
+    pub fn capacity(&self) -> usize {
+        self.bytes.capacity()
+    }
+
+    /// Append a UTF-8 slice at the end of the string.
+    #[inline]
+    pub fn push_str(&mut self, other: &str) {
+        self.bytes.extend_from_slice(other.as_bytes())
+    }
+
+    /// Append a WTF-8 slice at the end of the string.
+    ///
+    /// This replaces newly paired surrogates at the boundary
+    /// with a supplementary code point,
+    /// like concatenating ill-formed UTF-16 strings effectively would.
+    #[inline]
+    pub fn push_wtf8(&mut self, other: &Wtf8) {
+        match ((&*self).final_lead_surrogate(), other.initial_trail_surrogate()) {
+            // Replace newly paired surrogates by a supplementary code point.
+            (Some(lead), Some(trail)) => {
+                let len_without_lead_surrogate = self.len() - 3;
+                self.bytes.truncate(len_without_lead_surrogate);
+                let other_without_trail_surrogate = &other.as_bytes()[3..];
+                // 4 bytes for the supplementary code point
+                self.bytes.reserve(4 + other_without_trail_surrogate.len());
+                self.push_char(decode_surrogate_pair(lead, trail));
+                self.bytes.extend_from_slice(other_without_trail_surrogate);
+            }
+            _ => {
+                // If we'll be pushing a string containing a surrogate, we may
+                // no longer have UTF-8.
+                if self.is_known_utf8 && other.next_surrogate(0).is_some() {
+                    self.is_known_utf8 = false;
+                }
+
+                self.bytes.extend_from_slice(other.as_bytes());
+            }
+        }
+    }
+
+    /// Append a Unicode scalar value at the end of the string.
+    #[inline]
+    pub fn push_char(&mut self, c: char) {
+        // SAFETY: It's always safe to push a char.
+        unsafe { self.push_code_point_unchecked(CodePoint::from_char(c)) }
+    }
+
+    /// Append a code point at the end of the string.
+    ///
+    /// This replaces newly paired surrogates at the boundary
+    /// with a supplementary code point,
+    /// like concatenating ill-formed UTF-16 strings effectively would.
+    #[inline]
+    pub fn push(&mut self, code_point: CodePoint) {
+        if let Some(trail) = code_point.to_trail_surrogate() {
+            if let Some(lead) = (&*self).final_lead_surrogate() {
+                let len_without_lead_surrogate = self.len() - 3;
+                self.bytes.truncate(len_without_lead_surrogate);
+                self.push_char(decode_surrogate_pair(lead, trail));
+                return;
+            }
+
+            // We're pushing a trailing surrogate.
+            self.is_known_utf8 = false;
+        } else if code_point.to_lead_surrogate().is_some() {
+            // We're pushing a leading surrogate.
+            self.is_known_utf8 = false;
+        }
+
+        // No newly paired surrogates at the boundary.
+        unsafe { self.push_code_point_unchecked(code_point) }
+    }
+
+    /// Shortens a string to the specified length.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `new_len` > current length,
+    /// or if `new_len` is not a code point boundary.
+    #[inline]
+    pub fn truncate(&mut self, new_len: usize) {
+        assert!(self.is_code_point_boundary(new_len));
+        self.bytes.truncate(new_len)
+    }
+
+    /// Consumes the WTF-8 string and tries to convert it to a vec of bytes.
+    #[inline]
+    pub fn into_bytes(self) -> Vec<u8> {
+        self.bytes
+    }
+
+    /// Consumes the WTF-8 string and tries to convert it to UTF-8.
+    ///
+    /// This does not copy the data.
+    ///
+    /// If the contents are not well-formed UTF-8
+    /// (that is, if the string contains surrogates),
+    /// the original WTF-8 string is returned instead.
+    pub fn into_string(self) -> Result<String, Wtf8Buf> {
+        if self.is_known_utf8 || self.next_surrogate(0).is_none() {
+            Ok(unsafe { String::from_utf8_unchecked(self.bytes) })
+        } else {
+            Err(self)
+        }
+    }
+
+    /// Consumes the WTF-8 string and converts it lossily to UTF-8.
+    ///
+    /// This does not copy the data (but may overwrite parts of it in place).
+    ///
+    /// Surrogates are replaced with `"\u{FFFD}"` (the replacement character “�”)
+    pub fn into_string_lossy(mut self) -> String {
+        if !self.is_known_utf8 {
+            let mut pos = 0;
+            while let Some((surrogate_pos, _)) = self.next_surrogate(pos) {
+                pos = surrogate_pos + 3;
+                // Surrogates and the replacement character are all 3 bytes, so
+                // they can substituted in-place.
+                self.bytes[surrogate_pos..pos].copy_from_slice("\u{FFFD}".as_bytes());
+            }
+        }
+        unsafe { String::from_utf8_unchecked(self.bytes) }
+    }
+
+    /// Converts this `Wtf8Buf` into a boxed `Wtf8`.
+    #[inline]
+    pub fn into_box(self) -> Box<Wtf8> {
+        // SAFETY: relies on `Wtf8` being `repr(transparent)`.
+        unsafe { mem::transmute(self.bytes.into_boxed_slice()) }
+    }
+
+    /// Converts a `Box<Wtf8>` into a `Wtf8Buf`.
+    pub fn from_box(boxed: Box<Wtf8>) -> Wtf8Buf {
+        let bytes: Box<[u8]> = unsafe { mem::transmute(boxed) };
+        Wtf8Buf { bytes: bytes.into_vec(), is_known_utf8: false }
+    }
+
+    /// Provides plumbing to core `Vec::extend_from_slice`.
+    /// More well behaving alternative to allowing outer types
+    /// full mutable access to the core `Vec`.
+    #[inline]
+    pub unsafe fn extend_from_slice_unchecked(&mut self, other: &[u8]) {
+        self.bytes.extend_from_slice(other);
+        self.is_known_utf8 = false;
+    }
+}
+
+/// Creates a new WTF-8 string from an iterator of code points.
+///
+/// This replaces surrogate code point pairs with supplementary code points,
+/// like concatenating ill-formed UTF-16 strings effectively would.
+impl FromIterator<CodePoint> for Wtf8Buf {
+    fn from_iter<T: IntoIterator<Item = CodePoint>>(iter: T) -> Wtf8Buf {
+        let mut string = Wtf8Buf::new();
+        string.extend(iter);
+        string
+    }
+}
+
+/// Append code points from an iterator to the string.
+///
+/// This replaces surrogate code point pairs with supplementary code points,
+/// like concatenating ill-formed UTF-16 strings effectively would.
+impl Extend<CodePoint> for Wtf8Buf {
+    fn extend<T: IntoIterator<Item = CodePoint>>(&mut self, iter: T) {
+        let iterator = iter.into_iter();
+        let (low, _high) = iterator.size_hint();
+        // Lower bound of one byte per code point (ASCII only)
+        self.bytes.reserve(low);
+        iterator.for_each(move |code_point| self.push(code_point));
+    }
+
+    #[inline]
+    fn extend_one(&mut self, code_point: CodePoint) {
+        self.push(code_point);
+    }
+
+    #[inline]
+    fn extend_reserve(&mut self, additional: usize) {
+        // Lower bound of one byte per code point (ASCII only)
+        self.bytes.reserve(additional);
+    }
+}
+
+/// Creates an owned `Wtf8Buf` from a borrowed `Wtf8`.
+pub(super) fn to_owned(slice: &Wtf8) -> Wtf8Buf {
+    Wtf8Buf { bytes: slice.as_bytes().to_vec(), is_known_utf8: false }
+}
+
+/// Lossily converts the string to UTF-8.
+/// Returns a UTF-8 `&str` slice if the contents are well-formed in UTF-8.
+///
+/// Surrogates are replaced with `"\u{FFFD}"` (the replacement character “�”).
+///
+/// This only copies the data if necessary (if it contains any surrogate).
+pub(super) fn to_string_lossy(slice: &Wtf8) -> Cow<'_, str> {
+    let Some((surrogate_pos, _)) = slice.next_surrogate(0) else {
+        return Cow::Borrowed(unsafe { str::from_utf8_unchecked(slice.as_bytes()) });
+    };
+    let wtf8_bytes = slice.as_bytes();
+    let mut utf8_bytes = Vec::with_capacity(slice.len());
+    utf8_bytes.extend_from_slice(&wtf8_bytes[..surrogate_pos]);
+    utf8_bytes.extend_from_slice("\u{FFFD}".as_bytes());
+    let mut pos = surrogate_pos + 3;
+    loop {
+        match slice.next_surrogate(pos) {
+            Some((surrogate_pos, _)) => {
+                utf8_bytes.extend_from_slice(&wtf8_bytes[pos..surrogate_pos]);
+                utf8_bytes.extend_from_slice("\u{FFFD}".as_bytes());
+                pos = surrogate_pos + 3;
+            }
+            None => {
+                utf8_bytes.extend_from_slice(&wtf8_bytes[pos..]);
+                return Cow::Owned(unsafe { String::from_utf8_unchecked(utf8_bytes) });
+            }
+        }
+    }
+}
+
+#[inline]
+pub(super) fn clone_into(slice: &Wtf8, buf: &mut Wtf8Buf) {
+    buf.is_known_utf8 = false;
+    slice.as_bytes().clone_into(&mut buf.bytes);
+}
+
+#[cfg(not(test))]
+impl Wtf8 {
+    #[rustc_allow_incoherent_impl]
+    pub fn to_owned(&self) -> Wtf8Buf {
+        to_owned(self)
+    }
+
+    #[rustc_allow_incoherent_impl]
+    pub fn clone_into(&self, buf: &mut Wtf8Buf) {
+        clone_into(self, buf)
+    }
+
+    #[rustc_allow_incoherent_impl]
+    pub fn to_string_lossy(&self) -> Cow<'_, str> {
+        to_string_lossy(self)
+    }
+
+    #[rustc_allow_incoherent_impl]
+    pub fn into_box(&self) -> Box<Wtf8> {
+        let boxed: Box<[u8]> = self.as_bytes().into();
+        unsafe { mem::transmute(boxed) }
+    }
+
+    #[rustc_allow_incoherent_impl]
+    pub fn empty_box() -> Box<Wtf8> {
+        let boxed: Box<[u8]> = Default::default();
+        unsafe { mem::transmute(boxed) }
+    }
+
+    #[cfg(target_has_atomic = "ptr")]
+    #[rustc_allow_incoherent_impl]
+    pub fn into_arc(&self) -> Arc<Wtf8> {
+        let arc: Arc<[u8]> = Arc::from(self.as_bytes());
+        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Wtf8) }
+    }
+
+    #[rustc_allow_incoherent_impl]
+    pub fn into_rc(&self) -> Rc<Wtf8> {
+        let rc: Rc<[u8]> = Rc::from(self.as_bytes());
+        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Wtf8) }
+    }
+
+    #[inline]
+    #[rustc_allow_incoherent_impl]
+    pub fn to_ascii_lowercase(&self) -> Wtf8Buf {
+        Wtf8Buf { bytes: self.as_bytes().to_ascii_lowercase(), is_known_utf8: false }
+    }
+
+    #[inline]
+    #[rustc_allow_incoherent_impl]
+    pub fn to_ascii_uppercase(&self) -> Wtf8Buf {
+        Wtf8Buf { bytes: self.as_bytes().to_ascii_uppercase(), is_known_utf8: false }
+    }
+}
+
+#[inline]
+fn decode_surrogate_pair(lead: u16, trail: u16) -> char {
+    let code_point = 0x10000 + ((((lead - 0xD800) as u32) << 10) | (trail - 0xDC00) as u32);
+    unsafe { char::from_u32_unchecked(code_point) }
+}
+
+impl Hash for Wtf8Buf {
+    #[inline]
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        state.write(&self.bytes);
+        0xfeu8.hash(state)
+    }
+}
diff --git a/library/std/src/sys_common/wtf8/tests.rs b/library/alloc/src/wtf8/tests.rs
index b57c99a8452..291f63f9f9e 100644
--- a/library/std/src/sys_common/wtf8/tests.rs
+++ b/library/alloc/src/wtf8/tests.rs
@@ -1,3 +1,5 @@
+use realalloc::string::ToString;
+
 use super::*;
 
 #[test]
@@ -82,82 +84,85 @@ fn code_point_to_char_lossy() {
 
 #[test]
 fn wtf8buf_new() {
-    assert_eq!(Wtf8Buf::new().bytes, b"");
+    assert_eq!(Wtf8Buf::new().as_bytes(), b"");
 }
 
 #[test]
 fn wtf8buf_from_str() {
-    assert_eq!(Wtf8Buf::from_str("").bytes, b"");
-    assert_eq!(Wtf8Buf::from_str("aé 💩").bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
+    assert_eq!(Wtf8Buf::from_str("").as_bytes(), b"");
+    assert_eq!(Wtf8Buf::from_str("aé 💩").as_bytes(), b"a\xC3\xA9 \xF0\x9F\x92\xA9");
 }
 
 #[test]
 fn wtf8buf_from_string() {
-    assert_eq!(Wtf8Buf::from_string(String::from("")).bytes, b"");
-    assert_eq!(Wtf8Buf::from_string(String::from("aé 💩")).bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
+    assert_eq!(Wtf8Buf::from_string(String::from("")).as_bytes(), b"");
+    assert_eq!(
+        Wtf8Buf::from_string(String::from("aé 💩")).as_bytes(),
+        b"a\xC3\xA9 \xF0\x9F\x92\xA9"
+    );
 }
 
 #[test]
 fn wtf8buf_from_wide() {
     let buf = Wtf8Buf::from_wide(&[]);
-    assert_eq!(buf.bytes, b"");
+    assert_eq!(buf.as_bytes(), b"");
     assert!(buf.is_known_utf8);
 
     let buf = Wtf8Buf::from_wide(&[0x61, 0xE9, 0x20, 0xD83D, 0xDCA9]);
-    assert_eq!(buf.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
+    assert_eq!(buf.as_bytes(), b"a\xC3\xA9 \xF0\x9F\x92\xA9");
     assert!(buf.is_known_utf8);
 
     let buf = Wtf8Buf::from_wide(&[0x61, 0xE9, 0x20, 0xD83D, 0xD83D, 0xDCA9]);
-    assert_eq!(buf.bytes, b"a\xC3\xA9 \xED\xA0\xBD\xF0\x9F\x92\xA9");
+    assert_eq!(buf.as_bytes(), b"a\xC3\xA9 \xED\xA0\xBD\xF0\x9F\x92\xA9");
     assert!(!buf.is_known_utf8);
 
     let buf = Wtf8Buf::from_wide(&[0xD800]);
-    assert_eq!(buf.bytes, b"\xED\xA0\x80");
+    assert_eq!(buf.as_bytes(), b"\xED\xA0\x80");
     assert!(!buf.is_known_utf8);
 
     let buf = Wtf8Buf::from_wide(&[0xDBFF]);
-    assert_eq!(buf.bytes, b"\xED\xAF\xBF");
+    assert_eq!(buf.as_bytes(), b"\xED\xAF\xBF");
     assert!(!buf.is_known_utf8);
 
     let buf = Wtf8Buf::from_wide(&[0xDC00]);
-    assert_eq!(buf.bytes, b"\xED\xB0\x80");
+    assert_eq!(buf.as_bytes(), b"\xED\xB0\x80");
     assert!(!buf.is_known_utf8);
 
     let buf = Wtf8Buf::from_wide(&[0xDFFF]);
-    assert_eq!(buf.bytes, b"\xED\xBF\xBF");
+    assert_eq!(buf.as_bytes(), b"\xED\xBF\xBF");
     assert!(!buf.is_known_utf8);
 }
 
 #[test]
 fn wtf8buf_push_str() {
     let mut string = Wtf8Buf::new();
-    assert_eq!(string.bytes, b"");
+    assert_eq!(string.as_bytes(), b"");
     assert!(string.is_known_utf8);
 
     string.push_str("aé 💩");
-    assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
+    assert_eq!(string.as_bytes(), b"a\xC3\xA9 \xF0\x9F\x92\xA9");
     assert!(string.is_known_utf8);
 }
 
 #[test]
 fn wtf8buf_push_char() {
     let mut string = Wtf8Buf::from_str("aé ");
-    assert_eq!(string.bytes, b"a\xC3\xA9 ");
+    assert_eq!(string.as_bytes(), b"a\xC3\xA9 ");
     assert!(string.is_known_utf8);
 
     string.push_char('💩');
-    assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
+    assert_eq!(string.as_bytes(), b"a\xC3\xA9 \xF0\x9F\x92\xA9");
     assert!(string.is_known_utf8);
 }
 
 #[test]
 fn wtf8buf_push() {
     let mut string = Wtf8Buf::from_str("aé ");
-    assert_eq!(string.bytes, b"a\xC3\xA9 ");
+    assert_eq!(string.as_bytes(), b"a\xC3\xA9 ");
     assert!(string.is_known_utf8);
 
     string.push(CodePoint::from_char('💩'));
-    assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
+    assert_eq!(string.as_bytes(), b"a\xC3\xA9 \xF0\x9F\x92\xA9");
     assert!(string.is_known_utf8);
 
     fn c(value: u32) -> CodePoint {
@@ -168,53 +173,53 @@ fn wtf8buf_push() {
     string.push(c(0xD83D)); // lead
     assert!(!string.is_known_utf8);
     string.push(c(0xDCA9)); // trail
-    assert_eq!(string.bytes, b"\xF0\x9F\x92\xA9"); // Magic!
+    assert_eq!(string.as_bytes(), b"\xF0\x9F\x92\xA9"); // Magic!
 
     let mut string = Wtf8Buf::new();
     string.push(c(0xD83D)); // lead
     assert!(!string.is_known_utf8);
     string.push(c(0x20)); // not surrogate
     string.push(c(0xDCA9)); // trail
-    assert_eq!(string.bytes, b"\xED\xA0\xBD \xED\xB2\xA9");
+    assert_eq!(string.as_bytes(), b"\xED\xA0\xBD \xED\xB2\xA9");
 
     let mut string = Wtf8Buf::new();
     string.push(c(0xD800)); // lead
     assert!(!string.is_known_utf8);
     string.push(c(0xDBFF)); // lead
-    assert_eq!(string.bytes, b"\xED\xA0\x80\xED\xAF\xBF");
+    assert_eq!(string.as_bytes(), b"\xED\xA0\x80\xED\xAF\xBF");
 
     let mut string = Wtf8Buf::new();
     string.push(c(0xD800)); // lead
     assert!(!string.is_known_utf8);
     string.push(c(0xE000)); // not surrogate
-    assert_eq!(string.bytes, b"\xED\xA0\x80\xEE\x80\x80");
+    assert_eq!(string.as_bytes(), b"\xED\xA0\x80\xEE\x80\x80");
 
     let mut string = Wtf8Buf::new();
     string.push(c(0xD7FF)); // not surrogate
     assert!(string.is_known_utf8);
     string.push(c(0xDC00)); // trail
     assert!(!string.is_known_utf8);
-    assert_eq!(string.bytes, b"\xED\x9F\xBF\xED\xB0\x80");
+    assert_eq!(string.as_bytes(), b"\xED\x9F\xBF\xED\xB0\x80");
 
     let mut string = Wtf8Buf::new();
     string.push(c(0x61)); // not surrogate, < 3 bytes
     assert!(string.is_known_utf8);
     string.push(c(0xDC00)); // trail
     assert!(!string.is_known_utf8);
-    assert_eq!(string.bytes, b"\x61\xED\xB0\x80");
+    assert_eq!(string.as_bytes(), b"\x61\xED\xB0\x80");
 
     let mut string = Wtf8Buf::new();
     string.push(c(0xDC00)); // trail
     assert!(!string.is_known_utf8);
-    assert_eq!(string.bytes, b"\xED\xB0\x80");
+    assert_eq!(string.as_bytes(), b"\xED\xB0\x80");
 }
 
 #[test]
 fn wtf8buf_push_wtf8() {
     let mut string = Wtf8Buf::from_str("aé");
-    assert_eq!(string.bytes, b"a\xC3\xA9");
+    assert_eq!(string.as_bytes(), b"a\xC3\xA9");
     string.push_wtf8(Wtf8::from_str(" 💩"));
-    assert_eq!(string.bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
+    assert_eq!(string.as_bytes(), b"a\xC3\xA9 \xF0\x9F\x92\xA9");
     assert!(string.is_known_utf8);
 
     fn w(v: &[u8]) -> &Wtf8 {
@@ -224,42 +229,42 @@ fn wtf8buf_push_wtf8() {
     let mut string = Wtf8Buf::new();
     string.push_wtf8(w(b"\xED\xA0\xBD")); // lead
     string.push_wtf8(w(b"\xED\xB2\xA9")); // trail
-    assert_eq!(string.bytes, b"\xF0\x9F\x92\xA9"); // Magic!
+    assert_eq!(string.as_bytes(), b"\xF0\x9F\x92\xA9"); // Magic!
 
     let mut string = Wtf8Buf::new();
     string.push_wtf8(w(b"\xED\xA0\xBD")); // lead
     string.push_wtf8(w(b" ")); // not surrogate
     string.push_wtf8(w(b"\xED\xB2\xA9")); // trail
-    assert_eq!(string.bytes, b"\xED\xA0\xBD \xED\xB2\xA9");
+    assert_eq!(string.as_bytes(), b"\xED\xA0\xBD \xED\xB2\xA9");
     assert!(!string.is_known_utf8);
 
     let mut string = Wtf8Buf::new();
     string.push_wtf8(w(b"\xED\xA0\x80")); // lead
     string.push_wtf8(w(b"\xED\xAF\xBF")); // lead
-    assert_eq!(string.bytes, b"\xED\xA0\x80\xED\xAF\xBF");
+    assert_eq!(string.as_bytes(), b"\xED\xA0\x80\xED\xAF\xBF");
     assert!(!string.is_known_utf8);
 
     let mut string = Wtf8Buf::new();
     string.push_wtf8(w(b"\xED\xA0\x80")); // lead
     string.push_wtf8(w(b"\xEE\x80\x80")); // not surrogate
-    assert_eq!(string.bytes, b"\xED\xA0\x80\xEE\x80\x80");
+    assert_eq!(string.as_bytes(), b"\xED\xA0\x80\xEE\x80\x80");
     assert!(!string.is_known_utf8);
 
     let mut string = Wtf8Buf::new();
     string.push_wtf8(w(b"\xED\x9F\xBF")); // not surrogate
     string.push_wtf8(w(b"\xED\xB0\x80")); // trail
-    assert_eq!(string.bytes, b"\xED\x9F\xBF\xED\xB0\x80");
+    assert_eq!(string.as_bytes(), b"\xED\x9F\xBF\xED\xB0\x80");
     assert!(!string.is_known_utf8);
 
     let mut string = Wtf8Buf::new();
     string.push_wtf8(w(b"a")); // not surrogate, < 3 bytes
     string.push_wtf8(w(b"\xED\xB0\x80")); // trail
-    assert_eq!(string.bytes, b"\x61\xED\xB0\x80");
+    assert_eq!(string.as_bytes(), b"\x61\xED\xB0\x80");
     assert!(!string.is_known_utf8);
 
     let mut string = Wtf8Buf::new();
     string.push_wtf8(w(b"\xED\xB0\x80")); // trail
-    assert_eq!(string.bytes, b"\xED\xB0\x80");
+    assert_eq!(string.as_bytes(), b"\xED\xB0\x80");
     assert!(!string.is_known_utf8);
 }
 
@@ -269,15 +274,15 @@ fn wtf8buf_truncate() {
     assert!(string.is_known_utf8);
 
     string.truncate(3);
-    assert_eq!(string.bytes, b"a\xC3\xA9");
+    assert_eq!(string.as_bytes(), b"a\xC3\xA9");
     assert!(string.is_known_utf8);
 
     string.truncate(1);
-    assert_eq!(string.bytes, b"a");
+    assert_eq!(string.as_bytes(), b"a");
     assert!(string.is_known_utf8);
 
     string.truncate(0);
-    assert_eq!(string.bytes, b"");
+    assert_eq!(string.as_bytes(), b"");
     assert!(string.is_known_utf8);
 }
 
@@ -287,11 +292,11 @@ fn wtf8buf_truncate_around_non_bmp() {
     assert!(string.is_known_utf8);
 
     string.truncate(4);
-    assert_eq!(string.bytes, b"\xF0\x9F\x92\xA9");
+    assert_eq!(string.as_bytes(), b"\xF0\x9F\x92\xA9");
     assert!(string.is_known_utf8);
 
     string.truncate(0);
-    assert_eq!(string.bytes, b"");
+    assert_eq!(string.as_bytes(), b"");
     assert!(string.is_known_utf8);
 }
 
@@ -361,7 +366,7 @@ fn wtf8buf_from_iterator() {
         Wtf8Buf { bytes: b"a\xC3\xA9 \xF0\x9F\x92\xA9".to_vec(), is_known_utf8: true }
     );
 
-    assert_eq!(f(&[0xD83D, 0xDCA9]).bytes, b"\xF0\x9F\x92\xA9"); // Magic!
+    assert_eq!(f(&[0xD83D, 0xDCA9]).as_bytes(), b"\xF0\x9F\x92\xA9"); // Magic!
     assert_eq!(
         f(&[0xD83D, 0x20, 0xDCA9]),
         Wtf8Buf { bytes: b"\xED\xA0\xBD \xED\xB2\xA9".to_vec(), is_known_utf8: false }
@@ -401,7 +406,7 @@ fn wtf8buf_extend() {
         Wtf8Buf { bytes: b"a\xC3\xA9 \xF0\x9F\x92\xA9".to_vec(), is_known_utf8: true }
     );
 
-    assert_eq!(e(&[0xD83D], &[0xDCA9]).bytes, b"\xF0\x9F\x92\xA9"); // Magic!
+    assert_eq!(e(&[0xD83D], &[0xDCA9]).as_bytes(), b"\xF0\x9F\x92\xA9"); // Magic!
     assert_eq!(
         e(&[0xD83D, 0x20], &[0xDCA9]),
         Wtf8Buf { bytes: b"\xED\xA0\xBD \xED\xB2\xA9".to_vec(), is_known_utf8: false }
@@ -449,8 +454,8 @@ fn wtf8buf_show_str() {
 
 #[test]
 fn wtf8_from_str() {
-    assert_eq!(&Wtf8::from_str("").bytes, b"");
-    assert_eq!(&Wtf8::from_str("aé 💩").bytes, b"a\xC3\xA9 \xF0\x9F\x92\xA9");
+    assert_eq!(&Wtf8::from_str("").as_bytes(), b"");
+    assert_eq!(&Wtf8::from_str("aé 💩").as_bytes(), b"a\xC3\xA9 \xF0\x9F\x92\xA9");
 }
 
 #[test]
@@ -461,7 +466,7 @@ fn wtf8_len() {
 
 #[test]
 fn wtf8_slice() {
-    assert_eq!(&Wtf8::from_str("aé 💩")[1..4].bytes, b"\xC3\xA9 ");
+    assert_eq!(&Wtf8::from_str("aé 💩")[1..4].as_bytes(), b"\xC3\xA9 ");
 }
 
 #[test]
@@ -472,7 +477,7 @@ fn wtf8_slice_not_code_point_boundary() {
 
 #[test]
 fn wtf8_slice_from() {
-    assert_eq!(&Wtf8::from_str("aé 💩")[1..].bytes, b"\xC3\xA9 \xF0\x9F\x92\xA9");
+    assert_eq!(&Wtf8::from_str("aé 💩")[1..].as_bytes(), b"\xC3\xA9 \xF0\x9F\x92\xA9");
 }
 
 #[test]
@@ -483,7 +488,7 @@ fn wtf8_slice_from_not_code_point_boundary() {
 
 #[test]
 fn wtf8_slice_to() {
-    assert_eq!(&Wtf8::from_str("aé 💩")[..4].bytes, b"a\xC3\xA9 ");
+    assert_eq!(&Wtf8::from_str("aé 💩")[..4].as_bytes(), b"a\xC3\xA9 ");
 }
 
 #[test]
@@ -529,12 +534,12 @@ fn wtf8_as_str() {
 
 #[test]
 fn wtf8_to_string_lossy() {
-    assert_eq!(Wtf8::from_str("").to_string_lossy(), Cow::Borrowed(""));
-    assert_eq!(Wtf8::from_str("aé 💩").to_string_lossy(), Cow::Borrowed("aé 💩"));
+    assert_eq!(to_string_lossy(Wtf8::from_str("")), Cow::Borrowed(""));
+    assert_eq!(to_string_lossy(Wtf8::from_str("aé 💩")), Cow::Borrowed("aé 💩"));
     let mut string = Wtf8Buf::from_str("aé 💩");
     string.push(CodePoint::from_u32(0xD800).unwrap());
     let expected: Cow<'_, str> = Cow::Owned(String::from("aé 💩�"));
-    assert_eq!(string.to_string_lossy(), expected);
+    assert_eq!(to_string_lossy(&string), expected);
 }
 
 #[test]
@@ -548,7 +553,7 @@ fn wtf8_display() {
 
     let mut string = Wtf8Buf::from_str("aé 💩");
     string.push(CodePoint::from_u32(0xD800).unwrap());
-    assert_eq!("aé 💩�", d(string.as_inner()));
+    assert_eq!("aé 💩�", d(string.as_ref()));
 }
 
 #[test]
@@ -577,67 +582,41 @@ fn wtf8_encode_wide_size_hint() {
 #[test]
 fn wtf8_clone_into() {
     let mut string = Wtf8Buf::new();
-    Wtf8::from_str("green").clone_into(&mut string);
-    assert_eq!(string.bytes, b"green");
+    clone_into(Wtf8::from_str("green"), &mut string);
+    assert_eq!(string.as_bytes(), b"green");
 
     let mut string = Wtf8Buf::from_str("green");
-    Wtf8::from_str("").clone_into(&mut string);
-    assert_eq!(string.bytes, b"");
+    clone_into(Wtf8::from_str(""), &mut string);
+    assert_eq!(string.as_bytes(), b"");
 
     let mut string = Wtf8Buf::from_str("red");
-    Wtf8::from_str("green").clone_into(&mut string);
-    assert_eq!(string.bytes, b"green");
+    clone_into(Wtf8::from_str("green"), &mut string);
+    assert_eq!(string.as_bytes(), b"green");
 
     let mut string = Wtf8Buf::from_str("green");
-    Wtf8::from_str("red").clone_into(&mut string);
-    assert_eq!(string.bytes, b"red");
+    clone_into(Wtf8::from_str("red"), &mut string);
+    assert_eq!(string.as_bytes(), b"red");
 
     let mut string = Wtf8Buf::from_str("green");
     assert!(string.is_known_utf8);
-    unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").clone_into(&mut string) };
-    assert_eq!(string.bytes, b"\xED\xA0\x80");
+    clone_into(unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80") }, &mut string);
+    assert_eq!(string.as_bytes(), b"\xED\xA0\x80");
     assert!(!string.is_known_utf8);
 }
 
 #[test]
-fn wtf8_to_ascii_lowercase() {
-    let lowercase = Wtf8::from_str("").to_ascii_lowercase();
-    assert_eq!(lowercase.bytes, b"");
-
-    let lowercase = Wtf8::from_str("GrEeN gRaPeS! 🍇").to_ascii_lowercase();
-    assert_eq!(lowercase.bytes, b"green grapes! \xf0\x9f\x8d\x87");
-
-    let lowercase = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_ascii_lowercase() };
-    assert_eq!(lowercase.bytes, b"\xED\xA0\x80");
-    assert!(!lowercase.is_known_utf8);
-}
-
-#[test]
-fn wtf8_to_ascii_uppercase() {
-    let uppercase = Wtf8::from_str("").to_ascii_uppercase();
-    assert_eq!(uppercase.bytes, b"");
-
-    let uppercase = Wtf8::from_str("GrEeN gRaPeS! 🍇").to_ascii_uppercase();
-    assert_eq!(uppercase.bytes, b"GREEN GRAPES! \xf0\x9f\x8d\x87");
-
-    let uppercase = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_ascii_uppercase() };
-    assert_eq!(uppercase.bytes, b"\xED\xA0\x80");
-    assert!(!uppercase.is_known_utf8);
-}
-
-#[test]
 fn wtf8_make_ascii_lowercase() {
     let mut lowercase = Wtf8Buf::from_str("");
     lowercase.make_ascii_lowercase();
-    assert_eq!(lowercase.bytes, b"");
+    assert_eq!(lowercase.as_bytes(), b"");
 
     let mut lowercase = Wtf8Buf::from_str("GrEeN gRaPeS! 🍇");
     lowercase.make_ascii_lowercase();
-    assert_eq!(lowercase.bytes, b"green grapes! \xf0\x9f\x8d\x87");
+    assert_eq!(lowercase.as_bytes(), b"green grapes! \xf0\x9f\x8d\x87");
 
-    let mut lowercase = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_owned() };
+    let mut lowercase = to_owned(unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80") });
     lowercase.make_ascii_lowercase();
-    assert_eq!(lowercase.bytes, b"\xED\xA0\x80");
+    assert_eq!(lowercase.as_bytes(), b"\xED\xA0\x80");
     assert!(!lowercase.is_known_utf8);
 }
 
@@ -645,22 +624,22 @@ fn wtf8_make_ascii_lowercase() {
 fn wtf8_make_ascii_uppercase() {
     let mut uppercase = Wtf8Buf::from_str("");
     uppercase.make_ascii_uppercase();
-    assert_eq!(uppercase.bytes, b"");
+    assert_eq!(uppercase.as_bytes(), b"");
 
     let mut uppercase = Wtf8Buf::from_str("GrEeN gRaPeS! 🍇");
     uppercase.make_ascii_uppercase();
-    assert_eq!(uppercase.bytes, b"GREEN GRAPES! \xf0\x9f\x8d\x87");
+    assert_eq!(uppercase.as_bytes(), b"GREEN GRAPES! \xf0\x9f\x8d\x87");
 
-    let mut uppercase = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_owned() };
+    let mut uppercase = to_owned(unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80") });
     uppercase.make_ascii_uppercase();
-    assert_eq!(uppercase.bytes, b"\xED\xA0\x80");
+    assert_eq!(uppercase.as_bytes(), b"\xED\xA0\x80");
     assert!(!uppercase.is_known_utf8);
 }
 
 #[test]
 fn wtf8_to_owned() {
-    let string = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_owned() };
-    assert_eq!(string.bytes, b"\xED\xA0\x80");
+    let string = to_owned(unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80") });
+    assert_eq!(string.as_bytes(), b"\xED\xA0\x80");
     assert!(!string.is_known_utf8);
 }
 
@@ -669,44 +648,44 @@ fn wtf8_valid_utf8_boundaries() {
     let mut string = Wtf8Buf::from_str("aé 💩");
     string.push(CodePoint::from_u32(0xD800).unwrap());
     string.push(CodePoint::from_u32(0xD800).unwrap());
-    check_utf8_boundary(&string, 0);
-    check_utf8_boundary(&string, 1);
-    check_utf8_boundary(&string, 3);
-    check_utf8_boundary(&string, 4);
-    check_utf8_boundary(&string, 8);
-    check_utf8_boundary(&string, 14);
+    string.check_utf8_boundary(0);
+    string.check_utf8_boundary(1);
+    string.check_utf8_boundary(3);
+    string.check_utf8_boundary(4);
+    string.check_utf8_boundary(8);
+    string.check_utf8_boundary(14);
     assert_eq!(string.len(), 14);
 
     string.push_char('a');
-    check_utf8_boundary(&string, 14);
-    check_utf8_boundary(&string, 15);
+    string.check_utf8_boundary(14);
+    string.check_utf8_boundary(15);
 
     let mut string = Wtf8Buf::from_str("a");
     string.push(CodePoint::from_u32(0xD800).unwrap());
-    check_utf8_boundary(&string, 1);
+    string.check_utf8_boundary(1);
 
     let mut string = Wtf8Buf::from_str("\u{D7FF}");
     string.push(CodePoint::from_u32(0xD800).unwrap());
-    check_utf8_boundary(&string, 3);
+    string.check_utf8_boundary(3);
 
     let mut string = Wtf8Buf::new();
     string.push(CodePoint::from_u32(0xD800).unwrap());
     string.push_char('\u{D7FF}');
-    check_utf8_boundary(&string, 3);
+    string.check_utf8_boundary(3);
 }
 
 #[test]
 #[should_panic(expected = "byte index 4 is out of bounds")]
 fn wtf8_utf8_boundary_out_of_bounds() {
     let string = Wtf8::from_str("aé");
-    check_utf8_boundary(&string, 4);
+    string.check_utf8_boundary(4);
 }
 
 #[test]
 #[should_panic(expected = "byte index 1 is not a codepoint boundary")]
 fn wtf8_utf8_boundary_inside_codepoint() {
     let string = Wtf8::from_str("é");
-    check_utf8_boundary(&string, 1);
+    string.check_utf8_boundary(1);
 }
 
 #[test]
@@ -714,7 +693,7 @@ fn wtf8_utf8_boundary_inside_codepoint() {
 fn wtf8_utf8_boundary_inside_surrogate() {
     let mut string = Wtf8Buf::new();
     string.push(CodePoint::from_u32(0xD800).unwrap());
-    check_utf8_boundary(&string, 1);
+    string.check_utf8_boundary(1);
 }
 
 #[test]
@@ -723,20 +702,22 @@ fn wtf8_utf8_boundary_between_surrogates() {
     let mut string = Wtf8Buf::new();
     string.push(CodePoint::from_u32(0xD800).unwrap());
     string.push(CodePoint::from_u32(0xD800).unwrap());
-    check_utf8_boundary(&string, 3);
+    string.check_utf8_boundary(3);
 }
 
 #[test]
 fn wobbled_wtf8_plus_bytes_isnt_utf8() {
-    let mut string: Wtf8Buf = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_owned() };
+    let mut string: Wtf8Buf = to_owned(unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80") });
     assert!(!string.is_known_utf8);
-    string.extend_from_slice(b"some utf-8");
+    unsafe {
+        string.extend_from_slice_unchecked(b"some utf-8");
+    }
     assert!(!string.is_known_utf8);
 }
 
 #[test]
 fn wobbled_wtf8_plus_str_isnt_utf8() {
-    let mut string: Wtf8Buf = unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80").to_owned() };
+    let mut string: Wtf8Buf = to_owned(unsafe { Wtf8::from_bytes_unchecked(b"\xED\xA0\x80") });
     assert!(!string.is_known_utf8);
     string.push_str("some utf-8");
     assert!(!string.is_known_utf8);
diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs
index 3241b4b0045..97de7d6a701 100644
--- a/library/alloctests/lib.rs
+++ b/library/alloctests/lib.rs
@@ -18,6 +18,8 @@
 #![feature(allocator_api)]
 #![feature(array_into_iter_constructors)]
 #![feature(assert_matches)]
+#![feature(char_internals)]
+#![feature(char_max_len)]
 #![feature(core_intrinsics)]
 #![feature(exact_size_is_empty)]
 #![feature(extend_one)]
@@ -41,6 +43,7 @@
 #![feature(trusted_random_access)]
 #![feature(try_reserve_kind)]
 #![feature(try_trait_v2)]
+#![feature(wtf8_internals)]
 // tidy-alphabetical-end
 //
 // Language features:
@@ -68,15 +71,18 @@ extern crate test;
 mod testing;
 use realalloc::*;
 
-// We are directly including collections and raw_vec here as both use non-public
-// methods and fields in tests and as such need to have the types to test in the
-// same crate as the tests themself.
+// We are directly including collections, raw_vec, and wtf8 here as they use non-public
+// methods and fields in tests and as such need to have the types to test in the same
+// crate as the tests themself.
 #[path = "../alloc/src/collections/mod.rs"]
 mod collections;
 
 #[path = "../alloc/src/raw_vec/mod.rs"]
 mod raw_vec;
 
+#[path = "../alloc/src/wtf8/mod.rs"]
+mod wtf8;
+
 #[allow(dead_code)] // Not used in all configurations
 pub(crate) mod test_helpers {
     /// Copied from `std::test_helpers::test_rng`, since these tests rely on the
diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs
index fcfc7f8dd29..447af240a4b 100644
--- a/library/alloctests/tests/lib.rs
+++ b/library/alloctests/tests/lib.rs
@@ -3,6 +3,7 @@
 #![feature(iter_array_chunks)]
 #![feature(assert_matches)]
 #![feature(btree_extract_if)]
+#![feature(wtf8_internals)]
 #![feature(char_max_len)]
 #![feature(cow_is_borrowed)]
 #![feature(core_intrinsics)]
diff --git a/library/compiler-builtins/compiler-builtins/README.md b/library/compiler-builtins/compiler-builtins/README.md
index 387b70c0499..2d92b7651f9 100644
--- a/library/compiler-builtins/compiler-builtins/README.md
+++ b/library/compiler-builtins/compiler-builtins/README.md
@@ -10,6 +10,16 @@ to be added as an explicit dependency in `Cargo.toml`.
 
 [`compiler-rt`]: https://github.com/llvm/llvm-project/tree/1b1dc505057322f4fa1110ef4f53c44347f52986/compiler-rt
 
+## Configuration
+
+`compiler-builtins` can be configured with the following environment variables when the `c` feature
+is enabled:
+
+- `LLVM_COMPILER_RT_LIB`
+- `RUST_COMPILER_RT_ROOT`
+
+See `build.rs` for details.
+
 ## Contributing
 
 See [CONTRIBUTING.md](CONTRIBUTING.md).
diff --git a/library/compiler-builtins/compiler-builtins/build.rs b/library/compiler-builtins/compiler-builtins/build.rs
index 43b978606e5..6e1d230e3cd 100644
--- a/library/compiler-builtins/compiler-builtins/build.rs
+++ b/library/compiler-builtins/compiler-builtins/build.rs
@@ -540,12 +540,20 @@ mod c {
             sources.extend(&[("__emutls_get_address", "emutls.c")]);
         }
 
+        // Optionally, link against a prebuilt llvm compiler-rt containing the builtins
+        // library. Only the builtins library is required. On many platforms, this is
+        // available as a library named libclang_rt.builtins.a.
+        let link_against_prebuilt_rt = env::var_os("LLVM_COMPILER_RT_LIB").is_some();
+
         // When compiling the C code we require the user to tell us where the
         // source code is, and this is largely done so when we're compiling as
         // part of rust-lang/rust we can use the same llvm-project repository as
         // rust-lang/rust.
         let root = match env::var_os("RUST_COMPILER_RT_ROOT") {
             Some(s) => PathBuf::from(s),
+            // If a prebuild libcompiler-rt is provided, set a valid
+            // path to simplify later logic. Nothing should be compiled.
+            None if link_against_prebuilt_rt => PathBuf::new(),
             None => {
                 panic!(
                     "RUST_COMPILER_RT_ROOT is not set. You may need to run \
@@ -553,7 +561,7 @@ mod c {
                 );
             }
         };
-        if !root.exists() {
+        if !link_against_prebuilt_rt && !root.exists() {
             panic!("RUST_COMPILER_RT_ROOT={} does not exist", root.display());
         }
 
@@ -569,7 +577,7 @@ mod c {
         let src_dir = root.join("lib/builtins");
         if target.arch == "aarch64" && target.env != "msvc" && target.os != "uefi" {
             // See below for why we're building these as separate libraries.
-            build_aarch64_out_of_line_atomics_libraries(&src_dir, cfg);
+            build_aarch64_out_of_line_atomics_libraries(&src_dir, cfg, link_against_prebuilt_rt);
 
             // Some run-time CPU feature detection is necessary, as well.
             let cpu_model_src = if src_dir.join("cpu_model.c").exists() {
@@ -583,20 +591,45 @@ mod c {
         let mut added_sources = HashSet::new();
         for (sym, src) in sources.map.iter() {
             let src = src_dir.join(src);
-            if added_sources.insert(src.clone()) {
+            if !link_against_prebuilt_rt && added_sources.insert(src.clone()) {
                 cfg.file(&src);
                 println!("cargo:rerun-if-changed={}", src.display());
             }
             println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);
         }
 
-        cfg.compile("libcompiler-rt.a");
+        if link_against_prebuilt_rt {
+            let rt_builtins_ext = PathBuf::from(env::var_os("LLVM_COMPILER_RT_LIB").unwrap());
+            if !rt_builtins_ext.exists() {
+                panic!(
+                    "LLVM_COMPILER_RT_LIB={} does not exist",
+                    rt_builtins_ext.display()
+                );
+            }
+            if let Some(dir) = rt_builtins_ext.parent() {
+                println!("cargo::rustc-link-search=native={}", dir.display());
+            }
+            if let Some(lib) = rt_builtins_ext.file_name() {
+                println!(
+                    "cargo::rustc-link-lib=static:+verbatim={}",
+                    lib.to_str().unwrap()
+                );
+            }
+        } else {
+            cfg.compile("libcompiler-rt.a");
+        }
     }
 
-    fn build_aarch64_out_of_line_atomics_libraries(builtins_dir: &Path, cfg: &mut cc::Build) {
+    fn build_aarch64_out_of_line_atomics_libraries(
+        builtins_dir: &Path,
+        cfg: &mut cc::Build,
+        link_against_prebuilt_rt: bool,
+    ) {
         let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
         let outlined_atomics_file = builtins_dir.join("aarch64").join("lse.S");
-        println!("cargo:rerun-if-changed={}", outlined_atomics_file.display());
+        if !link_against_prebuilt_rt {
+            println!("cargo:rerun-if-changed={}", outlined_atomics_file.display());
+        }
 
         cfg.include(&builtins_dir);
 
@@ -609,6 +642,13 @@ mod c {
                 for (model_number, model_name) in
                     &[(1, "relax"), (2, "acq"), (3, "rel"), (4, "acq_rel")]
                 {
+                    let sym = format!("__aarch64_{}{}_{}", instruction_type, size, model_name);
+                    println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);
+
+                    if link_against_prebuilt_rt {
+                        continue;
+                    }
+
                     // The original compiler-rt build system compiles the same
                     // source file multiple times with different compiler
                     // options. Here we do something slightly different: we
@@ -632,9 +672,6 @@ mod c {
                     .unwrap();
                     drop(file);
                     cfg.file(path);
-
-                    let sym = format!("__aarch64_{}{}_{}", instruction_type, size, model_name);
-                    println!("cargo:rustc-cfg={}=\"optimized-c\"", sym);
                 }
             }
         }
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index bb75ec74c81..835ee57ce23 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -184,18 +184,12 @@ pub struct TryFromSliceError(());
 impl fmt::Display for TryFromSliceError {
     #[inline]
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        #[allow(deprecated)]
-        self.description().fmt(f)
+        "could not convert slice to array".fmt(f)
     }
 }
 
 #[stable(feature = "try_from", since = "1.34.0")]
-impl Error for TryFromSliceError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "could not convert slice to array"
-    }
-}
+impl Error for TryFromSliceError {}
 
 #[stable(feature = "try_from_slice_error", since = "1.36.0")]
 #[rustc_const_unstable(feature = "const_try", issue = "74935")]
diff --git a/library/core/src/char/convert.rs b/library/core/src/char/convert.rs
index 23061cb663b..cf5a91bf8dd 100644
--- a/library/core/src/char/convert.rs
+++ b/library/core/src/char/convert.rs
@@ -193,21 +193,16 @@ enum CharErrorKind {
 }
 
 #[stable(feature = "char_from_str", since = "1.20.0")]
-impl Error for ParseCharError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        match self.kind {
-            CharErrorKind::EmptyString => "cannot parse char from empty string",
-            CharErrorKind::TooManyChars => "too many characters in string",
-        }
-    }
-}
+impl Error for ParseCharError {}
 
 #[stable(feature = "char_from_str", since = "1.20.0")]
 impl fmt::Display for ParseCharError {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        #[allow(deprecated)]
-        self.description().fmt(f)
+        match self.kind {
+            CharErrorKind::EmptyString => "cannot parse char from empty string",
+            CharErrorKind::TooManyChars => "too many characters in string",
+        }
+        .fmt(f)
     }
 }
 
diff --git a/library/core/src/char/decode.rs b/library/core/src/char/decode.rs
index 23319fbe5dd..d7c5f45ae4e 100644
--- a/library/core/src/char/decode.rs
+++ b/library/core/src/char/decode.rs
@@ -126,9 +126,4 @@ impl fmt::Display for DecodeUtf16Error {
 }
 
 #[stable(feature = "decode_utf16", since = "1.9.0")]
-impl Error for DecodeUtf16Error {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "unpaired surrogate found"
-    }
-}
+impl Error for DecodeUtf16Error {}
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 7ee0962721f..985e669c92d 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -1872,28 +1872,33 @@ pub const unsafe fn encode_utf8_raw_unchecked(code: u32, dst: *mut u8) {
     // SAFETY: The caller must guarantee that the buffer pointed to by `dst`
     // is at least `len` bytes long.
     unsafe {
-        match len {
-            1 => {
-                *dst = code as u8;
-            }
-            2 => {
-                *dst = (code >> 6 & 0x1F) as u8 | TAG_TWO_B;
-                *dst.add(1) = (code & 0x3F) as u8 | TAG_CONT;
-            }
-            3 => {
-                *dst = (code >> 12 & 0x0F) as u8 | TAG_THREE_B;
-                *dst.add(1) = (code >> 6 & 0x3F) as u8 | TAG_CONT;
-                *dst.add(2) = (code & 0x3F) as u8 | TAG_CONT;
-            }
-            4 => {
-                *dst = (code >> 18 & 0x07) as u8 | TAG_FOUR_B;
-                *dst.add(1) = (code >> 12 & 0x3F) as u8 | TAG_CONT;
-                *dst.add(2) = (code >> 6 & 0x3F) as u8 | TAG_CONT;
-                *dst.add(3) = (code & 0x3F) as u8 | TAG_CONT;
-            }
-            // SAFETY: `char` always takes between 1 and 4 bytes to encode in UTF-8.
-            _ => crate::hint::unreachable_unchecked(),
+        if len == 1 {
+            *dst = code as u8;
+            return;
+        }
+
+        let last1 = (code >> 0 & 0x3F) as u8 | TAG_CONT;
+        let last2 = (code >> 6 & 0x3F) as u8 | TAG_CONT;
+        let last3 = (code >> 12 & 0x3F) as u8 | TAG_CONT;
+        let last4 = (code >> 18 & 0x3F) as u8 | TAG_FOUR_B;
+
+        if len == 2 {
+            *dst = last2 | TAG_TWO_B;
+            *dst.add(1) = last1;
+            return;
         }
+
+        if len == 3 {
+            *dst = last3 | TAG_THREE_B;
+            *dst.add(1) = last2;
+            *dst.add(2) = last1;
+            return;
+        }
+
+        *dst = last4;
+        *dst.add(1) = last3;
+        *dst.add(2) = last2;
+        *dst.add(3) = last1;
     }
 }
 
diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs
index 0c3034c3d4c..a0a7b7928d1 100644
--- a/library/core/src/convert/mod.rs
+++ b/library/core/src/convert/mod.rs
@@ -958,11 +958,7 @@ impl fmt::Display for Infallible {
 }
 
 #[stable(feature = "str_parse_error2", since = "1.8.0")]
-impl Error for Infallible {
-    fn description(&self) -> &str {
-        match *self {}
-    }
-}
+impl Error for Infallible {}
 
 #[stable(feature = "convert_infallible", since = "1.34.0")]
 #[rustc_const_unstable(feature = "const_cmp", issue = "143800")]
diff --git a/library/core/src/error.rs b/library/core/src/error.rs
index 88e633c9eef..92b3c83d1bf 100644
--- a/library/core/src/error.rs
+++ b/library/core/src/error.rs
@@ -1042,11 +1042,6 @@ impl<'a> crate::iter::FusedIterator for Source<'a> {}
 
 #[stable(feature = "error_by_ref", since = "1.51.0")]
 impl<'a, T: Error + ?Sized> Error for &'a T {
-    #[allow(deprecated, deprecated_in_future)]
-    fn description(&self) -> &str {
-        Error::description(&**self)
-    }
-
     #[allow(deprecated)]
     fn cause(&self) -> Option<&dyn Error> {
         Error::cause(&**self)
@@ -1062,36 +1057,16 @@ impl<'a, T: Error + ?Sized> Error for &'a T {
 }
 
 #[stable(feature = "fmt_error", since = "1.11.0")]
-impl Error for crate::fmt::Error {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "an error occurred when formatting an argument"
-    }
-}
+impl Error for crate::fmt::Error {}
 
 #[stable(feature = "try_borrow", since = "1.13.0")]
-impl Error for crate::cell::BorrowError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "already mutably borrowed"
-    }
-}
+impl Error for crate::cell::BorrowError {}
 
 #[stable(feature = "try_borrow", since = "1.13.0")]
-impl Error for crate::cell::BorrowMutError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "already borrowed"
-    }
-}
+impl Error for crate::cell::BorrowMutError {}
 
 #[stable(feature = "try_from", since = "1.34.0")]
-impl Error for crate::char::CharTryFromError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "converted integer out of range for `char`"
-    }
-}
+impl Error for crate::char::CharTryFromError {}
 
 #[stable(feature = "duration_checked_float", since = "1.66.0")]
 impl Error for crate::time::TryFromFloatSecsError {}
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index 8ac29e5b076..b6de8925308 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -359,7 +359,7 @@ impl FormattingOptions {
     ///   always be printed.
     /// - `-`: Currently not used
     #[unstable(feature = "formatting_options", issue = "118117")]
-    pub fn sign(&mut self, sign: Option<Sign>) -> &mut Self {
+    pub const fn sign(&mut self, sign: Option<Sign>) -> &mut Self {
         let sign = match sign {
             None => 0,
             Some(Sign::Plus) => flags::SIGN_PLUS_FLAG,
@@ -372,7 +372,7 @@ impl FormattingOptions {
     ///
     /// This is used to indicate for integer formats that the padding to width should both be done with a 0 character as well as be sign-aware
     #[unstable(feature = "formatting_options", issue = "118117")]
-    pub fn sign_aware_zero_pad(&mut self, sign_aware_zero_pad: bool) -> &mut Self {
+    pub const fn sign_aware_zero_pad(&mut self, sign_aware_zero_pad: bool) -> &mut Self {
         if sign_aware_zero_pad {
             self.flags |= flags::SIGN_AWARE_ZERO_PAD_FLAG;
         } else {
@@ -389,7 +389,7 @@ impl FormattingOptions {
     /// - [`Octal`] - precedes the argument with a `0b`
     /// - [`Binary`] - precedes the argument with a `0o`
     #[unstable(feature = "formatting_options", issue = "118117")]
-    pub fn alternate(&mut self, alternate: bool) -> &mut Self {
+    pub const fn alternate(&mut self, alternate: bool) -> &mut Self {
         if alternate {
             self.flags |= flags::ALTERNATE_FLAG;
         } else {
@@ -404,7 +404,7 @@ impl FormattingOptions {
     /// being formatted is smaller than width some extra characters will be
     /// printed around it.
     #[unstable(feature = "formatting_options", issue = "118117")]
-    pub fn fill(&mut self, fill: char) -> &mut Self {
+    pub const fn fill(&mut self, fill: char) -> &mut Self {
         self.flags = self.flags & (u32::MAX << 21) | fill as u32;
         self
     }
@@ -413,7 +413,7 @@ impl FormattingOptions {
     /// The alignment specifies how the value being formatted should be
     /// positioned if it is smaller than the width of the formatter.
     #[unstable(feature = "formatting_options", issue = "118117")]
-    pub fn align(&mut self, align: Option<Alignment>) -> &mut Self {
+    pub const fn align(&mut self, align: Option<Alignment>) -> &mut Self {
         let align: u32 = match align {
             Some(Alignment::Left) => flags::ALIGN_LEFT,
             Some(Alignment::Right) => flags::ALIGN_RIGHT,
@@ -430,7 +430,7 @@ impl FormattingOptions {
     /// the padding specified by [`FormattingOptions::fill`]/[`FormattingOptions::align`]
     /// will be used to take up the required space.
     #[unstable(feature = "formatting_options", issue = "118117")]
-    pub fn width(&mut self, width: Option<u16>) -> &mut Self {
+    pub const fn width(&mut self, width: Option<u16>) -> &mut Self {
         if let Some(width) = width {
             self.flags |= flags::WIDTH_FLAG;
             self.width = width;
@@ -450,7 +450,7 @@ impl FormattingOptions {
     /// - For floating-point types, this indicates how many digits after the
     /// decimal point should be printed.
     #[unstable(feature = "formatting_options", issue = "118117")]
-    pub fn precision(&mut self, precision: Option<u16>) -> &mut Self {
+    pub const fn precision(&mut self, precision: Option<u16>) -> &mut Self {
         if let Some(precision) = precision {
             self.flags |= flags::PRECISION_FLAG;
             self.precision = precision;
@@ -463,7 +463,7 @@ impl FormattingOptions {
     /// Specifies whether the [`Debug`] trait should use lower-/upper-case
     /// hexadecimal or normal integers
     #[unstable(feature = "formatting_options", issue = "118117")]
-    pub fn debug_as_hex(&mut self, debug_as_hex: Option<DebugAsHex>) -> &mut Self {
+    pub const fn debug_as_hex(&mut self, debug_as_hex: Option<DebugAsHex>) -> &mut Self {
         let debug_as_hex = match debug_as_hex {
             None => 0,
             Some(DebugAsHex::Lower) => flags::DEBUG_LOWER_HEX_FLAG,
@@ -537,7 +537,7 @@ impl FormattingOptions {
     ///
     /// You may alternatively use [`Formatter::new()`].
     #[unstable(feature = "formatting_options", issue = "118117")]
-    pub fn create_formatter<'a>(self, write: &'a mut (dyn Write + 'a)) -> Formatter<'a> {
+    pub const fn create_formatter<'a>(self, write: &'a mut (dyn Write + 'a)) -> Formatter<'a> {
         Formatter { options: self, buf: write }
     }
 }
@@ -578,13 +578,13 @@ impl<'a> Formatter<'a> {
     ///
     /// You may alternatively use [`FormattingOptions::create_formatter()`].
     #[unstable(feature = "formatting_options", issue = "118117")]
-    pub fn new(write: &'a mut (dyn Write + 'a), options: FormattingOptions) -> Self {
+    pub const fn new(write: &'a mut (dyn Write + 'a), options: FormattingOptions) -> Self {
         Formatter { options, buf: write }
     }
 
     /// Creates a new formatter based on this one with given [`FormattingOptions`].
     #[unstable(feature = "formatting_options", issue = "118117")]
-    pub fn with_options<'b>(&'b mut self, options: FormattingOptions) -> Formatter<'b> {
+    pub const fn with_options<'b>(&'b mut self, options: FormattingOptions) -> Formatter<'b> {
         Formatter { options, buf: self.buf }
     }
 }
diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs
index c72eeb9a9c9..535c5a8e77b 100644
--- a/library/core/src/hint.rs
+++ b/library/core/src/hint.rs
@@ -267,39 +267,29 @@ pub const unsafe fn assert_unchecked(cond: bool) {
 #[inline(always)]
 #[stable(feature = "renamed_spin_loop", since = "1.49.0")]
 pub fn spin_loop() {
-    #[cfg(target_arch = "x86")]
-    {
-        // SAFETY: the `cfg` attr ensures that we only execute this on x86 targets.
-        unsafe { crate::arch::x86::_mm_pause() };
-    }
-
-    #[cfg(target_arch = "x86_64")]
-    {
-        // SAFETY: the `cfg` attr ensures that we only execute this on x86_64 targets.
-        unsafe { crate::arch::x86_64::_mm_pause() };
-    }
-
-    #[cfg(target_arch = "riscv32")]
-    {
-        crate::arch::riscv32::pause();
-    }
-
-    #[cfg(target_arch = "riscv64")]
-    {
-        crate::arch::riscv64::pause();
-    }
-
-    #[cfg(any(target_arch = "aarch64", target_arch = "arm64ec"))]
-    {
-        // SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets.
-        unsafe { crate::arch::aarch64::__isb(crate::arch::aarch64::SY) };
-    }
-
-    #[cfg(all(target_arch = "arm", target_feature = "v6"))]
-    {
-        // SAFETY: the `cfg` attr ensures that we only execute this on arm targets
-        // with support for the v6 feature.
-        unsafe { crate::arch::arm::__yield() };
+    crate::cfg_select! {
+        target_arch = "x86" => {
+            // SAFETY: the `cfg` attr ensures that we only execute this on x86 targets.
+            unsafe { crate::arch::x86::_mm_pause() }
+        }
+        target_arch = "x86_64" => {
+            // SAFETY: the `cfg` attr ensures that we only execute this on x86_64 targets.
+            unsafe { crate::arch::x86_64::_mm_pause() }
+        }
+        target_arch = "riscv32" => crate::arch::riscv32::pause(),
+        target_arch = "riscv64" => crate::arch::riscv64::pause(),
+        any(target_arch = "aarch64", target_arch = "arm64ec") => {
+            // SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets.
+            unsafe { crate::arch::aarch64::__isb(crate::arch::aarch64::SY) }
+        }
+        all(target_arch = "arm", target_feature = "v6") => {
+            // SAFETY: the `cfg` attr ensures that we only execute this on arm targets
+            // with support for the v6 feature.
+            unsafe { crate::arch::arm::__yield() }
+        }
+        target_arch = "loongarch32" => crate::arch::loongarch32::ibar::<0>(),
+        target_arch = "loongarch64" => crate::arch::loongarch64::ibar::<0>(),
+        _ => { /* do nothing */ }
     }
 }
 
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index f69d6a98592..82506379cac 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -363,6 +363,8 @@ pub mod slice;
 pub mod str;
 pub mod time;
 
+pub mod wtf8;
+
 pub mod unicode;
 
 /* Async */
diff --git a/library/core/src/net/parser.rs b/library/core/src/net/parser.rs
index 73230f6ee5b..3aab24a90d8 100644
--- a/library/core/src/net/parser.rs
+++ b/library/core/src/net/parser.rs
@@ -497,16 +497,7 @@ pub struct AddrParseError(AddrKind);
 
 #[stable(feature = "addr_parse_error_error", since = "1.4.0")]
 impl fmt::Display for AddrParseError {
-    #[allow(deprecated, deprecated_in_future)]
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt.write_str(self.description())
-    }
-}
-
-#[stable(feature = "addr_parse_error_error", since = "1.4.0")]
-impl Error for AddrParseError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.0 {
             AddrKind::Ip => "invalid IP address syntax",
             AddrKind::Ipv4 => "invalid IPv4 address syntax",
@@ -515,5 +506,9 @@ impl Error for AddrParseError {
             AddrKind::SocketV4 => "invalid IPv4 socket address syntax",
             AddrKind::SocketV6 => "invalid IPv6 socket address syntax",
         }
+        .fmt(f)
     }
 }
+
+#[stable(feature = "addr_parse_error_error", since = "1.4.0")]
+impl Error for AddrParseError {}
diff --git a/library/core/src/num/dec2flt/mod.rs b/library/core/src/num/dec2flt/mod.rs
index 3118a6e5ca6..dd4eccd24de 100644
--- a/library/core/src/num/dec2flt/mod.rs
+++ b/library/core/src/num/dec2flt/mod.rs
@@ -219,21 +219,16 @@ enum FloatErrorKind {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl Error for ParseFloatError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        match self.kind {
-            FloatErrorKind::Empty => "cannot parse float from empty string",
-            FloatErrorKind::Invalid => "invalid float literal",
-        }
-    }
-}
+impl Error for ParseFloatError {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for ParseFloatError {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        #[allow(deprecated)]
-        self.description().fmt(f)
+        match self.kind {
+            FloatErrorKind::Empty => "cannot parse float from empty string",
+            FloatErrorKind::Invalid => "invalid float literal",
+        }
+        .fmt(f)
     }
 }
 
diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs
index cfedd465cab..faa52329827 100644
--- a/library/core/src/num/error.rs
+++ b/library/core/src/num/error.rs
@@ -11,19 +11,13 @@ pub struct TryFromIntError(pub(crate) ());
 
 #[stable(feature = "try_from", since = "1.34.0")]
 impl fmt::Display for TryFromIntError {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        #[allow(deprecated)]
-        self.description().fmt(fmt)
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        "out of range integral type conversion attempted".fmt(f)
     }
 }
 
 #[stable(feature = "try_from", since = "1.34.0")]
-impl Error for TryFromIntError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "out of range integral type conversion attempted"
-    }
-}
+impl Error for TryFromIntError {}
 
 #[stable(feature = "try_from", since = "1.34.0")]
 #[rustc_const_unstable(feature = "const_try", issue = "74935")]
@@ -128,15 +122,6 @@ impl ParseIntError {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for ParseIntError {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        #[allow(deprecated)]
-        self.description().fmt(f)
-    }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Error for ParseIntError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
         match self.kind {
             IntErrorKind::Empty => "cannot parse integer from empty string",
             IntErrorKind::InvalidDigit => "invalid digit found in string",
@@ -144,5 +129,9 @@ impl Error for ParseIntError {
             IntErrorKind::NegOverflow => "number too small to fit in target type",
             IntErrorKind::Zero => "number would be zero for non-zero type",
         }
+        .fmt(f)
     }
 }
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Error for ParseIntError {}
diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs
index 69e6c100e76..4282b1af9f2 100644
--- a/library/core/src/num/f128.rs
+++ b/library/core/src/num/f128.rs
@@ -630,6 +630,13 @@ impl f128 {
 
     /// Converts radians to degrees.
     ///
+    /// # Unspecified precision
+    ///
+    /// The precision of this function is non-deterministic. This means it varies by platform,
+    /// Rust version, and can even differ within the same execution from one invocation to the next.
+    ///
+    /// # Examples
+    ///
     /// ```
     /// #![feature(f128)]
     /// # // FIXME(f16_f128): remove when `eqtf2` is available
@@ -645,13 +652,22 @@ impl f128 {
     #[unstable(feature = "f128", issue = "116909")]
     #[must_use = "this returns the result of the operation, without modifying the original"]
     pub const fn to_degrees(self) -> Self {
-        // Use a literal for better precision.
-        const PIS_IN_180: f128 = 57.2957795130823208767981548141051703324054724665643215491602_f128;
+        // The division here is correctly rounded with respect to the true value of 180/π.
+        // Although π is irrational and already rounded, the double rounding happens
+        // to produce correct result for f128.
+        const PIS_IN_180: f128 = 180.0 / consts::PI;
         self * PIS_IN_180
     }
 
     /// Converts degrees to radians.
     ///
+    /// # Unspecified precision
+    ///
+    /// The precision of this function is non-deterministic. This means it varies by platform,
+    /// Rust version, and can even differ within the same execution from one invocation to the next.
+    ///
+    /// # Examples
+    ///
     /// ```
     /// #![feature(f128)]
     /// # // FIXME(f16_f128): remove when `eqtf2` is available
@@ -668,7 +684,8 @@ impl f128 {
     #[unstable(feature = "f128", issue = "116909")]
     #[must_use = "this returns the result of the operation, without modifying the original"]
     pub const fn to_radians(self) -> f128 {
-        // Use a literal for better precision.
+        // Use a literal to avoid double rounding, consts::PI is already rounded,
+        // and dividing would round again.
         const RADS_PER_DEG: f128 =
             0.0174532925199432957692369076848861271344287188854172545609719_f128;
         self * RADS_PER_DEG
diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs
index b66cef03d20..23a8661c14b 100644
--- a/library/core/src/num/f16.rs
+++ b/library/core/src/num/f16.rs
@@ -625,6 +625,13 @@ impl f16 {
 
     /// Converts radians to degrees.
     ///
+    /// # Unspecified precision
+    ///
+    /// The precision of this function is non-deterministic. This means it varies by platform,
+    /// Rust version, and can even differ within the same execution from one invocation to the next.
+    ///
+    /// # Examples
+    ///
     /// ```
     /// #![feature(f16)]
     /// # // FIXME(f16_f128): extendhfsf2, truncsfhf2, __gnu_h2f_ieee, __gnu_f2h_ieee missing for many platforms
@@ -640,13 +647,21 @@ impl f16 {
     #[unstable(feature = "f16", issue = "116909")]
     #[must_use = "this returns the result of the operation, without modifying the original"]
     pub const fn to_degrees(self) -> Self {
-        // Use a literal for better precision.
+        // Use a literal to avoid double rounding, consts::PI is already rounded,
+        // and dividing would round again.
         const PIS_IN_180: f16 = 57.2957795130823208767981548141051703_f16;
         self * PIS_IN_180
     }
 
     /// Converts degrees to radians.
     ///
+    /// # Unspecified precision
+    ///
+    /// The precision of this function is non-deterministic. This means it varies by platform,
+    /// Rust version, and can even differ within the same execution from one invocation to the next.
+    ///
+    /// # Examples
+    ///
     /// ```
     /// #![feature(f16)]
     /// # // FIXME(f16_f128): extendhfsf2, truncsfhf2, __gnu_h2f_ieee, __gnu_f2h_ieee missing for many platforms
@@ -663,7 +678,8 @@ impl f16 {
     #[unstable(feature = "f16", issue = "116909")]
     #[must_use = "this returns the result of the operation, without modifying the original"]
     pub const fn to_radians(self) -> f16 {
-        // Use a literal for better precision.
+        // Use a literal to avoid double rounding, consts::PI is already rounded,
+        // and dividing would round again.
         const RADS_PER_DEG: f16 = 0.017453292519943295769236907684886_f16;
         self * RADS_PER_DEG
     }
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index f8344da79ad..da08bfc5950 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -839,6 +839,13 @@ impl f32 {
 
     /// Converts radians to degrees.
     ///
+    /// # Unspecified precision
+    ///
+    /// The precision of this function is non-deterministic. This means it varies by platform,
+    /// Rust version, and can even differ within the same execution from one invocation to the next.
+    ///
+    /// # Examples
+    ///
     /// ```
     /// let angle = std::f32::consts::PI;
     ///
@@ -852,13 +859,21 @@ impl f32 {
     #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")]
     #[inline]
     pub const fn to_degrees(self) -> f32 {
-        // Use a constant for better precision.
+        // Use a literal to avoid double rounding, consts::PI is already rounded,
+        // and dividing would round again.
         const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32;
         self * PIS_IN_180
     }
 
     /// Converts degrees to radians.
     ///
+    /// # Unspecified precision
+    ///
+    /// The precision of this function is non-deterministic. This means it varies by platform,
+    /// Rust version, and can even differ within the same execution from one invocation to the next.
+    ///
+    /// # Examples
+    ///
     /// ```
     /// let angle = 180.0f32;
     ///
@@ -872,6 +887,9 @@ impl f32 {
     #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")]
     #[inline]
     pub const fn to_radians(self) -> f32 {
+        // The division here is correctly rounded with respect to the true value of π/180.
+        // Although π is irrational and already rounded, the double rounding happens
+        // to produce correct result for f32.
         const RADS_PER_DEG: f32 = consts::PI / 180.0;
         self * RADS_PER_DEG
     }
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index 93da63c896e..dc0977cb147 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -856,6 +856,13 @@ impl f64 {
 
     /// Converts radians to degrees.
     ///
+    /// # Unspecified precision
+    ///
+    /// The precision of this function is non-deterministic. This means it varies by platform,
+    /// Rust version, and can even differ within the same execution from one invocation to the next.
+    ///
+    /// # Examples
+    ///
     /// ```
     /// let angle = std::f64::consts::PI;
     ///
@@ -869,14 +876,22 @@ impl f64 {
     #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")]
     #[inline]
     pub const fn to_degrees(self) -> f64 {
-        // The division here is correctly rounded with respect to the true
-        // value of 180/π. (This differs from f32, where a constant must be
-        // used to ensure a correctly rounded result.)
-        self * (180.0f64 / consts::PI)
+        // The division here is correctly rounded with respect to the true value of 180/π.
+        // Although π is irrational and already rounded, the double rounding happens
+        // to produce correct result for f64.
+        const PIS_IN_180: f64 = 180.0 / consts::PI;
+        self * PIS_IN_180
     }
 
     /// Converts degrees to radians.
     ///
+    /// # Unspecified precision
+    ///
+    /// The precision of this function is non-deterministic. This means it varies by platform,
+    /// Rust version, and can even differ within the same execution from one invocation to the next.
+    ///
+    /// # Examples
+    ///
     /// ```
     /// let angle = 180.0_f64;
     ///
@@ -890,6 +905,9 @@ impl f64 {
     #[rustc_const_stable(feature = "const_float_methods", since = "1.85.0")]
     #[inline]
     pub const fn to_radians(self) -> f64 {
+        // The division here is correctly rounded with respect to the true value of π/180.
+        // Although π is irrational and already rounded, the double rounding happens
+        // to produce correct result for f64.
         const RADS_PER_DEG: f64 = consts::PI / 180.0;
         self * RADS_PER_DEG
     }
diff --git a/library/core/src/num/niche_types.rs b/library/core/src/num/niche_types.rs
index d57b1d433e5..610d9d8cf92 100644
--- a/library/core/src/num/niche_types.rs
+++ b/library/core/src/num/niche_types.rs
@@ -178,3 +178,18 @@ impl NotAllOnesHelper for u64 {
 impl NotAllOnesHelper for i64 {
     type Type = I64NotAllOnes;
 }
+
+define_valid_range_type! {
+    pub struct CodePointInner(u32 as u32 in 0..=0x10ffff);
+}
+
+impl CodePointInner {
+    pub const ZERO: Self = CodePointInner::new(0).unwrap();
+}
+
+impl Default for CodePointInner {
+    #[inline]
+    fn default() -> Self {
+        Self::ZERO
+    }
+}
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index e83e77344cf..fa09409b6da 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -1961,6 +1961,42 @@ impl<T> Option<T> {
             _ => None,
         }
     }
+
+    /// Reduces two options into one, using the provided function if both are `Some`.
+    ///
+    /// If `self` is `Some(s)` and `other` is `Some(o)`, this method returns `Some(f(s, o))`.
+    /// Otherwise, if only one of `self` and `other` is `Some`, that one is returned.
+    /// If both `self` and `other` are `None`, `None` is returned.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(option_reduce)]
+    ///
+    /// let s12 = Some(12);
+    /// let s17 = Some(17);
+    /// let n = None;
+    /// let f = |a, b| a + b;
+    ///
+    /// assert_eq!(s12.reduce(s17, f), Some(29));
+    /// assert_eq!(s12.reduce(n, f), Some(12));
+    /// assert_eq!(n.reduce(s17, f), Some(17));
+    /// assert_eq!(n.reduce(n, f), None);
+    /// ```
+    #[unstable(feature = "option_reduce", issue = "144273")]
+    pub fn reduce<U, R, F>(self, other: Option<U>, f: F) -> Option<R>
+    where
+        T: Into<R>,
+        U: Into<R>,
+        F: FnOnce(T, U) -> R,
+    {
+        match (self, other) {
+            (Some(a), Some(b)) => Some(f(a, b)),
+            (Some(a), _) => Some(a.into()),
+            (_, Some(b)) => Some(b.into()),
+            _ => None,
+        }
+    }
 }
 
 impl<T, U> Option<(T, U)> {
diff --git a/library/core/src/panic/location.rs b/library/core/src/panic/location.rs
index cafdcfa2c2e..7a68d393906 100644
--- a/library/core/src/panic/location.rs
+++ b/library/core/src/panic/location.rs
@@ -39,7 +39,7 @@ use crate::ptr::NonNull;
 pub struct Location<'a> {
     // A raw pointer is used rather than a reference because the pointer is valid for one more byte
     // than the length stored in this pointer; the additional byte is the NUL-terminator used by
-    // `Location::file_with_nul`.
+    // `Location::file_as_c_str`.
     filename: NonNull<str>,
     line: u32,
     col: u32,
@@ -195,7 +195,7 @@ impl<'a> Location<'a> {
     #[must_use]
     #[unstable(feature = "file_with_nul", issue = "141727")]
     #[inline]
-    pub const fn file_with_nul(&self) -> &'a CStr {
+    pub const fn file_as_c_str(&self) -> &'a CStr {
         let filename = self.filename.as_ptr();
 
         // SAFETY: The filename is valid for `filename_len+1` bytes, so this addition can't
diff --git a/library/core/src/ptr/metadata.rs b/library/core/src/ptr/metadata.rs
index 0deac3621e8..dc3ec3fd199 100644
--- a/library/core/src/ptr/metadata.rs
+++ b/library/core/src/ptr/metadata.rs
@@ -106,6 +106,9 @@ pub const fn metadata<T: PointeeSized>(ptr: *const T) -> <T as Pointee>::Metadat
 /// For slices, see the documentation of [`slice::from_raw_parts`] for safety requirements.
 /// For trait objects, the metadata must come from a pointer to the same underlying erased type.
 ///
+/// If you are attempting to deconstruct a DST in a generic context to be reconstructed later,
+/// a thin pointer can always be obtained by casting `*const T` to `*const ()`.
+///
 /// [`slice::from_raw_parts`]: crate::slice::from_raw_parts
 #[unstable(feature = "ptr_metadata", issue = "81513")]
 #[inline]
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index f5c490ca7ce..6fc85a83e17 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -914,6 +914,7 @@ pub const fn dangling<T>() -> *const T {
 #[must_use]
 #[stable(feature = "strict_provenance", since = "1.84.0")]
 #[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")]
+#[allow(integer_to_ptr_transmutes)] // Expected semantics here.
 pub const fn without_provenance_mut<T>(addr: usize) -> *mut T {
     // An int-to-pointer transmute currently has exactly the intended semantics: it creates a
     // pointer without provenance. Note that this is *not* a stable guarantee about transmute
diff --git a/library/core/src/str/error.rs b/library/core/src/str/error.rs
index 4c8231a2286..1677c849ae4 100644
--- a/library/core/src/str/error.rs
+++ b/library/core/src/str/error.rs
@@ -124,12 +124,7 @@ impl fmt::Display for Utf8Error {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl Error for Utf8Error {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "invalid utf-8: corrupt contents"
-    }
-}
+impl Error for Utf8Error {}
 
 /// An error returned when parsing a `bool` using [`from_str`] fails
 ///
@@ -147,9 +142,4 @@ impl fmt::Display for ParseBoolError {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl Error for ParseBoolError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "failed to parse bool"
-    }
-}
+impl Error for ParseBoolError {}
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 1b6e84175b9..1a055a0a5ad 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -3072,7 +3072,7 @@ impl str {
     /// for example references to `Box<str>` or `Arc<str>`.
     #[inline]
     #[unstable(feature = "str_as_str", issue = "130366")]
-    pub fn as_str(&self) -> &str {
+    pub const fn as_str(&self) -> &str {
         self
     }
 }
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index 0cc570f4b73..f37e47f132d 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -927,7 +927,7 @@ impl Duration {
     pub fn from_secs_f64(secs: f64) -> Duration {
         match Duration::try_from_secs_f64(secs) {
             Ok(v) => v,
-            Err(e) => panic!("{}", e.description()),
+            Err(e) => panic!("{e}"),
         }
     }
 
@@ -964,7 +964,7 @@ impl Duration {
     pub fn from_secs_f32(secs: f32) -> Duration {
         match Duration::try_from_secs_f32(secs) {
             Ok(v) => v,
-            Err(e) => panic!("{}", e.description()),
+            Err(e) => panic!("{e}"),
         }
     }
 
@@ -1445,8 +1445,9 @@ pub struct TryFromFloatSecsError {
     kind: TryFromFloatSecsErrorKind,
 }
 
-impl TryFromFloatSecsError {
-    const fn description(&self) -> &'static str {
+#[stable(feature = "duration_checked_float", since = "1.66.0")]
+impl fmt::Display for TryFromFloatSecsError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match self.kind {
             TryFromFloatSecsErrorKind::Negative => {
                 "cannot convert float seconds to Duration: value is negative"
@@ -1455,13 +1456,7 @@ impl TryFromFloatSecsError {
                 "cannot convert float seconds to Duration: value is either too big or NaN"
             }
         }
-    }
-}
-
-#[stable(feature = "duration_checked_float", since = "1.66.0")]
-impl fmt::Display for TryFromFloatSecsError {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.description().fmt(f)
+        .fmt(f)
     }
 }
 
diff --git a/library/core/src/wtf8.rs b/library/core/src/wtf8.rs
new file mode 100644
index 00000000000..de0dfa560a3
--- /dev/null
+++ b/library/core/src/wtf8.rs
@@ -0,0 +1,597 @@
+//! Implementation of [the WTF-8 encoding](https://simonsapin.github.io/wtf-8/).
+//!
+//! This library uses Rust’s type system to maintain
+//! [well-formedness](https://simonsapin.github.io/wtf-8/#well-formed),
+//! like the `String` and `&str` types do for UTF-8.
+//!
+//! Since [WTF-8 must not be used
+//! for interchange](https://simonsapin.github.io/wtf-8/#intended-audience),
+//! this library deliberately does not provide access to the underlying bytes
+//! of WTF-8 strings,
+//! nor can it decode WTF-8 from arbitrary bytes.
+//! WTF-8 strings can be obtained from UTF-8, UTF-16, or code points.
+#![unstable(
+    feature = "wtf8_internals",
+    issue = "none",
+    reason = "this is internal code for representing OsStr on some platforms and not a public API"
+)]
+// rustdoc bug: doc(hidden) on the module won't stop types in the module from showing up in trait
+// implementations, so, we'll have to add more doc(hidden)s anyway
+#![doc(hidden)]
+
+use crate::char::{MAX_LEN_UTF16, encode_utf16_raw};
+use crate::clone::CloneToUninit;
+use crate::fmt::{self, Write};
+use crate::hash::{Hash, Hasher};
+use crate::iter::FusedIterator;
+use crate::num::niche_types::CodePointInner;
+use crate::str::next_code_point;
+use crate::{ops, slice, str};
+
+/// A Unicode code point: from U+0000 to U+10FFFF.
+///
+/// Compares with the `char` type,
+/// which represents a Unicode scalar value:
+/// a code point that is not a surrogate (U+D800 to U+DFFF).
+#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy)]
+#[doc(hidden)]
+pub struct CodePoint(CodePointInner);
+
+/// Format the code point as `U+` followed by four to six hexadecimal digits.
+/// Example: `U+1F4A9`
+impl fmt::Debug for CodePoint {
+    #[inline]
+    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(formatter, "U+{:04X}", self.0.as_inner())
+    }
+}
+
+impl CodePoint {
+    /// Unsafely creates a new `CodePoint` without checking the value.
+    ///
+    /// Only use when `value` is known to be less than or equal to 0x10FFFF.
+    #[inline]
+    pub unsafe fn from_u32_unchecked(value: u32) -> CodePoint {
+        // SAFETY: Guaranteed by caller.
+        CodePoint(unsafe { CodePointInner::new_unchecked(value) })
+    }
+
+    /// Creates a new `CodePoint` if the value is a valid code point.
+    ///
+    /// Returns `None` if `value` is above 0x10FFFF.
+    #[inline]
+    pub fn from_u32(value: u32) -> Option<CodePoint> {
+        Some(CodePoint(CodePointInner::new(value)?))
+    }
+
+    /// Creates a new `CodePoint` from a `char`.
+    ///
+    /// Since all Unicode scalar values are code points, this always succeeds.
+    #[inline]
+    pub fn from_char(value: char) -> CodePoint {
+        // SAFETY: All char are valid for this type.
+        unsafe { CodePoint::from_u32_unchecked(value as u32) }
+    }
+
+    /// Returns the numeric value of the code point.
+    #[inline]
+    pub fn to_u32(&self) -> u32 {
+        self.0.as_inner()
+    }
+
+    /// Returns the numeric value of the code point if it is a leading surrogate.
+    #[inline]
+    pub fn to_lead_surrogate(&self) -> Option<u16> {
+        match self.to_u32() {
+            lead @ 0xD800..=0xDBFF => Some(lead as u16),
+            _ => None,
+        }
+    }
+
+    /// Returns the numeric value of the code point if it is a trailing surrogate.
+    #[inline]
+    pub fn to_trail_surrogate(&self) -> Option<u16> {
+        match self.to_u32() {
+            trail @ 0xDC00..=0xDFFF => Some(trail as u16),
+            _ => None,
+        }
+    }
+
+    /// Optionally returns a Unicode scalar value for the code point.
+    ///
+    /// Returns `None` if the code point is a surrogate (from U+D800 to U+DFFF).
+    #[inline]
+    pub fn to_char(&self) -> Option<char> {
+        match self.to_u32() {
+            0xD800..=0xDFFF => None,
+            // SAFETY: We explicitly check that the char is valid.
+            valid => Some(unsafe { char::from_u32_unchecked(valid) }),
+        }
+    }
+
+    /// Returns a Unicode scalar value for the code point.
+    ///
+    /// Returns `'\u{FFFD}'` (the replacement character “�”)
+    /// if the code point is a surrogate (from U+D800 to U+DFFF).
+    #[inline]
+    pub fn to_char_lossy(&self) -> char {
+        self.to_char().unwrap_or(char::REPLACEMENT_CHARACTER)
+    }
+}
+
+/// A borrowed slice of well-formed WTF-8 data.
+///
+/// Similar to `&str`, but can additionally contain surrogate code points
+/// if they’re not in a surrogate pair.
+#[derive(Eq, Ord, PartialEq, PartialOrd)]
+#[repr(transparent)]
+#[rustc_has_incoherent_inherent_impls]
+#[doc(hidden)]
+pub struct Wtf8 {
+    bytes: [u8],
+}
+
+impl AsRef<[u8]> for Wtf8 {
+    #[inline]
+    fn as_ref(&self) -> &[u8] {
+        &self.bytes
+    }
+}
+
+/// Formats the string in double quotes, with characters escaped according to
+/// [`char::escape_debug`] and unpaired surrogates represented as `\u{xxxx}`,
+/// where each `x` is a hexadecimal digit.
+impl fmt::Debug for Wtf8 {
+    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fn write_str_escaped(f: &mut fmt::Formatter<'_>, s: &str) -> fmt::Result {
+            use crate::fmt::Write;
+            for c in s.chars().flat_map(|c| c.escape_debug()) {
+                f.write_char(c)?
+            }
+            Ok(())
+        }
+
+        formatter.write_str("\"")?;
+        let mut pos = 0;
+        while let Some((surrogate_pos, surrogate)) = self.next_surrogate(pos) {
+            // SAFETY: next_surrogate provides an index for a range of valid UTF-8 bytes.
+            write_str_escaped(formatter, unsafe {
+                str::from_utf8_unchecked(&self.bytes[pos..surrogate_pos])
+            })?;
+            write!(formatter, "\\u{{{:x}}}", surrogate)?;
+            pos = surrogate_pos + 3;
+        }
+
+        // SAFETY: after next_surrogate returns None, the remainder is valid UTF-8.
+        write_str_escaped(formatter, unsafe { str::from_utf8_unchecked(&self.bytes[pos..]) })?;
+        formatter.write_str("\"")
+    }
+}
+
+/// Formats the string with unpaired surrogates substituted with the replacement
+/// character, U+FFFD.
+impl fmt::Display for Wtf8 {
+    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let wtf8_bytes = &self.bytes;
+        let mut pos = 0;
+        loop {
+            match self.next_surrogate(pos) {
+                Some((surrogate_pos, _)) => {
+                    // SAFETY: next_surrogate provides an index for a range of valid UTF-8 bytes.
+                    formatter.write_str(unsafe {
+                        str::from_utf8_unchecked(&wtf8_bytes[pos..surrogate_pos])
+                    })?;
+                    formatter.write_char(char::REPLACEMENT_CHARACTER)?;
+                    pos = surrogate_pos + 3;
+                }
+                None => {
+                    // SAFETY: after next_surrogate returns None, the remainder is valid UTF-8.
+                    let s = unsafe { str::from_utf8_unchecked(&wtf8_bytes[pos..]) };
+                    if pos == 0 { return s.fmt(formatter) } else { return formatter.write_str(s) }
+                }
+            }
+        }
+    }
+}
+
+impl Wtf8 {
+    /// Creates a WTF-8 slice from a UTF-8 `&str` slice.
+    #[inline]
+    pub fn from_str(value: &str) -> &Wtf8 {
+        // SAFETY: Since WTF-8 is a superset of UTF-8, this always is valid.
+        unsafe { Wtf8::from_bytes_unchecked(value.as_bytes()) }
+    }
+
+    /// Creates a WTF-8 slice from a WTF-8 byte slice.
+    ///
+    /// Since the byte slice is not checked for valid WTF-8, this functions is
+    /// marked unsafe.
+    #[inline]
+    pub unsafe fn from_bytes_unchecked(value: &[u8]) -> &Wtf8 {
+        // SAFETY: start with &[u8], end with fancy &[u8]
+        unsafe { &*(value as *const [u8] as *const Wtf8) }
+    }
+
+    /// Creates a mutable WTF-8 slice from a mutable WTF-8 byte slice.
+    ///
+    /// Since the byte slice is not checked for valid WTF-8, this functions is
+    /// marked unsafe.
+    #[inline]
+    pub unsafe fn from_mut_bytes_unchecked(value: &mut [u8]) -> &mut Wtf8 {
+        // SAFETY: start with &mut [u8], end with fancy &mut [u8]
+        unsafe { &mut *(value as *mut [u8] as *mut Wtf8) }
+    }
+
+    /// Returns the length, in WTF-8 bytes.
+    #[inline]
+    pub fn len(&self) -> usize {
+        self.bytes.len()
+    }
+
+    #[inline]
+    pub fn is_empty(&self) -> bool {
+        self.bytes.is_empty()
+    }
+
+    /// Returns the code point at `position` if it is in the ASCII range,
+    /// or `b'\xFF'` otherwise.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `position` is beyond the end of the string.
+    #[inline]
+    pub fn ascii_byte_at(&self, position: usize) -> u8 {
+        match self.bytes[position] {
+            ascii_byte @ 0x00..=0x7F => ascii_byte,
+            _ => 0xFF,
+        }
+    }
+
+    /// Returns an iterator for the string’s code points.
+    #[inline]
+    pub fn code_points(&self) -> Wtf8CodePoints<'_> {
+        Wtf8CodePoints { bytes: self.bytes.iter() }
+    }
+
+    /// Access raw bytes of WTF-8 data
+    #[inline]
+    pub fn as_bytes(&self) -> &[u8] {
+        &self.bytes
+    }
+
+    /// Tries to convert the string to UTF-8 and return a `&str` slice.
+    ///
+    /// Returns `None` if the string contains surrogates.
+    ///
+    /// This does not copy the data.
+    #[inline]
+    pub fn as_str(&self) -> Result<&str, str::Utf8Error> {
+        str::from_utf8(&self.bytes)
+    }
+
+    /// Converts the WTF-8 string to potentially ill-formed UTF-16
+    /// and return an iterator of 16-bit code units.
+    ///
+    /// This is lossless:
+    /// calling `Wtf8Buf::from_ill_formed_utf16` on the resulting code units
+    /// would always return the original WTF-8 string.
+    #[inline]
+    pub fn encode_wide(&self) -> EncodeWide<'_> {
+        EncodeWide { code_points: self.code_points(), extra: 0 }
+    }
+
+    #[inline]
+    pub fn next_surrogate(&self, mut pos: usize) -> Option<(usize, u16)> {
+        let mut iter = self.bytes[pos..].iter();
+        loop {
+            let b = *iter.next()?;
+            if b < 0x80 {
+                pos += 1;
+            } else if b < 0xE0 {
+                iter.next();
+                pos += 2;
+            } else if b == 0xED {
+                match (iter.next(), iter.next()) {
+                    (Some(&b2), Some(&b3)) if b2 >= 0xA0 => {
+                        return Some((pos, decode_surrogate(b2, b3)));
+                    }
+                    _ => pos += 3,
+                }
+            } else if b < 0xF0 {
+                iter.next();
+                iter.next();
+                pos += 3;
+            } else {
+                iter.next();
+                iter.next();
+                iter.next();
+                pos += 4;
+            }
+        }
+    }
+
+    #[inline]
+    pub fn final_lead_surrogate(&self) -> Option<u16> {
+        match self.bytes {
+            [.., 0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)),
+            _ => None,
+        }
+    }
+
+    #[inline]
+    pub fn initial_trail_surrogate(&self) -> Option<u16> {
+        match self.bytes {
+            [0xED, b2 @ 0xB0..=0xBF, b3, ..] => Some(decode_surrogate(b2, b3)),
+            _ => None,
+        }
+    }
+
+    #[inline]
+    pub fn make_ascii_lowercase(&mut self) {
+        self.bytes.make_ascii_lowercase()
+    }
+
+    #[inline]
+    pub fn make_ascii_uppercase(&mut self) {
+        self.bytes.make_ascii_uppercase()
+    }
+
+    #[inline]
+    pub fn is_ascii(&self) -> bool {
+        self.bytes.is_ascii()
+    }
+
+    #[inline]
+    pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
+        self.bytes.eq_ignore_ascii_case(&other.bytes)
+    }
+}
+
+/// Returns a slice of the given string for the byte range \[`begin`..`end`).
+///
+/// # Panics
+///
+/// Panics when `begin` and `end` do not point to code point boundaries,
+/// or point beyond the end of the string.
+impl ops::Index<ops::Range<usize>> for Wtf8 {
+    type Output = Wtf8;
+
+    #[inline]
+    fn index(&self, range: ops::Range<usize>) -> &Wtf8 {
+        if range.start <= range.end
+            && self.is_code_point_boundary(range.start)
+            && self.is_code_point_boundary(range.end)
+        {
+            // SAFETY: is_code_point_boundary checks that the index is valid
+            unsafe { slice_unchecked(self, range.start, range.end) }
+        } else {
+            slice_error_fail(self, range.start, range.end)
+        }
+    }
+}
+
+/// Returns a slice of the given string from byte `begin` to its end.
+///
+/// # Panics
+///
+/// Panics when `begin` is not at a code point boundary,
+/// or is beyond the end of the string.
+impl ops::Index<ops::RangeFrom<usize>> for Wtf8 {
+    type Output = Wtf8;
+
+    #[inline]
+    fn index(&self, range: ops::RangeFrom<usize>) -> &Wtf8 {
+        if self.is_code_point_boundary(range.start) {
+            // SAFETY: is_code_point_boundary checks that the index is valid
+            unsafe { slice_unchecked(self, range.start, self.len()) }
+        } else {
+            slice_error_fail(self, range.start, self.len())
+        }
+    }
+}
+
+/// Returns a slice of the given string from its beginning to byte `end`.
+///
+/// # Panics
+///
+/// Panics when `end` is not at a code point boundary,
+/// or is beyond the end of the string.
+impl ops::Index<ops::RangeTo<usize>> for Wtf8 {
+    type Output = Wtf8;
+
+    #[inline]
+    fn index(&self, range: ops::RangeTo<usize>) -> &Wtf8 {
+        if self.is_code_point_boundary(range.end) {
+            // SAFETY: is_code_point_boundary checks that the index is valid
+            unsafe { slice_unchecked(self, 0, range.end) }
+        } else {
+            slice_error_fail(self, 0, range.end)
+        }
+    }
+}
+
+impl ops::Index<ops::RangeFull> for Wtf8 {
+    type Output = Wtf8;
+
+    #[inline]
+    fn index(&self, _range: ops::RangeFull) -> &Wtf8 {
+        self
+    }
+}
+
+#[inline]
+fn decode_surrogate(second_byte: u8, third_byte: u8) -> u16 {
+    // The first byte is assumed to be 0xED
+    0xD800 | (second_byte as u16 & 0x3F) << 6 | third_byte as u16 & 0x3F
+}
+
+impl Wtf8 {
+    /// Copied from str::is_char_boundary
+    #[inline]
+    pub fn is_code_point_boundary(&self, index: usize) -> bool {
+        if index == 0 {
+            return true;
+        }
+        match self.bytes.get(index) {
+            None => index == self.len(),
+            Some(&b) => (b as i8) >= -0x40,
+        }
+    }
+
+    /// Verify that `index` is at the edge of either a valid UTF-8 codepoint
+    /// (i.e. a codepoint that's not a surrogate) or of the whole string.
+    ///
+    /// These are the cases currently permitted by `OsStr::self_encoded_bytes`.
+    /// Splitting between surrogates is valid as far as WTF-8 is concerned, but
+    /// we do not permit it in the public API because WTF-8 is considered an
+    /// implementation detail.
+    #[track_caller]
+    #[inline]
+    pub fn check_utf8_boundary(&self, index: usize) {
+        if index == 0 {
+            return;
+        }
+        match self.bytes.get(index) {
+            Some(0xED) => (), // Might be a surrogate
+            Some(&b) if (b as i8) >= -0x40 => return,
+            Some(_) => panic!("byte index {index} is not a codepoint boundary"),
+            None if index == self.len() => return,
+            None => panic!("byte index {index} is out of bounds"),
+        }
+        if self.bytes[index + 1] >= 0xA0 {
+            // There's a surrogate after index. Now check before index.
+            if index >= 3 && self.bytes[index - 3] == 0xED && self.bytes[index - 2] >= 0xA0 {
+                panic!("byte index {index} lies between surrogate codepoints");
+            }
+        }
+    }
+}
+
+/// Copied from core::str::raw::slice_unchecked
+#[inline]
+unsafe fn slice_unchecked(s: &Wtf8, begin: usize, end: usize) -> &Wtf8 {
+    // SAFETY: memory layout of a &[u8] and &Wtf8 are the same
+    unsafe {
+        let len = end - begin;
+        let start = s.as_bytes().as_ptr().add(begin);
+        Wtf8::from_bytes_unchecked(slice::from_raw_parts(start, len))
+    }
+}
+
+/// Copied from core::str::raw::slice_error_fail
+#[inline(never)]
+fn slice_error_fail(s: &Wtf8, begin: usize, end: usize) -> ! {
+    assert!(begin <= end);
+    panic!("index {begin} and/or {end} in `{s:?}` do not lie on character boundary");
+}
+
+/// Iterator for the code points of a WTF-8 string.
+///
+/// Created with the method `.code_points()`.
+#[derive(Clone)]
+#[doc(hidden)]
+pub struct Wtf8CodePoints<'a> {
+    bytes: slice::Iter<'a, u8>,
+}
+
+impl Iterator for Wtf8CodePoints<'_> {
+    type Item = CodePoint;
+
+    #[inline]
+    fn next(&mut self) -> Option<CodePoint> {
+        // SAFETY: `self.bytes` has been created from a WTF-8 string
+        unsafe { next_code_point(&mut self.bytes).map(|c| CodePoint::from_u32_unchecked(c)) }
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let len = self.bytes.len();
+        (len.saturating_add(3) / 4, Some(len))
+    }
+}
+
+impl fmt::Debug for Wtf8CodePoints<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_tuple("Wtf8CodePoints")
+            // SAFETY: We always leave the string in a valid state after each iteration.
+            .field(&unsafe { Wtf8::from_bytes_unchecked(self.bytes.as_slice()) })
+            .finish()
+    }
+}
+
+/// Generates a wide character sequence for potentially ill-formed UTF-16.
+#[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Clone)]
+#[doc(hidden)]
+pub struct EncodeWide<'a> {
+    code_points: Wtf8CodePoints<'a>,
+    extra: u16,
+}
+
+// Copied from libunicode/u_str.rs
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Iterator for EncodeWide<'_> {
+    type Item = u16;
+
+    #[inline]
+    fn next(&mut self) -> Option<u16> {
+        if self.extra != 0 {
+            let tmp = self.extra;
+            self.extra = 0;
+            return Some(tmp);
+        }
+
+        let mut buf = [0; MAX_LEN_UTF16];
+        self.code_points.next().map(|code_point| {
+            let n = encode_utf16_raw(code_point.to_u32(), &mut buf).len();
+            if n == 2 {
+                self.extra = buf[1];
+            }
+            buf[0]
+        })
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        let (low, high) = self.code_points.size_hint();
+        let ext = (self.extra != 0) as usize;
+        // every code point gets either one u16 or two u16,
+        // so this iterator is between 1 or 2 times as
+        // long as the underlying iterator.
+        (low + ext, high.and_then(|n| n.checked_mul(2)).and_then(|n| n.checked_add(ext)))
+    }
+}
+
+impl fmt::Debug for EncodeWide<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct("EncodeWide").finish_non_exhaustive()
+    }
+}
+
+#[stable(feature = "encode_wide_fused_iterator", since = "1.62.0")]
+impl FusedIterator for EncodeWide<'_> {}
+
+impl Hash for CodePoint {
+    #[inline]
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.0.hash(state)
+    }
+}
+
+impl Hash for Wtf8 {
+    #[inline]
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        state.write(&self.bytes);
+        0xfeu8.hash(state)
+    }
+}
+
+#[unstable(feature = "clone_to_uninit", issue = "126799")]
+unsafe impl CloneToUninit for Wtf8 {
+    #[inline]
+    #[cfg_attr(debug_assertions, track_caller)]
+    unsafe fn clone_to_uninit(&self, dst: *mut u8) {
+        // SAFETY: we're just a transparent wrapper around [u8]
+        unsafe { self.bytes.clone_to_uninit(dst) }
+    }
+}
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
index d2281b1df2f..b9b768f29d7 100644
--- a/library/coretests/tests/lib.rs
+++ b/library/coretests/tests/lib.rs
@@ -80,6 +80,7 @@
 #![feature(next_index)]
 #![feature(non_exhaustive_omitted_patterns_lint)]
 #![feature(numfmt)]
+#![feature(option_reduce)]
 #![feature(pattern)]
 #![feature(pointer_is_aligned_to)]
 #![feature(portable_simd)]
@@ -194,6 +195,7 @@ mod time;
 mod tuple;
 mod unicode;
 mod waker;
+mod wtf8;
 
 /// Copied from `std::test_helpers::test_rng`, see that function for rationale.
 #[track_caller]
diff --git a/library/coretests/tests/wtf8.rs b/library/coretests/tests/wtf8.rs
new file mode 100644
index 00000000000..9f187e70630
--- /dev/null
+++ b/library/coretests/tests/wtf8.rs
@@ -0,0 +1 @@
+// All `wtf8` tests live in library/alloctests/tests/wtf8.rs
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 15a7a770d1a..fc0fef620e3 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -1875,12 +1875,7 @@ impl<'a, K: Debug, V: Debug> fmt::Display for OccupiedError<'a, K, V> {
 }
 
 #[unstable(feature = "map_try_insert", issue = "82766")]
-impl<'a, K: fmt::Debug, V: fmt::Debug> Error for OccupiedError<'a, K, V> {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "key already exists"
-    }
-}
+impl<'a, K: Debug, V: Debug> Error for OccupiedError<'a, K, V> {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, K, V, S> IntoIterator for &'a HashMap<K, V, S> {
diff --git a/library/std/src/env.rs b/library/std/src/env.rs
index 9f17ff76445..e457cd61c75 100644
--- a/library/std/src/env.rs
+++ b/library/std/src/env.rs
@@ -296,15 +296,7 @@ impl fmt::Display for VarError {
 }
 
 #[stable(feature = "env", since = "1.0.0")]
-impl Error for VarError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        match *self {
-            VarError::NotPresent => "environment variable not found",
-            VarError::NotUnicode(..) => "environment variable was not valid unicode",
-        }
-    }
-}
+impl Error for VarError {}
 
 /// Sets the environment variable `key` to the value `value` for the currently running
 /// process.
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index 1ed4f2f9f0c..d9c9606fc1c 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -3036,6 +3036,9 @@ pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
 /// Entries for the current and parent directories (typically `.` and `..`) are
 /// skipped.
 ///
+/// The order in which `read_dir` returns entries can change between calls. If reproducible
+/// ordering is required, the entries should be explicitly sorted.
+///
 /// # Platform-specific behavior
 ///
 /// This function currently corresponds to the `opendir` function on Unix
diff --git a/library/std/src/io/buffered/bufwriter.rs b/library/std/src/io/buffered/bufwriter.rs
index 574eb83dc56..d569fed24c5 100644
--- a/library/std/src/io/buffered/bufwriter.rs
+++ b/library/std/src/io/buffered/bufwriter.rs
@@ -492,23 +492,15 @@ impl WriterPanicked {
     pub fn into_inner(self) -> Vec<u8> {
         self.buf
     }
-
-    const DESCRIPTION: &'static str =
-        "BufWriter inner writer panicked, what data remains unwritten is not known";
 }
 
 #[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
-impl error::Error for WriterPanicked {
-    #[allow(deprecated, deprecated_in_future)]
-    fn description(&self) -> &str {
-        Self::DESCRIPTION
-    }
-}
+impl error::Error for WriterPanicked {}
 
 #[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
 impl fmt::Display for WriterPanicked {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}", Self::DESCRIPTION)
+        "BufWriter inner writer panicked, what data remains unwritten is not known".fmt(f)
     }
 }
 
diff --git a/library/std/src/io/buffered/mod.rs b/library/std/src/io/buffered/mod.rs
index 475d877528f..e36f2d92108 100644
--- a/library/std/src/io/buffered/mod.rs
+++ b/library/std/src/io/buffered/mod.rs
@@ -179,12 +179,7 @@ impl<W> From<IntoInnerError<W>> for Error {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<W: Send + fmt::Debug> error::Error for IntoInnerError<W> {
-    #[allow(deprecated, deprecated_in_future)]
-    fn description(&self) -> &str {
-        error::Error::description(self.error())
-    }
-}
+impl<W: Send + fmt::Debug> error::Error for IntoInnerError<W> {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<W> fmt::Display for IntoInnerError<W> {
diff --git a/library/std/src/io/error.rs b/library/std/src/io/error.rs
index dcfa189823f..57a980d6acd 100644
--- a/library/std/src/io/error.rs
+++ b/library/std/src/io/error.rs
@@ -1049,15 +1049,6 @@ impl fmt::Display for Error {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl error::Error for Error {
-    #[allow(deprecated, deprecated_in_future)]
-    fn description(&self) -> &str {
-        match self.repr.data() {
-            ErrorData::Os(..) | ErrorData::Simple(..) => self.kind().as_str(),
-            ErrorData::SimpleMessage(msg) => msg.message,
-            ErrorData::Custom(c) => c.error.description(),
-        }
-    }
-
     #[allow(deprecated)]
     fn cause(&self) -> Option<&dyn error::Error> {
         match self.repr.data() {
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index ab417b6c72f..30a1b108817 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -15,7 +15,7 @@
 //!
 //! If you already know the name of what you are looking for, the fastest way to
 //! find it is to use the <a href="#" onclick="window.searchState.focus();">search
-//! bar</a> at the top of the page.
+//! button</a> at the top of the page.
 //!
 //! Otherwise, you may want to jump to one of these useful sections:
 //!
@@ -391,6 +391,7 @@
 #![feature(try_with_capacity)]
 #![feature(unique_rc_arc)]
 #![feature(vec_into_raw_parts)]
+#![feature(wtf8_internals)]
 // tidy-alphabetical-end
 //
 // Library features (unwind):
diff --git a/library/std/src/os/windows/ffi.rs b/library/std/src/os/windows/ffi.rs
index 496443dbbc3..345d5b74285 100644
--- a/library/std/src/os/windows/ffi.rs
+++ b/library/std/src/os/windows/ffi.rs
@@ -53,12 +53,13 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
+use alloc::wtf8::Wtf8Buf;
+
 use crate::ffi::{OsStr, OsString};
+use crate::fmt;
+use crate::iter::FusedIterator;
 use crate::sealed::Sealed;
 use crate::sys::os_str::Buf;
-#[stable(feature = "rust1", since = "1.0.0")]
-pub use crate::sys_common::wtf8::EncodeWide;
-use crate::sys_common::wtf8::Wtf8Buf;
 use crate::sys_common::{AsInner, FromInner};
 
 /// Windows-specific extensions to [`OsString`].
@@ -130,6 +131,35 @@ pub trait OsStrExt: Sealed {
 impl OsStrExt for OsStr {
     #[inline]
     fn encode_wide(&self) -> EncodeWide<'_> {
-        self.as_inner().inner.encode_wide()
+        EncodeWide { inner: self.as_inner().inner.encode_wide() }
+    }
+}
+
+/// Iterator returned by [`OsStrExt::encode_wide`].
+#[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Clone)]
+pub struct EncodeWide<'a> {
+    inner: alloc::wtf8::EncodeWide<'a>,
+}
+#[stable(feature = "encode_wide_debug", since = "CURRENT_RUSTC_VERSION")]
+impl fmt::Debug for EncodeWide<'_> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Debug::fmt(&self.inner, f)
+    }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Iterator for EncodeWide<'_> {
+    type Item = u16;
+
+    #[inline]
+    fn next(&mut self) -> Option<u16> {
+        self.inner.next()
+    }
+
+    #[inline]
+    fn size_hint(&self) -> (usize, Option<usize>) {
+        self.inner.size_hint()
     }
 }
+#[stable(feature = "encode_wide_fused_iterator", since = "1.62.0")]
+impl FusedIterator for EncodeWide<'_> {}
diff --git a/library/std/src/os/windows/io/socket.rs b/library/std/src/os/windows/io/socket.rs
index 1c228914de9..28e972925e6 100644
--- a/library/std/src/os/windows/io/socket.rs
+++ b/library/std/src/os/windows/io/socket.rs
@@ -54,7 +54,7 @@ impl BorrowedSocket<'_> {
     ///
     /// # Safety
     ///
-    /// The resource pointed to by `raw` must remain open for the duration of
+    /// The resource pointed to by `socket` must remain open for the duration of
     /// the returned `BorrowedSocket`, and it must not have the value
     /// `INVALID_SOCKET`.
     #[inline]
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 3899fbf86db..470d300d2d9 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -3677,19 +3677,13 @@ impl_cmp_os_str!(<'a> Cow<'a, Path>, OsString);
 
 #[stable(since = "1.7.0", feature = "strip_prefix")]
 impl fmt::Display for StripPrefixError {
-    #[allow(deprecated, deprecated_in_future)]
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.description().fmt(f)
+        "prefix not found".fmt(f)
     }
 }
 
 #[stable(since = "1.7.0", feature = "strip_prefix")]
-impl Error for StripPrefixError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "prefix not found"
-    }
-}
+impl Error for StripPrefixError {}
 
 #[unstable(feature = "normalize_lexically", issue = "134694")]
 impl fmt::Display for NormalizeError {
diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs
index a40e29a772a..3231125f7a1 100644
--- a/library/std/src/sync/lazy_lock.rs
+++ b/library/std/src/sync/lazy_lock.rs
@@ -244,7 +244,11 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
     #[inline]
     #[stable(feature = "lazy_cell", since = "1.80.0")]
     pub fn force(this: &LazyLock<T, F>) -> &T {
-        this.once.call_once(|| {
+        this.once.call_once_force(|state| {
+            if state.is_poisoned() {
+                panic_poisoned();
+            }
+
             // SAFETY: `call_once` only runs this closure once, ever.
             let data = unsafe { &mut *this.data.get() };
             let f = unsafe { ManuallyDrop::take(&mut data.f) };
@@ -257,8 +261,7 @@ impl<T, F: FnOnce() -> T> LazyLock<T, F> {
         // * the closure was called and initialized `value`.
         // * the closure was called and panicked, so this point is never reached.
         // * the closure was not called, but a previous call initialized `value`.
-        // * the closure was not called because the Once is poisoned, so this point
-        //   is never reached.
+        // * the closure was not called because the Once is poisoned, which we handled above.
         // So `value` has definitely been initialized and will not be modified again.
         unsafe { &*(*this.data.get()).value }
     }
diff --git a/library/std/src/sync/mpmc/utils.rs b/library/std/src/sync/mpmc/utils.rs
index 0cbc61160f7..e3bcb149f64 100644
--- a/library/std/src/sync/mpmc/utils.rs
+++ b/library/std/src/sync/mpmc/utils.rs
@@ -23,14 +23,13 @@ use crate::ops::{Deref, DerefMut};
     any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "powerpc64",),
     repr(align(128))
 )]
-// arm, mips, mips64, and riscv64 have 32-byte cache line size.
+// arm, mips and mips64 have 32-byte cache line size.
 //
 // Sources:
 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_arm.go#L7
 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips.go#L7
 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mipsle.go#L7
 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_mips64x.go#L9
-// - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_riscv64.go#L7
 #[cfg_attr(
     any(
         target_arch = "arm",
@@ -38,7 +37,6 @@ use crate::ops::{Deref, DerefMut};
         target_arch = "mips32r6",
         target_arch = "mips64",
         target_arch = "mips64r6",
-        target_arch = "riscv64",
     ),
     repr(align(32))
 )]
@@ -47,11 +45,12 @@ use crate::ops::{Deref, DerefMut};
 // Sources:
 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_s390x.go#L7
 #[cfg_attr(target_arch = "s390x", repr(align(256)))]
-// x86 and wasm have 64-byte cache line size.
+// x86, wasm and riscv have 64-byte cache line size.
 //
 // Sources:
 // - https://github.com/golang/go/blob/dda2991c2ea0c5914714469c4defc2562a907230/src/internal/cpu/cpu_x86.go#L9
 // - https://github.com/golang/go/blob/3dd58676054223962cd915bb0934d1f9f489d4d2/src/internal/cpu/cpu_wasm.go#L7
+// - https://github.com/golang/go/blob/5e31f78c8a4ed1b872ddc194f0cd1ae931b37d7e/src/internal/cpu/cpu_riscv64.go#L7
 //
 // All others are assumed to have 64-byte cache line size.
 #[cfg_attr(
@@ -64,7 +63,6 @@ use crate::ops::{Deref, DerefMut};
         target_arch = "mips32r6",
         target_arch = "mips64",
         target_arch = "mips64r6",
-        target_arch = "riscv64",
         target_arch = "s390x",
     )),
     repr(align(64))
diff --git a/library/std/src/sync/mpsc.rs b/library/std/src/sync/mpsc.rs
index 03d7fddc2fa..f91c26aa22c 100644
--- a/library/std/src/sync/mpsc.rs
+++ b/library/std/src/sync/mpsc.rs
@@ -1108,12 +1108,7 @@ impl<T> fmt::Display for SendError<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> error::Error for SendError<T> {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "sending on a closed channel"
-    }
-}
+impl<T> error::Error for SendError<T> {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> fmt::Debug for TrySendError<T> {
@@ -1136,15 +1131,7 @@ impl<T> fmt::Display for TrySendError<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> error::Error for TrySendError<T> {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        match *self {
-            TrySendError::Full(..) => "sending on a full channel",
-            TrySendError::Disconnected(..) => "sending on a closed channel",
-        }
-    }
-}
+impl<T> error::Error for TrySendError<T> {}
 
 #[stable(feature = "mpsc_error_conversions", since = "1.24.0")]
 impl<T> From<SendError<T>> for TrySendError<T> {
@@ -1168,12 +1155,7 @@ impl fmt::Display for RecvError {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl error::Error for RecvError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "receiving on a closed channel"
-    }
-}
+impl error::Error for RecvError {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for TryRecvError {
@@ -1186,15 +1168,7 @@ impl fmt::Display for TryRecvError {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl error::Error for TryRecvError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        match *self {
-            TryRecvError::Empty => "receiving on an empty channel",
-            TryRecvError::Disconnected => "receiving on a closed channel",
-        }
-    }
-}
+impl error::Error for TryRecvError {}
 
 #[stable(feature = "mpsc_error_conversions", since = "1.24.0")]
 impl From<RecvError> for TryRecvError {
@@ -1221,15 +1195,7 @@ impl fmt::Display for RecvTimeoutError {
 }
 
 #[stable(feature = "mpsc_recv_timeout_error", since = "1.15.0")]
-impl error::Error for RecvTimeoutError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        match *self {
-            RecvTimeoutError::Timeout => "timed out waiting on channel",
-            RecvTimeoutError::Disconnected => "channel is empty and sending half is closed",
-        }
-    }
-}
+impl error::Error for RecvTimeoutError {}
 
 #[stable(feature = "mpsc_error_conversions", since = "1.24.0")]
 impl From<RecvError> for RecvTimeoutError {
diff --git a/library/std/src/sync/poison.rs b/library/std/src/sync/poison.rs
index 31889dcc10f..49a71b9ad10 100644
--- a/library/std/src/sync/poison.rs
+++ b/library/std/src/sync/poison.rs
@@ -263,12 +263,7 @@ impl<T> fmt::Display for PoisonError<T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Error for PoisonError<T> {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "poisoned lock: another task failed inside"
-    }
-}
+impl<T> Error for PoisonError<T> {}
 
 impl<T> PoisonError<T> {
     /// Creates a `PoisonError`.
@@ -376,17 +371,6 @@ impl<T> fmt::Display for TryLockError<T> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Error for TryLockError<T> {
-    #[allow(deprecated, deprecated_in_future)]
-    fn description(&self) -> &str {
-        match *self {
-            #[cfg(panic = "unwind")]
-            TryLockError::Poisoned(ref p) => p.description(),
-            #[cfg(not(panic = "unwind"))]
-            TryLockError::Poisoned(ref p) => match p._never {},
-            TryLockError::WouldBlock => "try_lock failed because the operation would block",
-        }
-    }
-
     #[allow(deprecated)]
     fn cause(&self) -> Option<&dyn Error> {
         match *self {
diff --git a/library/std/src/sys/alloc/wasm.rs b/library/std/src/sys/alloc/wasm.rs
index c8fab992a88..48e2fdd4ecc 100644
--- a/library/std/src/sys/alloc/wasm.rs
+++ b/library/std/src/sys/alloc/wasm.rs
@@ -16,12 +16,15 @@
 //! 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 core::cell::SyncUnsafeCell;
 
 use crate::alloc::{GlobalAlloc, Layout, System};
 
-static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::Dlmalloc::new();
+struct SyncDlmalloc(dlmalloc::Dlmalloc);
+unsafe impl Sync for SyncDlmalloc {}
+
+static DLMALLOC: SyncUnsafeCell<SyncDlmalloc> =
+    SyncUnsafeCell::new(SyncDlmalloc(dlmalloc::Dlmalloc::new()));
 
 #[stable(feature = "alloc_system_type", since = "1.28.0")]
 unsafe impl GlobalAlloc for System {
@@ -30,7 +33,7 @@ unsafe impl GlobalAlloc for System {
         // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access.
         // Calling malloc() is safe because preconditions on this function match the trait method preconditions.
         let _lock = lock::lock();
-        unsafe { DLMALLOC.malloc(layout.size(), layout.align()) }
+        unsafe { (*DLMALLOC.get()).0.malloc(layout.size(), layout.align()) }
     }
 
     #[inline]
@@ -38,7 +41,7 @@ unsafe impl GlobalAlloc for System {
         // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access.
         // Calling calloc() is safe because preconditions on this function match the trait method preconditions.
         let _lock = lock::lock();
-        unsafe { DLMALLOC.calloc(layout.size(), layout.align()) }
+        unsafe { (*DLMALLOC.get()).0.calloc(layout.size(), layout.align()) }
     }
 
     #[inline]
@@ -46,7 +49,7 @@ unsafe impl GlobalAlloc for System {
         // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access.
         // Calling free() is safe because preconditions on this function match the trait method preconditions.
         let _lock = lock::lock();
-        unsafe { DLMALLOC.free(ptr, layout.size(), layout.align()) }
+        unsafe { (*DLMALLOC.get()).0.free(ptr, layout.size(), layout.align()) }
     }
 
     #[inline]
@@ -54,7 +57,7 @@ unsafe impl GlobalAlloc for System {
         // SAFETY: DLMALLOC access is guaranteed to be safe because the lock gives us unique and non-reentrant access.
         // Calling realloc() is safe because preconditions on this function match the trait method preconditions.
         let _lock = lock::lock();
-        unsafe { DLMALLOC.realloc(ptr, layout.size(), layout.align(), new_size) }
+        unsafe { (*DLMALLOC.get()).0.realloc(ptr, layout.size(), layout.align(), new_size) }
     }
 }
 
diff --git a/library/std/src/sys/fd/unix.rs b/library/std/src/sys/fd/unix.rs
index cdca73cdca1..a12f692e754 100644
--- a/library/std/src/sys/fd/unix.rs
+++ b/library/std/src/sys/fd/unix.rs
@@ -37,10 +37,10 @@ pub struct FileDesc(OwnedFd);
 //
 // On Apple targets however, apparently the 64-bit libc is either buggy or
 // intentionally showing odd behavior by rejecting any read with a size
-// larger than or equal to INT_MAX. To handle both of these the read
-// size is capped on both platforms.
+// larger than INT_MAX. To handle both of these the read size is capped on
+// both platforms.
 const READ_LIMIT: usize = if cfg!(target_vendor = "apple") {
-    libc::c_int::MAX as usize - 1
+    libc::c_int::MAX as usize
 } else {
     libc::ssize_t::MAX as usize
 };
diff --git a/library/std/src/sys/fs/mod.rs b/library/std/src/sys/fs/mod.rs
index dbd782f5018..0276bf6e64c 100644
--- a/library/std/src/sys/fs/mod.rs
+++ b/library/std/src/sys/fs/mod.rs
@@ -117,9 +117,18 @@ pub fn set_permissions(path: &Path, perm: FilePermissions) -> io::Result<()> {
 #[cfg(unix)]
 pub fn set_permissions_nofollow(path: &Path, perm: crate::fs::Permissions) -> io::Result<()> {
     use crate::fs::OpenOptions;
-    use crate::os::unix::fs::OpenOptionsExt;
 
-    OpenOptions::new().custom_flags(libc::O_NOFOLLOW).open(path)?.set_permissions(perm)
+    let mut options = OpenOptions::new();
+
+    // ESP-IDF and Horizon do not support O_NOFOLLOW, so we skip setting it.
+    // Their filesystems do not have symbolic links, so no special handling is required.
+    #[cfg(not(any(target_os = "espidf", target_os = "horizon")))]
+    {
+        use crate::os::unix::fs::OpenOptionsExt;
+        options.custom_flags(libc::O_NOFOLLOW);
+    }
+
+    options.open(path)?.set_permissions(perm)
 }
 
 #[cfg(not(unix))]
diff --git a/library/std/src/sys/net/connection/sgx.rs b/library/std/src/sys/net/connection/sgx.rs
index 242df10bc32..2389fd1bcb6 100644
--- a/library/std/src/sys/net/connection/sgx.rs
+++ b/library/std/src/sys/net/connection/sgx.rs
@@ -452,12 +452,7 @@ pub struct NonIpSockAddr {
     host: String,
 }
 
-impl error::Error for NonIpSockAddr {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "Failed to convert address to SocketAddr"
-    }
-}
+impl error::Error for NonIpSockAddr {}
 
 impl fmt::Display for NonIpSockAddr {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/library/std/src/sys/os_str/wtf8.rs b/library/std/src/sys/os_str/wtf8.rs
index bbc704ebf86..96da891874e 100644
--- a/library/std/src/sys/os_str/wtf8.rs
+++ b/library/std/src/sys/os_str/wtf8.rs
@@ -1,12 +1,12 @@
 //! The underlying OsString/OsStr implementation on Windows is a
 //! wrapper around the "WTF-8" encoding; see the `wtf8` module for more.
+use alloc::wtf8::{Wtf8, Wtf8Buf};
 use core::clone::CloneToUninit;
 
 use crate::borrow::Cow;
 use crate::collections::TryReserveError;
 use crate::rc::Rc;
 use crate::sync::Arc;
-use crate::sys_common::wtf8::{Wtf8, Wtf8Buf, check_utf8_boundary};
 use crate::sys_common::{AsInner, FromInner, IntoInner};
 use crate::{fmt, mem};
 
@@ -220,7 +220,9 @@ impl Buf {
     /// trailing surrogate half.
     #[inline]
     pub unsafe fn extend_from_slice_unchecked(&mut self, other: &[u8]) {
-        self.inner.extend_from_slice(other);
+        unsafe {
+            self.inner.extend_from_slice_unchecked(other);
+        }
     }
 }
 
@@ -238,7 +240,7 @@ impl Slice {
     #[track_caller]
     #[inline]
     pub fn check_public_boundary(&self, index: usize) {
-        check_utf8_boundary(&self.inner, index);
+        self.inner.check_utf8_boundary(index);
     }
 
     #[inline]
diff --git a/library/std/src/sys/pal/hermit/os.rs b/library/std/src/sys/pal/hermit/os.rs
index a998c3165e5..0fe713a503b 100644
--- a/library/std/src/sys/pal/hermit/os.rs
+++ b/library/std/src/sys/pal/hermit/os.rs
@@ -1,5 +1,4 @@
 use super::hermit_abi;
-use crate::error::Error as StdError;
 use crate::ffi::{OsStr, OsString};
 use crate::marker::PhantomData;
 use crate::path::{self, PathBuf};
@@ -52,12 +51,7 @@ impl fmt::Display for JoinPathsError {
     }
 }
 
-impl StdError for JoinPathsError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "not supported on hermit yet"
-    }
-}
+impl crate::error::Error for JoinPathsError {}
 
 pub fn current_exe() -> io::Result<PathBuf> {
     unsupported()
diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs
index 6e43a79ddec..4a297b6823f 100644
--- a/library/std/src/sys/pal/sgx/mod.rs
+++ b/library/std/src/sys/pal/sgx/mod.rs
@@ -59,8 +59,7 @@ pub fn sgx_ineffective<T>(v: T) -> crate::io::Result<T> {
 
 #[inline]
 pub fn is_interrupted(code: i32) -> bool {
-    use fortanix_sgx_abi::Error;
-    code == Error::Interrupted as _
+    code == fortanix_sgx_abi::Error::Interrupted as _
 }
 
 pub fn decode_error_kind(code: i32) -> ErrorKind {
diff --git a/library/std/src/sys/pal/sgx/os.rs b/library/std/src/sys/pal/sgx/os.rs
index 70f838679c9..28d79963ac8 100644
--- a/library/std/src/sys/pal/sgx/os.rs
+++ b/library/std/src/sys/pal/sgx/os.rs
@@ -1,11 +1,10 @@
 use fortanix_sgx_abi::{Error, RESULT_SUCCESS};
 
-use crate::error::Error as StdError;
 use crate::ffi::{OsStr, OsString};
 use crate::marker::PhantomData;
 use crate::path::{self, PathBuf};
 use crate::sys::{decode_error_kind, sgx_ineffective, unsupported};
-use crate::{fmt, io, str};
+use crate::{fmt, io};
 
 pub fn errno() -> i32 {
     RESULT_SUCCESS
@@ -59,12 +58,7 @@ impl fmt::Display for JoinPathsError {
     }
 }
 
-impl StdError for JoinPathsError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "not supported in SGX yet"
-    }
-}
+impl crate::error::Error for JoinPathsError {}
 
 pub fn current_exe() -> io::Result<PathBuf> {
     unsupported()
diff --git a/library/std/src/sys/pal/solid/os.rs b/library/std/src/sys/pal/solid/os.rs
index 8f5976b0592..cb6e2cbceae 100644
--- a/library/std/src/sys/pal/solid/os.rs
+++ b/library/std/src/sys/pal/solid/os.rs
@@ -1,5 +1,4 @@
 use super::{error, itron, unsupported};
-use crate::error::Error as StdError;
 use crate::ffi::{OsStr, OsString};
 use crate::path::{self, PathBuf};
 use crate::{fmt, io};
@@ -58,12 +57,7 @@ impl fmt::Display for JoinPathsError {
     }
 }
 
-impl StdError for JoinPathsError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "not supported on this platform yet"
-    }
-}
+impl crate::error::Error for JoinPathsError {}
 
 pub fn current_exe() -> io::Result<PathBuf> {
     unsupported()
diff --git a/library/std/src/sys/pal/teeos/os.rs b/library/std/src/sys/pal/teeos/os.rs
index 03f3c72b022..512b3e2885b 100644
--- a/library/std/src/sys/pal/teeos/os.rs
+++ b/library/std/src/sys/pal/teeos/os.rs
@@ -3,7 +3,6 @@
 use core::marker::PhantomData;
 
 use super::unsupported;
-use crate::error::Error as StdError;
 use crate::ffi::{OsStr, OsString};
 use crate::path::PathBuf;
 use crate::{fmt, io, path};
@@ -62,12 +61,7 @@ impl fmt::Display for JoinPathsError {
     }
 }
 
-impl StdError for JoinPathsError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "not supported on this platform yet"
-    }
-}
+impl crate::error::Error for JoinPathsError {}
 
 pub fn current_exe() -> io::Result<PathBuf> {
     unsupported()
diff --git a/library/std/src/sys/pal/uefi/os.rs b/library/std/src/sys/pal/uefi/os.rs
index bfd4dc81cb4..aae6cb9e064 100644
--- a/library/std/src/sys/pal/uefi/os.rs
+++ b/library/std/src/sys/pal/uefi/os.rs
@@ -2,7 +2,6 @@ use r_efi::efi::Status;
 use r_efi::efi::protocols::{device_path, loaded_image_device_path};
 
 use super::{RawOsError, helpers, unsupported_err};
-use crate::error::Error as StdError;
 use crate::ffi::{OsStr, OsString};
 use crate::marker::PhantomData;
 use crate::os::uefi;
@@ -122,7 +121,7 @@ impl fmt::Display for JoinPathsError {
     }
 }
 
-impl StdError for JoinPathsError {}
+impl crate::error::Error for JoinPathsError {}
 
 pub fn current_exe() -> io::Result<PathBuf> {
     let protocol = helpers::image_handle_protocol::<device_path::Protocol>(
diff --git a/library/std/src/sys/pal/unix/os.rs b/library/std/src/sys/pal/unix/os.rs
index 1110b775c09..81275afa707 100644
--- a/library/std/src/sys/pal/unix/os.rs
+++ b/library/std/src/sys/pal/unix/os.rs
@@ -7,7 +7,6 @@ mod tests;
 
 use libc::{c_char, c_int, c_void};
 
-use crate::error::Error as StdError;
 use crate::ffi::{CStr, OsStr, OsString};
 use crate::os::unix::prelude::*;
 use crate::path::{self, PathBuf};
@@ -248,12 +247,7 @@ impl fmt::Display for JoinPathsError {
     }
 }
 
-impl StdError for JoinPathsError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "failed to join paths"
-    }
-}
+impl crate::error::Error for JoinPathsError {}
 
 #[cfg(target_os = "aix")]
 pub fn current_exe() -> io::Result<PathBuf> {
diff --git a/library/std/src/sys/pal/unsupported/os.rs b/library/std/src/sys/pal/unsupported/os.rs
index a8ef97ecf67..13d2a2044f4 100644
--- a/library/std/src/sys/pal/unsupported/os.rs
+++ b/library/std/src/sys/pal/unsupported/os.rs
@@ -1,5 +1,4 @@
 use super::unsupported;
-use crate::error::Error as StdError;
 use crate::ffi::{OsStr, OsString};
 use crate::marker::PhantomData;
 use crate::path::{self, PathBuf};
@@ -51,12 +50,7 @@ impl fmt::Display for JoinPathsError {
     }
 }
 
-impl StdError for JoinPathsError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "not supported on this platform yet"
-    }
-}
+impl crate::error::Error for JoinPathsError {}
 
 pub fn current_exe() -> io::Result<PathBuf> {
     unsupported()
diff --git a/library/std/src/sys/pal/wasi/os.rs b/library/std/src/sys/pal/wasi/os.rs
index 672cf70d1a5..151ba254ec4 100644
--- a/library/std/src/sys/pal/wasi/os.rs
+++ b/library/std/src/sys/pal/wasi/os.rs
@@ -1,6 +1,5 @@
 #![forbid(unsafe_op_in_unsafe_fn)]
 
-use crate::error::Error as StdError;
 use crate::ffi::{CStr, OsStr, OsString};
 use crate::marker::PhantomData;
 use crate::os::wasi::prelude::*;
@@ -105,12 +104,7 @@ impl fmt::Display for JoinPathsError {
     }
 }
 
-impl StdError for JoinPathsError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "not supported on wasm yet"
-    }
-}
+impl crate::error::Error for JoinPathsError {}
 
 pub fn current_exe() -> io::Result<PathBuf> {
     unsupported()
diff --git a/library/std/src/sys/pal/windows/os.rs b/library/std/src/sys/pal/windows/os.rs
index f331282d2d7..1b3c80c079b 100644
--- a/library/std/src/sys/pal/windows/os.rs
+++ b/library/std/src/sys/pal/windows/os.rs
@@ -8,7 +8,6 @@ mod tests;
 use super::api;
 #[cfg(not(target_vendor = "uwp"))]
 use super::api::WinError;
-use crate::error::Error as StdError;
 use crate::ffi::{OsStr, OsString};
 use crate::os::windows::ffi::EncodeWide;
 use crate::os::windows::prelude::*;
@@ -162,12 +161,7 @@ impl fmt::Display for JoinPathsError {
     }
 }
 
-impl StdError for JoinPathsError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "failed to join paths"
-    }
-}
+impl crate::error::Error for JoinPathsError {}
 
 pub fn current_exe() -> io::Result<PathBuf> {
     super::fill_utf16_buf(
diff --git a/library/std/src/sys/pal/xous/os.rs b/library/std/src/sys/pal/xous/os.rs
index d612a27d2bd..d9b8418e6c3 100644
--- a/library/std/src/sys/pal/xous/os.rs
+++ b/library/std/src/sys/pal/xous/os.rs
@@ -1,5 +1,4 @@
 use super::unsupported;
-use crate::error::Error as StdError;
 use crate::ffi::{OsStr, OsString};
 use crate::marker::PhantomData;
 use crate::os::xous::ffi::Error as XousError;
@@ -110,12 +109,7 @@ impl fmt::Display for JoinPathsError {
     }
 }
 
-impl StdError for JoinPathsError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "not supported on this platform yet"
-    }
-}
+impl crate::error::Error for JoinPathsError {}
 
 pub fn current_exe() -> io::Result<PathBuf> {
     unsupported()
diff --git a/library/std/src/sys/pal/zkvm/os.rs b/library/std/src/sys/pal/zkvm/os.rs
index a8ef97ecf67..13d2a2044f4 100644
--- a/library/std/src/sys/pal/zkvm/os.rs
+++ b/library/std/src/sys/pal/zkvm/os.rs
@@ -1,5 +1,4 @@
 use super::unsupported;
-use crate::error::Error as StdError;
 use crate::ffi::{OsStr, OsString};
 use crate::marker::PhantomData;
 use crate::path::{self, PathBuf};
@@ -51,12 +50,7 @@ impl fmt::Display for JoinPathsError {
     }
 }
 
-impl StdError for JoinPathsError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "not supported on this platform yet"
-    }
-}
+impl crate::error::Error for JoinPathsError {}
 
 pub fn current_exe() -> io::Result<PathBuf> {
     unsupported()
diff --git a/library/std/src/sys_common/mod.rs b/library/std/src/sys_common/mod.rs
index 24b6cff1309..ec45c723e0d 100644
--- a/library/std/src/sys_common/mod.rs
+++ b/library/std/src/sys_common/mod.rs
@@ -21,7 +21,6 @@
 mod tests;
 
 pub mod wstr;
-pub mod wtf8;
 
 // common error constructors
 
diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs
deleted file mode 100644
index 50bde88b5a4..00000000000
--- a/library/std/src/sys_common/wtf8.rs
+++ /dev/null
@@ -1,1083 +0,0 @@
-//! Implementation of [the WTF-8 encoding](https://simonsapin.github.io/wtf-8/).
-//!
-//! This library uses Rust’s type system to maintain
-//! [well-formedness](https://simonsapin.github.io/wtf-8/#well-formed),
-//! like the `String` and `&str` types do for UTF-8.
-//!
-//! Since [WTF-8 must not be used
-//! for interchange](https://simonsapin.github.io/wtf-8/#intended-audience),
-//! this library deliberately does not provide access to the underlying bytes
-//! of WTF-8 strings,
-//! nor can it decode WTF-8 from arbitrary bytes.
-//! WTF-8 strings can be obtained from UTF-8, UTF-16, or code points.
-
-// this module is imported from @SimonSapin's repo and has tons of dead code on
-// unix (it's mostly used on windows), so don't worry about dead code here.
-#![allow(dead_code)]
-
-#[cfg(test)]
-mod tests;
-
-use core::char::{MAX_LEN_UTF8, MAX_LEN_UTF16, encode_utf8_raw, encode_utf16_raw};
-use core::clone::CloneToUninit;
-use core::str::next_code_point;
-
-use crate::borrow::Cow;
-use crate::collections::TryReserveError;
-use crate::hash::{Hash, Hasher};
-use crate::iter::FusedIterator;
-use crate::rc::Rc;
-use crate::sync::Arc;
-use crate::sys_common::AsInner;
-use crate::{fmt, mem, ops, slice, str};
-
-const UTF8_REPLACEMENT_CHARACTER: &str = "\u{FFFD}";
-
-/// A Unicode code point: from U+0000 to U+10FFFF.
-///
-/// Compares with the `char` type,
-/// which represents a Unicode scalar value:
-/// a code point that is not a surrogate (U+D800 to U+DFFF).
-#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy)]
-pub struct CodePoint {
-    value: u32,
-}
-
-/// Format the code point as `U+` followed by four to six hexadecimal digits.
-/// Example: `U+1F4A9`
-impl fmt::Debug for CodePoint {
-    #[inline]
-    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(formatter, "U+{:04X}", self.value)
-    }
-}
-
-impl CodePoint {
-    /// Unsafely creates a new `CodePoint` without checking the value.
-    ///
-    /// Only use when `value` is known to be less than or equal to 0x10FFFF.
-    #[inline]
-    pub unsafe fn from_u32_unchecked(value: u32) -> CodePoint {
-        CodePoint { value }
-    }
-
-    /// Creates a new `CodePoint` if the value is a valid code point.
-    ///
-    /// Returns `None` if `value` is above 0x10FFFF.
-    #[inline]
-    pub fn from_u32(value: u32) -> Option<CodePoint> {
-        match value {
-            0..=0x10FFFF => Some(CodePoint { value }),
-            _ => None,
-        }
-    }
-
-    /// Creates a new `CodePoint` from a `char`.
-    ///
-    /// Since all Unicode scalar values are code points, this always succeeds.
-    #[inline]
-    pub fn from_char(value: char) -> CodePoint {
-        CodePoint { value: value as u32 }
-    }
-
-    /// Returns the numeric value of the code point.
-    #[inline]
-    pub fn to_u32(&self) -> u32 {
-        self.value
-    }
-
-    /// Returns the numeric value of the code point if it is a leading surrogate.
-    #[inline]
-    pub fn to_lead_surrogate(&self) -> Option<u16> {
-        match self.value {
-            lead @ 0xD800..=0xDBFF => Some(lead as u16),
-            _ => None,
-        }
-    }
-
-    /// Returns the numeric value of the code point if it is a trailing surrogate.
-    #[inline]
-    pub fn to_trail_surrogate(&self) -> Option<u16> {
-        match self.value {
-            trail @ 0xDC00..=0xDFFF => Some(trail as u16),
-            _ => None,
-        }
-    }
-
-    /// Optionally returns a Unicode scalar value for the code point.
-    ///
-    /// Returns `None` if the code point is a surrogate (from U+D800 to U+DFFF).
-    #[inline]
-    pub fn to_char(&self) -> Option<char> {
-        match self.value {
-            0xD800..=0xDFFF => None,
-            _ => Some(unsafe { char::from_u32_unchecked(self.value) }),
-        }
-    }
-
-    /// Returns a Unicode scalar value for the code point.
-    ///
-    /// Returns `'\u{FFFD}'` (the replacement character “�”)
-    /// if the code point is a surrogate (from U+D800 to U+DFFF).
-    #[inline]
-    pub fn to_char_lossy(&self) -> char {
-        self.to_char().unwrap_or('\u{FFFD}')
-    }
-}
-
-/// An owned, growable string of well-formed WTF-8 data.
-///
-/// Similar to `String`, but can additionally contain surrogate code points
-/// if they’re not in a surrogate pair.
-#[derive(Eq, PartialEq, Ord, PartialOrd, Clone)]
-pub struct Wtf8Buf {
-    bytes: Vec<u8>,
-
-    /// Do we know that `bytes` holds a valid UTF-8 encoding? We can easily
-    /// know this if we're constructed from a `String` or `&str`.
-    ///
-    /// It is possible for `bytes` to have valid UTF-8 without this being
-    /// set, such as when we're concatenating `&Wtf8`'s and surrogates become
-    /// paired, as we don't bother to rescan the entire string.
-    is_known_utf8: bool,
-}
-
-impl ops::Deref for Wtf8Buf {
-    type Target = Wtf8;
-
-    fn deref(&self) -> &Wtf8 {
-        self.as_slice()
-    }
-}
-
-impl ops::DerefMut for Wtf8Buf {
-    fn deref_mut(&mut self) -> &mut Wtf8 {
-        self.as_mut_slice()
-    }
-}
-
-/// Formats the string in double quotes, with characters escaped according to
-/// [`char::escape_debug`] and unpaired surrogates represented as `\u{xxxx}`,
-/// where each `x` is a hexadecimal digit.
-///
-/// For example, the code units [U+0061, U+D800, U+000A] are formatted as
-/// `"a\u{D800}\n"`.
-impl fmt::Debug for Wtf8Buf {
-    #[inline]
-    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Debug::fmt(&**self, formatter)
-    }
-}
-
-/// Formats the string with unpaired surrogates substituted with the replacement
-/// character, U+FFFD.
-impl fmt::Display for Wtf8Buf {
-    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        if let Some(s) = self.as_known_utf8() {
-            fmt::Display::fmt(s, formatter)
-        } else {
-            fmt::Display::fmt(&**self, formatter)
-        }
-    }
-}
-
-impl Wtf8Buf {
-    /// Creates a new, empty WTF-8 string.
-    #[inline]
-    pub fn new() -> Wtf8Buf {
-        Wtf8Buf { bytes: Vec::new(), is_known_utf8: true }
-    }
-
-    /// Creates a new, empty WTF-8 string with pre-allocated capacity for `capacity` bytes.
-    #[inline]
-    pub fn with_capacity(capacity: usize) -> Wtf8Buf {
-        Wtf8Buf { bytes: Vec::with_capacity(capacity), is_known_utf8: true }
-    }
-
-    /// Creates a WTF-8 string from a WTF-8 byte vec.
-    ///
-    /// Since the byte vec is not checked for valid WTF-8, this function is
-    /// marked unsafe.
-    #[inline]
-    pub unsafe fn from_bytes_unchecked(value: Vec<u8>) -> Wtf8Buf {
-        Wtf8Buf { bytes: value, is_known_utf8: false }
-    }
-
-    /// Creates a WTF-8 string from a UTF-8 `String`.
-    ///
-    /// This takes ownership of the `String` and does not copy.
-    ///
-    /// Since WTF-8 is a superset of UTF-8, this always succeeds.
-    #[inline]
-    pub const fn from_string(string: String) -> Wtf8Buf {
-        Wtf8Buf { bytes: string.into_bytes(), is_known_utf8: true }
-    }
-
-    /// Creates a WTF-8 string from a UTF-8 `&str` slice.
-    ///
-    /// This copies the content of the slice.
-    ///
-    /// Since WTF-8 is a superset of UTF-8, this always succeeds.
-    #[inline]
-    pub fn from_str(s: &str) -> Wtf8Buf {
-        Wtf8Buf { bytes: s.as_bytes().to_vec(), is_known_utf8: true }
-    }
-
-    pub fn clear(&mut self) {
-        self.bytes.clear();
-        self.is_known_utf8 = true;
-    }
-
-    /// Creates a WTF-8 string from a potentially ill-formed UTF-16 slice of 16-bit code units.
-    ///
-    /// This is lossless: calling `.encode_wide()` on the resulting string
-    /// will always return the original code units.
-    pub fn from_wide(v: &[u16]) -> Wtf8Buf {
-        let mut string = Wtf8Buf::with_capacity(v.len());
-        for item in char::decode_utf16(v.iter().cloned()) {
-            match item {
-                Ok(ch) => string.push_char(ch),
-                Err(surrogate) => {
-                    let surrogate = surrogate.unpaired_surrogate();
-                    // Surrogates are known to be in the code point range.
-                    let code_point = unsafe { CodePoint::from_u32_unchecked(surrogate as u32) };
-                    // The string will now contain an unpaired surrogate.
-                    string.is_known_utf8 = false;
-                    // Skip the WTF-8 concatenation check,
-                    // surrogate pairs are already decoded by decode_utf16
-                    string.push_code_point_unchecked(code_point);
-                }
-            }
-        }
-        string
-    }
-
-    /// Appends the given `char` to the end of this string.
-    /// This does **not** include the WTF-8 concatenation check or `is_known_utf8` check.
-    /// Copied from String::push.
-    fn push_code_point_unchecked(&mut self, code_point: CodePoint) {
-        let mut bytes = [0; MAX_LEN_UTF8];
-        let bytes = encode_utf8_raw(code_point.value, &mut bytes);
-        self.bytes.extend_from_slice(bytes)
-    }
-
-    #[inline]
-    pub fn as_slice(&self) -> &Wtf8 {
-        unsafe { Wtf8::from_bytes_unchecked(&self.bytes) }
-    }
-
-    #[inline]
-    pub fn as_mut_slice(&mut self) -> &mut Wtf8 {
-        // Safety: `Wtf8` doesn't expose any way to mutate the bytes that would
-        // cause them to change from well-formed UTF-8 to ill-formed UTF-8,
-        // which would break the assumptions of the `is_known_utf8` field.
-        unsafe { Wtf8::from_mut_bytes_unchecked(&mut self.bytes) }
-    }
-
-    /// Converts the string to UTF-8 without validation, if it was created from
-    /// valid UTF-8.
-    #[inline]
-    fn as_known_utf8(&self) -> Option<&str> {
-        if self.is_known_utf8 {
-            // SAFETY: The buffer is known to be valid UTF-8.
-            Some(unsafe { str::from_utf8_unchecked(self.as_bytes()) })
-        } else {
-            None
-        }
-    }
-
-    /// Reserves capacity for at least `additional` more bytes to be inserted
-    /// in the given `Wtf8Buf`.
-    /// The collection may reserve more space to avoid frequent reallocations.
-    ///
-    /// # Panics
-    ///
-    /// Panics if the new capacity exceeds `isize::MAX` bytes.
-    #[inline]
-    pub fn reserve(&mut self, additional: usize) {
-        self.bytes.reserve(additional)
-    }
-
-    /// Tries to reserve capacity for at least `additional` more bytes to be
-    /// inserted in the given `Wtf8Buf`. The `Wtf8Buf` may reserve more space to
-    /// avoid frequent reallocations. After calling `try_reserve`, capacity will
-    /// be greater than or equal to `self.len() + additional`. Does nothing if
-    /// capacity is already sufficient. This method preserves the contents even
-    /// if an error occurs.
-    ///
-    /// # Errors
-    ///
-    /// If the capacity overflows, or the allocator reports a failure, then an error
-    /// is returned.
-    #[inline]
-    pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
-        self.bytes.try_reserve(additional)
-    }
-
-    #[inline]
-    pub fn reserve_exact(&mut self, additional: usize) {
-        self.bytes.reserve_exact(additional)
-    }
-
-    /// Tries to reserve the minimum capacity for exactly `additional` more
-    /// bytes to be inserted in the given `Wtf8Buf`. After calling
-    /// `try_reserve_exact`, capacity will be greater than or equal to
-    /// `self.len() + additional` if it returns `Ok(())`.
-    /// Does nothing if the capacity is already sufficient.
-    ///
-    /// Note that the allocator may give the `Wtf8Buf` more space than it
-    /// requests. Therefore, capacity can not be relied upon to be precisely
-    /// minimal. Prefer [`try_reserve`] if future insertions are expected.
-    ///
-    /// [`try_reserve`]: Wtf8Buf::try_reserve
-    ///
-    /// # Errors
-    ///
-    /// If the capacity overflows, or the allocator reports a failure, then an error
-    /// is returned.
-    #[inline]
-    pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
-        self.bytes.try_reserve_exact(additional)
-    }
-
-    #[inline]
-    pub fn shrink_to_fit(&mut self) {
-        self.bytes.shrink_to_fit()
-    }
-
-    #[inline]
-    pub fn shrink_to(&mut self, min_capacity: usize) {
-        self.bytes.shrink_to(min_capacity)
-    }
-
-    #[inline]
-    pub fn leak<'a>(self) -> &'a mut Wtf8 {
-        unsafe { Wtf8::from_mut_bytes_unchecked(self.bytes.leak()) }
-    }
-
-    /// Returns the number of bytes that this string buffer can hold without reallocating.
-    #[inline]
-    pub fn capacity(&self) -> usize {
-        self.bytes.capacity()
-    }
-
-    /// Append a UTF-8 slice at the end of the string.
-    #[inline]
-    pub fn push_str(&mut self, other: &str) {
-        self.bytes.extend_from_slice(other.as_bytes())
-    }
-
-    /// Append a WTF-8 slice at the end of the string.
-    ///
-    /// This replaces newly paired surrogates at the boundary
-    /// with a supplementary code point,
-    /// like concatenating ill-formed UTF-16 strings effectively would.
-    #[inline]
-    pub fn push_wtf8(&mut self, other: &Wtf8) {
-        match ((&*self).final_lead_surrogate(), other.initial_trail_surrogate()) {
-            // Replace newly paired surrogates by a supplementary code point.
-            (Some(lead), Some(trail)) => {
-                let len_without_lead_surrogate = self.len() - 3;
-                self.bytes.truncate(len_without_lead_surrogate);
-                let other_without_trail_surrogate = &other.bytes[3..];
-                // 4 bytes for the supplementary code point
-                self.bytes.reserve(4 + other_without_trail_surrogate.len());
-                self.push_char(decode_surrogate_pair(lead, trail));
-                self.bytes.extend_from_slice(other_without_trail_surrogate);
-            }
-            _ => {
-                // If we'll be pushing a string containing a surrogate, we may
-                // no longer have UTF-8.
-                if self.is_known_utf8 && other.next_surrogate(0).is_some() {
-                    self.is_known_utf8 = false;
-                }
-
-                self.bytes.extend_from_slice(&other.bytes);
-            }
-        }
-    }
-
-    /// Append a Unicode scalar value at the end of the string.
-    #[inline]
-    pub fn push_char(&mut self, c: char) {
-        self.push_code_point_unchecked(CodePoint::from_char(c))
-    }
-
-    /// Append a code point at the end of the string.
-    ///
-    /// This replaces newly paired surrogates at the boundary
-    /// with a supplementary code point,
-    /// like concatenating ill-formed UTF-16 strings effectively would.
-    #[inline]
-    pub fn push(&mut self, code_point: CodePoint) {
-        if let Some(trail) = code_point.to_trail_surrogate() {
-            if let Some(lead) = (&*self).final_lead_surrogate() {
-                let len_without_lead_surrogate = self.len() - 3;
-                self.bytes.truncate(len_without_lead_surrogate);
-                self.push_char(decode_surrogate_pair(lead, trail));
-                return;
-            }
-
-            // We're pushing a trailing surrogate.
-            self.is_known_utf8 = false;
-        } else if code_point.to_lead_surrogate().is_some() {
-            // We're pushing a leading surrogate.
-            self.is_known_utf8 = false;
-        }
-
-        // No newly paired surrogates at the boundary.
-        self.push_code_point_unchecked(code_point)
-    }
-
-    /// Shortens a string to the specified length.
-    ///
-    /// # Panics
-    ///
-    /// Panics if `new_len` > current length,
-    /// or if `new_len` is not a code point boundary.
-    #[inline]
-    pub fn truncate(&mut self, new_len: usize) {
-        assert!(is_code_point_boundary(self, new_len));
-        self.bytes.truncate(new_len)
-    }
-
-    /// Consumes the WTF-8 string and tries to convert it to a vec of bytes.
-    #[inline]
-    pub fn into_bytes(self) -> Vec<u8> {
-        self.bytes
-    }
-
-    /// Consumes the WTF-8 string and tries to convert it to UTF-8.
-    ///
-    /// This does not copy the data.
-    ///
-    /// If the contents are not well-formed UTF-8
-    /// (that is, if the string contains surrogates),
-    /// the original WTF-8 string is returned instead.
-    pub fn into_string(self) -> Result<String, Wtf8Buf> {
-        if self.is_known_utf8 || self.next_surrogate(0).is_none() {
-            Ok(unsafe { String::from_utf8_unchecked(self.bytes) })
-        } else {
-            Err(self)
-        }
-    }
-
-    /// Consumes the WTF-8 string and converts it lossily to UTF-8.
-    ///
-    /// This does not copy the data (but may overwrite parts of it in place).
-    ///
-    /// Surrogates are replaced with `"\u{FFFD}"` (the replacement character “�”)
-    pub fn into_string_lossy(mut self) -> String {
-        if !self.is_known_utf8 {
-            let mut pos = 0;
-            while let Some((surrogate_pos, _)) = self.next_surrogate(pos) {
-                pos = surrogate_pos + 3;
-                // Surrogates and the replacement character are all 3 bytes, so
-                // they can substituted in-place.
-                self.bytes[surrogate_pos..pos]
-                    .copy_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes());
-            }
-        }
-        unsafe { String::from_utf8_unchecked(self.bytes) }
-    }
-
-    /// Converts this `Wtf8Buf` into a boxed `Wtf8`.
-    #[inline]
-    pub fn into_box(self) -> Box<Wtf8> {
-        // SAFETY: relies on `Wtf8` being `repr(transparent)`.
-        unsafe { mem::transmute(self.bytes.into_boxed_slice()) }
-    }
-
-    /// Converts a `Box<Wtf8>` into a `Wtf8Buf`.
-    pub fn from_box(boxed: Box<Wtf8>) -> Wtf8Buf {
-        let bytes: Box<[u8]> = unsafe { mem::transmute(boxed) };
-        Wtf8Buf { bytes: bytes.into_vec(), is_known_utf8: false }
-    }
-
-    /// Provides plumbing to core `Vec::extend_from_slice`.
-    /// More well behaving alternative to allowing outer types
-    /// full mutable access to the core `Vec`.
-    #[inline]
-    pub(crate) fn extend_from_slice(&mut self, other: &[u8]) {
-        self.bytes.extend_from_slice(other);
-        self.is_known_utf8 = false;
-    }
-}
-
-/// Creates a new WTF-8 string from an iterator of code points.
-///
-/// This replaces surrogate code point pairs with supplementary code points,
-/// like concatenating ill-formed UTF-16 strings effectively would.
-impl FromIterator<CodePoint> for Wtf8Buf {
-    fn from_iter<T: IntoIterator<Item = CodePoint>>(iter: T) -> Wtf8Buf {
-        let mut string = Wtf8Buf::new();
-        string.extend(iter);
-        string
-    }
-}
-
-/// Append code points from an iterator to the string.
-///
-/// This replaces surrogate code point pairs with supplementary code points,
-/// like concatenating ill-formed UTF-16 strings effectively would.
-impl Extend<CodePoint> for Wtf8Buf {
-    fn extend<T: IntoIterator<Item = CodePoint>>(&mut self, iter: T) {
-        let iterator = iter.into_iter();
-        let (low, _high) = iterator.size_hint();
-        // Lower bound of one byte per code point (ASCII only)
-        self.bytes.reserve(low);
-        iterator.for_each(move |code_point| self.push(code_point));
-    }
-
-    #[inline]
-    fn extend_one(&mut self, code_point: CodePoint) {
-        self.push(code_point);
-    }
-
-    #[inline]
-    fn extend_reserve(&mut self, additional: usize) {
-        // Lower bound of one byte per code point (ASCII only)
-        self.bytes.reserve(additional);
-    }
-}
-
-/// A borrowed slice of well-formed WTF-8 data.
-///
-/// Similar to `&str`, but can additionally contain surrogate code points
-/// if they’re not in a surrogate pair.
-#[derive(Eq, Ord, PartialEq, PartialOrd)]
-#[repr(transparent)]
-pub struct Wtf8 {
-    bytes: [u8],
-}
-
-impl AsInner<[u8]> for Wtf8 {
-    #[inline]
-    fn as_inner(&self) -> &[u8] {
-        &self.bytes
-    }
-}
-
-/// Formats the string in double quotes, with characters escaped according to
-/// [`char::escape_debug`] and unpaired surrogates represented as `\u{xxxx}`,
-/// where each `x` is a hexadecimal digit.
-impl fmt::Debug for Wtf8 {
-    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fn write_str_escaped(f: &mut fmt::Formatter<'_>, s: &str) -> fmt::Result {
-            use crate::fmt::Write;
-            for c in s.chars().flat_map(|c| c.escape_debug()) {
-                f.write_char(c)?
-            }
-            Ok(())
-        }
-
-        formatter.write_str("\"")?;
-        let mut pos = 0;
-        while let Some((surrogate_pos, surrogate)) = self.next_surrogate(pos) {
-            write_str_escaped(formatter, unsafe {
-                str::from_utf8_unchecked(&self.bytes[pos..surrogate_pos])
-            })?;
-            write!(formatter, "\\u{{{:x}}}", surrogate)?;
-            pos = surrogate_pos + 3;
-        }
-        write_str_escaped(formatter, unsafe { str::from_utf8_unchecked(&self.bytes[pos..]) })?;
-        formatter.write_str("\"")
-    }
-}
-
-/// Formats the string with unpaired surrogates substituted with the replacement
-/// character, U+FFFD.
-impl fmt::Display for Wtf8 {
-    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let wtf8_bytes = &self.bytes;
-        let mut pos = 0;
-        loop {
-            match self.next_surrogate(pos) {
-                Some((surrogate_pos, _)) => {
-                    formatter.write_str(unsafe {
-                        str::from_utf8_unchecked(&wtf8_bytes[pos..surrogate_pos])
-                    })?;
-                    formatter.write_str(UTF8_REPLACEMENT_CHARACTER)?;
-                    pos = surrogate_pos + 3;
-                }
-                None => {
-                    let s = unsafe { str::from_utf8_unchecked(&wtf8_bytes[pos..]) };
-                    if pos == 0 { return s.fmt(formatter) } else { return formatter.write_str(s) }
-                }
-            }
-        }
-    }
-}
-
-impl Wtf8 {
-    /// Creates a WTF-8 slice from a UTF-8 `&str` slice.
-    ///
-    /// Since WTF-8 is a superset of UTF-8, this always succeeds.
-    #[inline]
-    pub fn from_str(value: &str) -> &Wtf8 {
-        unsafe { Wtf8::from_bytes_unchecked(value.as_bytes()) }
-    }
-
-    /// Creates a WTF-8 slice from a WTF-8 byte slice.
-    ///
-    /// Since the byte slice is not checked for valid WTF-8, this functions is
-    /// marked unsafe.
-    #[inline]
-    pub unsafe fn from_bytes_unchecked(value: &[u8]) -> &Wtf8 {
-        // SAFETY: start with &[u8], end with fancy &[u8]
-        unsafe { &*(value as *const [u8] as *const Wtf8) }
-    }
-
-    /// Creates a mutable WTF-8 slice from a mutable WTF-8 byte slice.
-    ///
-    /// Since the byte slice is not checked for valid WTF-8, this functions is
-    /// marked unsafe.
-    #[inline]
-    unsafe fn from_mut_bytes_unchecked(value: &mut [u8]) -> &mut Wtf8 {
-        // SAFETY: start with &mut [u8], end with fancy &mut [u8]
-        unsafe { &mut *(value as *mut [u8] as *mut Wtf8) }
-    }
-
-    /// Returns the length, in WTF-8 bytes.
-    #[inline]
-    pub fn len(&self) -> usize {
-        self.bytes.len()
-    }
-
-    #[inline]
-    pub fn is_empty(&self) -> bool {
-        self.bytes.is_empty()
-    }
-
-    /// Returns the code point at `position` if it is in the ASCII range,
-    /// or `b'\xFF'` otherwise.
-    ///
-    /// # Panics
-    ///
-    /// Panics if `position` is beyond the end of the string.
-    #[inline]
-    pub fn ascii_byte_at(&self, position: usize) -> u8 {
-        match self.bytes[position] {
-            ascii_byte @ 0x00..=0x7F => ascii_byte,
-            _ => 0xFF,
-        }
-    }
-
-    /// Returns an iterator for the string’s code points.
-    #[inline]
-    pub fn code_points(&self) -> Wtf8CodePoints<'_> {
-        Wtf8CodePoints { bytes: self.bytes.iter() }
-    }
-
-    /// Access raw bytes of WTF-8 data
-    #[inline]
-    pub fn as_bytes(&self) -> &[u8] {
-        &self.bytes
-    }
-
-    /// Tries to convert the string to UTF-8 and return a `&str` slice.
-    ///
-    /// Returns `None` if the string contains surrogates.
-    ///
-    /// This does not copy the data.
-    #[inline]
-    pub fn as_str(&self) -> Result<&str, str::Utf8Error> {
-        str::from_utf8(&self.bytes)
-    }
-
-    /// Creates an owned `Wtf8Buf` from a borrowed `Wtf8`.
-    pub fn to_owned(&self) -> Wtf8Buf {
-        Wtf8Buf { bytes: self.bytes.to_vec(), is_known_utf8: false }
-    }
-
-    /// Lossily converts the string to UTF-8.
-    /// Returns a UTF-8 `&str` slice if the contents are well-formed in UTF-8.
-    ///
-    /// Surrogates are replaced with `"\u{FFFD}"` (the replacement character “�”).
-    ///
-    /// This only copies the data if necessary (if it contains any surrogate).
-    pub fn to_string_lossy(&self) -> Cow<'_, str> {
-        let Some((surrogate_pos, _)) = self.next_surrogate(0) else {
-            return Cow::Borrowed(unsafe { str::from_utf8_unchecked(&self.bytes) });
-        };
-        let wtf8_bytes = &self.bytes;
-        let mut utf8_bytes = Vec::with_capacity(self.len());
-        utf8_bytes.extend_from_slice(&wtf8_bytes[..surrogate_pos]);
-        utf8_bytes.extend_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes());
-        let mut pos = surrogate_pos + 3;
-        loop {
-            match self.next_surrogate(pos) {
-                Some((surrogate_pos, _)) => {
-                    utf8_bytes.extend_from_slice(&wtf8_bytes[pos..surrogate_pos]);
-                    utf8_bytes.extend_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes());
-                    pos = surrogate_pos + 3;
-                }
-                None => {
-                    utf8_bytes.extend_from_slice(&wtf8_bytes[pos..]);
-                    return Cow::Owned(unsafe { String::from_utf8_unchecked(utf8_bytes) });
-                }
-            }
-        }
-    }
-
-    /// Converts the WTF-8 string to potentially ill-formed UTF-16
-    /// and return an iterator of 16-bit code units.
-    ///
-    /// This is lossless:
-    /// calling `Wtf8Buf::from_ill_formed_utf16` on the resulting code units
-    /// would always return the original WTF-8 string.
-    #[inline]
-    pub fn encode_wide(&self) -> EncodeWide<'_> {
-        EncodeWide { code_points: self.code_points(), extra: 0 }
-    }
-
-    #[inline]
-    fn next_surrogate(&self, mut pos: usize) -> Option<(usize, u16)> {
-        let mut iter = self.bytes[pos..].iter();
-        loop {
-            let b = *iter.next()?;
-            if b < 0x80 {
-                pos += 1;
-            } else if b < 0xE0 {
-                iter.next();
-                pos += 2;
-            } else if b == 0xED {
-                match (iter.next(), iter.next()) {
-                    (Some(&b2), Some(&b3)) if b2 >= 0xA0 => {
-                        return Some((pos, decode_surrogate(b2, b3)));
-                    }
-                    _ => pos += 3,
-                }
-            } else if b < 0xF0 {
-                iter.next();
-                iter.next();
-                pos += 3;
-            } else {
-                iter.next();
-                iter.next();
-                iter.next();
-                pos += 4;
-            }
-        }
-    }
-
-    #[inline]
-    fn final_lead_surrogate(&self) -> Option<u16> {
-        match self.bytes {
-            [.., 0xED, b2 @ 0xA0..=0xAF, b3] => Some(decode_surrogate(b2, b3)),
-            _ => None,
-        }
-    }
-
-    #[inline]
-    fn initial_trail_surrogate(&self) -> Option<u16> {
-        match self.bytes {
-            [0xED, b2 @ 0xB0..=0xBF, b3, ..] => Some(decode_surrogate(b2, b3)),
-            _ => None,
-        }
-    }
-
-    pub fn clone_into(&self, buf: &mut Wtf8Buf) {
-        buf.is_known_utf8 = false;
-        self.bytes.clone_into(&mut buf.bytes);
-    }
-
-    /// Boxes this `Wtf8`.
-    #[inline]
-    pub fn into_box(&self) -> Box<Wtf8> {
-        let boxed: Box<[u8]> = self.bytes.into();
-        unsafe { mem::transmute(boxed) }
-    }
-
-    /// Creates a boxed, empty `Wtf8`.
-    pub fn empty_box() -> Box<Wtf8> {
-        let boxed: Box<[u8]> = Default::default();
-        unsafe { mem::transmute(boxed) }
-    }
-
-    #[inline]
-    pub fn into_arc(&self) -> Arc<Wtf8> {
-        let arc: Arc<[u8]> = Arc::from(&self.bytes);
-        unsafe { Arc::from_raw(Arc::into_raw(arc) as *const Wtf8) }
-    }
-
-    #[inline]
-    pub fn into_rc(&self) -> Rc<Wtf8> {
-        let rc: Rc<[u8]> = Rc::from(&self.bytes);
-        unsafe { Rc::from_raw(Rc::into_raw(rc) as *const Wtf8) }
-    }
-
-    #[inline]
-    pub fn make_ascii_lowercase(&mut self) {
-        self.bytes.make_ascii_lowercase()
-    }
-
-    #[inline]
-    pub fn make_ascii_uppercase(&mut self) {
-        self.bytes.make_ascii_uppercase()
-    }
-
-    #[inline]
-    pub fn to_ascii_lowercase(&self) -> Wtf8Buf {
-        Wtf8Buf { bytes: self.bytes.to_ascii_lowercase(), is_known_utf8: false }
-    }
-
-    #[inline]
-    pub fn to_ascii_uppercase(&self) -> Wtf8Buf {
-        Wtf8Buf { bytes: self.bytes.to_ascii_uppercase(), is_known_utf8: false }
-    }
-
-    #[inline]
-    pub fn is_ascii(&self) -> bool {
-        self.bytes.is_ascii()
-    }
-
-    #[inline]
-    pub fn eq_ignore_ascii_case(&self, other: &Self) -> bool {
-        self.bytes.eq_ignore_ascii_case(&other.bytes)
-    }
-}
-
-/// Returns a slice of the given string for the byte range \[`begin`..`end`).
-///
-/// # Panics
-///
-/// Panics when `begin` and `end` do not point to code point boundaries,
-/// or point beyond the end of the string.
-impl ops::Index<ops::Range<usize>> for Wtf8 {
-    type Output = Wtf8;
-
-    #[inline]
-    fn index(&self, range: ops::Range<usize>) -> &Wtf8 {
-        // is_code_point_boundary checks that the index is in [0, .len()]
-        if range.start <= range.end
-            && is_code_point_boundary(self, range.start)
-            && is_code_point_boundary(self, range.end)
-        {
-            unsafe { slice_unchecked(self, range.start, range.end) }
-        } else {
-            slice_error_fail(self, range.start, range.end)
-        }
-    }
-}
-
-/// Returns a slice of the given string from byte `begin` to its end.
-///
-/// # Panics
-///
-/// Panics when `begin` is not at a code point boundary,
-/// or is beyond the end of the string.
-impl ops::Index<ops::RangeFrom<usize>> for Wtf8 {
-    type Output = Wtf8;
-
-    #[inline]
-    fn index(&self, range: ops::RangeFrom<usize>) -> &Wtf8 {
-        // is_code_point_boundary checks that the index is in [0, .len()]
-        if is_code_point_boundary(self, range.start) {
-            unsafe { slice_unchecked(self, range.start, self.len()) }
-        } else {
-            slice_error_fail(self, range.start, self.len())
-        }
-    }
-}
-
-/// Returns a slice of the given string from its beginning to byte `end`.
-///
-/// # Panics
-///
-/// Panics when `end` is not at a code point boundary,
-/// or is beyond the end of the string.
-impl ops::Index<ops::RangeTo<usize>> for Wtf8 {
-    type Output = Wtf8;
-
-    #[inline]
-    fn index(&self, range: ops::RangeTo<usize>) -> &Wtf8 {
-        // is_code_point_boundary checks that the index is in [0, .len()]
-        if is_code_point_boundary(self, range.end) {
-            unsafe { slice_unchecked(self, 0, range.end) }
-        } else {
-            slice_error_fail(self, 0, range.end)
-        }
-    }
-}
-
-impl ops::Index<ops::RangeFull> for Wtf8 {
-    type Output = Wtf8;
-
-    #[inline]
-    fn index(&self, _range: ops::RangeFull) -> &Wtf8 {
-        self
-    }
-}
-
-#[inline]
-fn decode_surrogate(second_byte: u8, third_byte: u8) -> u16 {
-    // The first byte is assumed to be 0xED
-    0xD800 | (second_byte as u16 & 0x3F) << 6 | third_byte as u16 & 0x3F
-}
-
-#[inline]
-fn decode_surrogate_pair(lead: u16, trail: u16) -> char {
-    let code_point = 0x10000 + ((((lead - 0xD800) as u32) << 10) | (trail - 0xDC00) as u32);
-    unsafe { char::from_u32_unchecked(code_point) }
-}
-
-/// Copied from str::is_char_boundary
-#[inline]
-pub fn is_code_point_boundary(slice: &Wtf8, index: usize) -> bool {
-    if index == 0 {
-        return true;
-    }
-    match slice.bytes.get(index) {
-        None => index == slice.len(),
-        Some(&b) => (b as i8) >= -0x40,
-    }
-}
-
-/// Verify that `index` is at the edge of either a valid UTF-8 codepoint
-/// (i.e. a codepoint that's not a surrogate) or of the whole string.
-///
-/// These are the cases currently permitted by `OsStr::slice_encoded_bytes`.
-/// Splitting between surrogates is valid as far as WTF-8 is concerned, but
-/// we do not permit it in the public API because WTF-8 is considered an
-/// implementation detail.
-#[track_caller]
-#[inline]
-pub fn check_utf8_boundary(slice: &Wtf8, index: usize) {
-    if index == 0 {
-        return;
-    }
-    match slice.bytes.get(index) {
-        Some(0xED) => (), // Might be a surrogate
-        Some(&b) if (b as i8) >= -0x40 => return,
-        Some(_) => panic!("byte index {index} is not a codepoint boundary"),
-        None if index == slice.len() => return,
-        None => panic!("byte index {index} is out of bounds"),
-    }
-    if slice.bytes[index + 1] >= 0xA0 {
-        // There's a surrogate after index. Now check before index.
-        if index >= 3 && slice.bytes[index - 3] == 0xED && slice.bytes[index - 2] >= 0xA0 {
-            panic!("byte index {index} lies between surrogate codepoints");
-        }
-    }
-}
-
-/// Copied from core::str::raw::slice_unchecked
-#[inline]
-pub unsafe fn slice_unchecked(s: &Wtf8, begin: usize, end: usize) -> &Wtf8 {
-    // SAFETY: memory layout of a &[u8] and &Wtf8 are the same
-    unsafe {
-        let len = end - begin;
-        let start = s.as_bytes().as_ptr().add(begin);
-        Wtf8::from_bytes_unchecked(slice::from_raw_parts(start, len))
-    }
-}
-
-/// Copied from core::str::raw::slice_error_fail
-#[inline(never)]
-pub fn slice_error_fail(s: &Wtf8, begin: usize, end: usize) -> ! {
-    assert!(begin <= end);
-    panic!("index {begin} and/or {end} in `{s:?}` do not lie on character boundary");
-}
-
-/// Iterator for the code points of a WTF-8 string.
-///
-/// Created with the method `.code_points()`.
-#[derive(Clone)]
-pub struct Wtf8CodePoints<'a> {
-    bytes: slice::Iter<'a, u8>,
-}
-
-impl Iterator for Wtf8CodePoints<'_> {
-    type Item = CodePoint;
-
-    #[inline]
-    fn next(&mut self) -> Option<CodePoint> {
-        // SAFETY: `self.bytes` has been created from a WTF-8 string
-        unsafe { next_code_point(&mut self.bytes).map(|c| CodePoint { value: c }) }
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let len = self.bytes.len();
-        (len.saturating_add(3) / 4, Some(len))
-    }
-}
-
-/// Generates a wide character sequence for potentially ill-formed UTF-16.
-#[stable(feature = "rust1", since = "1.0.0")]
-#[derive(Clone)]
-pub struct EncodeWide<'a> {
-    code_points: Wtf8CodePoints<'a>,
-    extra: u16,
-}
-
-// Copied from libunicode/u_str.rs
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Iterator for EncodeWide<'_> {
-    type Item = u16;
-
-    #[inline]
-    fn next(&mut self) -> Option<u16> {
-        if self.extra != 0 {
-            let tmp = self.extra;
-            self.extra = 0;
-            return Some(tmp);
-        }
-
-        let mut buf = [0; MAX_LEN_UTF16];
-        self.code_points.next().map(|code_point| {
-            let n = encode_utf16_raw(code_point.value, &mut buf).len();
-            if n == 2 {
-                self.extra = buf[1];
-            }
-            buf[0]
-        })
-    }
-
-    #[inline]
-    fn size_hint(&self) -> (usize, Option<usize>) {
-        let (low, high) = self.code_points.size_hint();
-        let ext = (self.extra != 0) as usize;
-        // every code point gets either one u16 or two u16,
-        // so this iterator is between 1 or 2 times as
-        // long as the underlying iterator.
-        (low + ext, high.and_then(|n| n.checked_mul(2)).and_then(|n| n.checked_add(ext)))
-    }
-}
-
-#[stable(feature = "encode_wide_fused_iterator", since = "1.62.0")]
-impl FusedIterator for EncodeWide<'_> {}
-
-impl Hash for CodePoint {
-    #[inline]
-    fn hash<H: Hasher>(&self, state: &mut H) {
-        self.value.hash(state)
-    }
-}
-
-impl Hash for Wtf8Buf {
-    #[inline]
-    fn hash<H: Hasher>(&self, state: &mut H) {
-        state.write(&self.bytes);
-        0xfeu8.hash(state)
-    }
-}
-
-impl Hash for Wtf8 {
-    #[inline]
-    fn hash<H: Hasher>(&self, state: &mut H) {
-        state.write(&self.bytes);
-        0xfeu8.hash(state)
-    }
-}
-
-#[unstable(feature = "clone_to_uninit", issue = "126799")]
-unsafe impl CloneToUninit for Wtf8 {
-    #[inline]
-    #[cfg_attr(debug_assertions, track_caller)]
-    unsafe fn clone_to_uninit(&self, dst: *mut u8) {
-        // SAFETY: we're just a transparent wrapper around [u8]
-        unsafe { self.bytes.clone_to_uninit(dst) }
-    }
-}
diff --git a/library/std/src/time.rs b/library/std/src/time.rs
index 07bb41f1496..84fbb4c2fe4 100644
--- a/library/std/src/time.rs
+++ b/library/std/src/time.rs
@@ -717,12 +717,7 @@ impl SystemTimeError {
 }
 
 #[stable(feature = "time2", since = "1.8.0")]
-impl Error for SystemTimeError {
-    #[allow(deprecated)]
-    fn description(&self) -> &str {
-        "other time was not earlier than self"
-    }
-}
+impl Error for SystemTimeError {}
 
 #[stable(feature = "time2", since = "1.8.0")]
 impl fmt::Display for SystemTimeError {
diff --git a/library/std/tests/sync/lazy_lock.rs b/library/std/tests/sync/lazy_lock.rs
index 6c14b79f2ce..68aeea834b4 100644
--- a/library/std/tests/sync/lazy_lock.rs
+++ b/library/std/tests/sync/lazy_lock.rs
@@ -34,16 +34,6 @@ fn lazy_default() {
 }
 
 #[test]
-#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
-fn lazy_poisoning() {
-    let x: LazyCell<String> = LazyCell::new(|| panic!("kaboom"));
-    for _ in 0..2 {
-        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| x.len()));
-        assert!(res.is_err());
-    }
-}
-
-#[test]
 #[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads
 fn sync_lazy_new() {
     static CALLED: AtomicUsize = AtomicUsize::new(0);
@@ -123,16 +113,6 @@ fn static_sync_lazy_via_fn() {
     assert_eq!(xs(), &vec![1, 2, 3]);
 }
 
-#[test]
-#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
-fn sync_lazy_poisoning() {
-    let x: LazyLock<String> = LazyLock::new(|| panic!("kaboom"));
-    for _ in 0..2 {
-        let res = panic::catch_unwind(|| x.len());
-        assert!(res.is_err());
-    }
-}
-
 // Check that we can infer `T` from closure's type.
 #[test]
 fn lazy_type_inference() {
@@ -146,17 +126,6 @@ fn is_sync_send() {
 }
 
 #[test]
-#[should_panic = "has previously been poisoned"]
-fn lazy_force_mut_panic() {
-    let mut lazy = LazyLock::<String>::new(|| panic!());
-    panic::catch_unwind(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);
@@ -165,3 +134,56 @@ fn lazy_force_mut() {
     p.clear();
     LazyLock::force_mut(&mut lazy);
 }
+
+#[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
+fn lazy_poisoning() {
+    let x: LazyCell<String> = LazyCell::new(|| panic!("kaboom"));
+    for _ in 0..2 {
+        let res = panic::catch_unwind(panic::AssertUnwindSafe(|| x.len()));
+        assert!(res.is_err());
+    }
+}
+
+/// Verifies that when a `LazyLock` is poisoned, it panics with the correct error message ("LazyLock
+/// instance has previously been poisoned") instead of the underlying `Once` error message.
+#[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
+#[should_panic(expected = "LazyLock instance has previously been poisoned")]
+fn lazy_lock_deref_panic() {
+    let lazy: LazyLock<String> = LazyLock::new(|| panic!("initialization failed"));
+
+    // First access will panic during initialization.
+    let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| {
+        let _ = &*lazy;
+    }));
+
+    // Second access should panic with the poisoned message.
+    let _ = &*lazy;
+}
+
+#[test]
+#[should_panic(expected = "LazyLock instance has previously been poisoned")]
+fn lazy_lock_deref_mut_panic() {
+    let mut lazy: LazyLock<String> = LazyLock::new(|| panic!("initialization failed"));
+
+    // First access will panic during initialization.
+    let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| {
+        let _ = LazyLock::force_mut(&mut lazy);
+    }));
+
+    // Second access should panic with the poisoned message.
+    let _ = &*lazy;
+}
+
+/// Verifies that when the initialization closure panics with a custom message, that message is
+/// preserved and not overridden by `LazyLock`.
+#[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
+#[should_panic(expected = "custom panic message from closure")]
+fn lazy_lock_preserves_closure_panic_message() {
+    let lazy: LazyLock<String> = LazyLock::new(|| panic!("custom panic message from closure"));
+
+    // This should panic with the original message from the closure.
+    let _ = &*lazy;
+}
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index 40e08361a0f..2ece53eb0cc 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -312,6 +312,12 @@ def default_build_triple(verbose):
 
     kernel, cputype, processor = uname.decode(default_encoding).split(maxsplit=2)
 
+    # ON NetBSD, use `uname -p` to set the CPU type
+    if kernel == "NetBSD":
+        cputype = (
+            subprocess.check_output(["uname", "-p"]).strip().decode(default_encoding)
+        )
+
     # The goal here is to come up with the same triple as LLVM would,
     # at least for the subset of platforms we're willing to target.
     kerneltype_mapper = {
@@ -433,10 +439,16 @@ def default_build_triple(verbose):
             kernel = "linux-androideabi"
         else:
             kernel += "eabihf"
-    elif cputype in {"armv7l", "armv8l"}:
+    elif cputype in {"armv6hf", "earmv6hf"}:
+        cputype = "armv6"
+        if kernel == "unknown-netbsd":
+            kernel += "-eabihf"
+    elif cputype in {"armv7l", "earmv7hf", "armv8l"}:
         cputype = "armv7"
         if kernel == "linux-android":
             kernel = "linux-androideabi"
+        elif kernel == "unknown-netbsd":
+            kernel += "-eabihf"
         else:
             kernel += "eabihf"
     elif cputype == "mips":
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 6ca32aca345..d30005c8d51 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -26,7 +26,9 @@ use crate::core::builder;
 use crate::core::builder::{
     Builder, Cargo, Kind, RunConfig, ShouldRun, Step, StepMetadata, crate_description,
 };
-use crate::core::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection};
+use crate::core::config::{
+    CompilerBuiltins, DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection,
+};
 use crate::utils::build_stamp;
 use crate::utils::build_stamp::BuildStamp;
 use crate::utils::exec::command;
@@ -96,10 +98,36 @@ impl Std {
         }
         deps
     }
+
+    /// Returns true if the standard library will be uplifted from stage 1 for the given
+    /// `build_compiler` (which determines the stdlib stage) and `target`.
+    ///
+    /// Uplifting is enabled if we're building a stage2+ libstd, full bootstrap is
+    /// disabled and we have a stage1 libstd already compiled for the given target.
+    pub fn should_be_uplifted_from_stage_1(
+        builder: &Builder<'_>,
+        stage: u32,
+        target: TargetSelection,
+    ) -> bool {
+        stage > 1
+            && !builder.config.full_bootstrap
+            // This estimates if a stage1 libstd exists for the given target. If we're not
+            // cross-compiling, it should definitely exist by the time we're building a stage2
+            // libstd.
+            // Or if we are cross-compiling, and we are building a cross-compiled rustc, then that
+            // rustc needs to link to a cross-compiled libstd, so again we should have a stage1
+            // libstd for the given target prepared.
+            // Even if we guess wrong in the cross-compiled case, the worst that should happen is
+            // that we build a fresh stage1 libstd below, and then we immediately uplift it, so we
+            // don't pay the libstd build cost twice.
+            && (target == builder.host_target || builder.config.hosts.contains(&target))
+    }
 }
 
 impl Step for Std {
-    type Output = ();
+    /// Build stamp of std, if it was indeed built or uplifted.
+    type Output = Option<BuildStamp>;
+
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -136,15 +164,20 @@ impl Step for Std {
     /// This will build the standard library for a particular stage of the build
     /// using the `compiler` targeting the `target` architecture. The artifacts
     /// created will also be linked into the sysroot directory.
-    fn run(self, builder: &Builder<'_>) {
+    fn run(self, builder: &Builder<'_>) -> Self::Output {
         let target = self.target;
 
-        // We already have std ready to be used for stage 0.
-        if self.build_compiler.stage == 0 {
+        // In most cases, we already have the std ready to be used for stage 0.
+        // However, if we are doing a local rebuild (so the build compiler can compile the standard
+        // library even on stage 0), and we're cross-compiling (so the stage0 standard library for
+        // *target* is not available), we still allow the stdlib to be built here.
+        if self.build_compiler.stage == 0
+            && !(builder.local_rebuild && target != builder.host_target)
+        {
             let compiler = self.build_compiler;
             builder.ensure(StdLink::from_std(self, compiler));
 
-            return;
+            return None;
         }
 
         let build_compiler = if builder.download_rustc() && self.force_recompile {
@@ -169,7 +202,7 @@ impl Step for Std {
                 &sysroot,
                 builder.config.ci_rust_std_contents(),
             );
-            return;
+            return None;
         }
 
         if builder.config.keep_stage.contains(&build_compiler.stage)
@@ -185,7 +218,7 @@ impl Step for Std {
             self.copy_extra_objects(builder, &build_compiler, target);
 
             builder.ensure(StdLink::from_std(self, build_compiler));
-            return;
+            return Some(build_stamp::libstd_stamp(builder, build_compiler, target));
         }
 
         let mut target_deps = builder.ensure(StartupObjects { compiler: build_compiler, target });
@@ -193,24 +226,9 @@ impl Step for Std {
         // Stage of the stdlib that we're building
         let stage = build_compiler.stage;
 
-        // If we're building a stage2+ libstd, full bootstrap is
-        // disabled and we have a stage1 libstd already compiled for the given target,
-        // then simply uplift a previously built stage1 library.
-        if build_compiler.stage > 1
-            && !builder.config.full_bootstrap
-            // This estimates if a stage1 libstd exists for the given target. If we're not
-            // cross-compiling, it should definitely exist by the time we're building a stage2
-            // libstd.
-            // Or if we are cross-compiling, and we are building a cross-compiled rustc, then that
-            // rustc needs to link to a cross-compiled libstd, so again we should have a stage1
-            // libstd for the given target prepared.
-            // Even if we guess wrong in the cross-compiled case, the worst that should happen is
-            // that we build a fresh stage1 libstd below, and then we immediately uplift it, so we
-            // don't pay the libstd build cost twice.
-            && (target == builder.host_target || builder.config.hosts.contains(&target))
-        {
+        if Self::should_be_uplifted_from_stage_1(builder, build_compiler.stage, target) {
             let build_compiler_for_std_to_uplift = builder.compiler(1, builder.host_target);
-            builder.std(build_compiler_for_std_to_uplift, target);
+            let stage_1_stamp = builder.std(build_compiler_for_std_to_uplift, target);
 
             let msg = if build_compiler_for_std_to_uplift.host == target {
                 format!(
@@ -231,7 +249,7 @@ impl Step for Std {
             self.copy_extra_objects(builder, &build_compiler, target);
 
             builder.ensure(StdLink::from_std(self, build_compiler_for_std_to_uplift));
-            return;
+            return stage_1_stamp;
         }
 
         target_deps.extend(self.copy_extra_objects(builder, &build_compiler, target));
@@ -284,11 +302,13 @@ impl Step for Std {
             build_compiler,
             target,
         );
+
+        let stamp = build_stamp::libstd_stamp(builder, build_compiler, target);
         run_cargo(
             builder,
             cargo,
             vec![],
-            &build_stamp::libstd_stamp(builder, build_compiler, target),
+            &stamp,
             target_deps,
             self.is_for_mir_opt_tests, // is_check
             false,
@@ -298,6 +318,7 @@ impl Step for Std {
             self,
             builder.compiler(build_compiler.stage, builder.config.host_target),
         ));
+        Some(stamp)
     }
 
     fn metadata(&self) -> Option<StepMetadata> {
@@ -560,29 +581,36 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, cargo: &mut Car
     // If `compiler-rt` is available ensure that the `c` feature of the
     // `compiler-builtins` crate is enabled and it's configured to learn where
     // `compiler-rt` is located.
-    let compiler_builtins_c_feature = if builder.config.optimized_compiler_builtins(target) {
-        // NOTE: this interacts strangely with `llvm-has-rust-patches`. In that case, we enforce `submodules = false`, so this is a no-op.
-        // But, the user could still decide to manually use an in-tree submodule.
-        //
-        // NOTE: if we're using system llvm, we'll end up building a version of `compiler-rt` that doesn't match the LLVM we're linking to.
-        // That's probably ok? At least, the difference wasn't enforced before. There's a comment in
-        // the compiler_builtins build script that makes me nervous, though:
-        // https://github.com/rust-lang/compiler-builtins/blob/31ee4544dbe47903ce771270d6e3bea8654e9e50/build.rs#L575-L579
-        builder.require_submodule(
-            "src/llvm-project",
-            Some(
-                "The `build.optimized-compiler-builtins` config option \
-                 requires `compiler-rt` sources from LLVM.",
-            ),
-        );
-        let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
-        assert!(compiler_builtins_root.exists());
-        // The path to `compiler-rt` is also used by `profiler_builtins` (above),
-        // so if you're changing something here please also change that as appropriate.
-        cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
-        " compiler-builtins-c"
-    } else {
-        ""
+    let compiler_builtins_c_feature = match builder.config.optimized_compiler_builtins(target) {
+        CompilerBuiltins::LinkLLVMBuiltinsLib(path) => {
+            cargo.env("LLVM_COMPILER_RT_LIB", path);
+            " compiler-builtins-c"
+        }
+        CompilerBuiltins::BuildLLVMFuncs => {
+            // NOTE: this interacts strangely with `llvm-has-rust-patches`. In that case, we enforce
+            // `submodules = false`, so this is a no-op. But, the user could still decide to
+            //  manually use an in-tree submodule.
+            //
+            // NOTE: if we're using system llvm, we'll end up building a version of `compiler-rt`
+            // that doesn't match the LLVM we're linking to. That's probably ok? At least, the
+            // difference wasn't enforced before. There's a comment in the compiler_builtins build
+            // script that makes me nervous, though:
+            // https://github.com/rust-lang/compiler-builtins/blob/31ee4544dbe47903ce771270d6e3bea8654e9e50/build.rs#L575-L579
+            builder.require_submodule(
+                "src/llvm-project",
+                Some(
+                    "The `build.optimized-compiler-builtins` config option \
+                     requires `compiler-rt` sources from LLVM.",
+                ),
+            );
+            let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt");
+            assert!(compiler_builtins_root.exists());
+            // The path to `compiler-rt` is also used by `profiler_builtins` (above),
+            // so if you're changing something here please also change that as appropriate.
+            cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root);
+            " compiler-builtins-c"
+        }
+        CompilerBuiltins::BuildRustOnly => "",
     };
 
     // `libtest` uses this to know whether or not to support
@@ -1309,9 +1337,7 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS
         cargo.env("CFG_OMIT_GIT_HASH", "1");
     }
 
-    if let Some(backend) = builder.config.default_codegen_backend(target) {
-        cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend.name());
-    }
+    cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", builder.config.default_codegen_backend(target).name());
 
     let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
     let target_config = builder.config.target_config.get(&target);
@@ -2008,6 +2034,7 @@ impl Step for Assemble {
 
                 let host_llvm_bin_dir = command(&host_llvm_config)
                     .arg("--bindir")
+                    .cached()
                     .run_capture_stdout(builder)
                     .stdout()
                     .trim()
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index daac75c03e2..778c3beb50f 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -21,7 +21,9 @@ use tracing::instrument;
 
 use crate::core::build_steps::compile::{get_codegen_backend_file, normalize_codegen_backend_name};
 use crate::core::build_steps::doc::DocumentationFormat;
-use crate::core::build_steps::tool::{self, RustcPrivateCompilers, Tool};
+use crate::core::build_steps::tool::{
+    self, RustcPrivateCompilers, Tool, ToolTargetBuildMode, get_tool_target_compiler,
+};
 use crate::core::build_steps::vendor::{VENDOR_DIR, Vendor};
 use crate::core::build_steps::{compile, llvm};
 use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step, StepMetadata};
@@ -75,7 +77,10 @@ impl Step for Docs {
     /// Builds the `rust-docs` installer component.
     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
         let host = self.host;
-        builder.default_doc(&[]);
+        // FIXME: explicitly enumerate the steps that should be executed here, and gather their
+        // documentation, rather than running all default steps and then read their output
+        // from a shared directory.
+        builder.run_default_doc_steps();
 
         let dest = "share/doc/rust/html";
 
@@ -132,13 +137,20 @@ impl Step for JsonDocs {
     }
 }
 
+/// Builds the `rustc-docs` installer component.
+/// Apart from the documentation of the `rustc_*` crates, it also includes the documentation of
+/// various in-tree helper tools (bootstrap, build_helper, tidy),
+/// and also rustc_private tools like rustdoc, clippy, miri or rustfmt.
+///
+/// It is currently hosted at <https://doc.rust-lang.org/nightly/nightly-rustc>.
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct RustcDocs {
-    pub host: TargetSelection,
+    target: TargetSelection,
 }
 
 impl Step for RustcDocs {
-    type Output = Option<GeneratedTarball>;
+    type Output = GeneratedTarball;
+
     const DEFAULT: bool = true;
     const IS_HOST: bool = true;
 
@@ -148,18 +160,17 @@ impl Step for RustcDocs {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(RustcDocs { host: run.target });
+        run.builder.ensure(RustcDocs { target: run.target });
     }
 
-    /// Builds the `rustc-docs` installer component.
-    fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
-        let host = self.host;
-        builder.default_doc(&[]);
+    fn run(self, builder: &Builder<'_>) -> Self::Output {
+        let target = self.target;
+        builder.run_default_doc_steps();
 
-        let mut tarball = Tarball::new(builder, "rustc-docs", &host.triple);
+        let mut tarball = Tarball::new(builder, "rustc-docs", &target.triple);
         tarball.set_product_name("Rustc Documentation");
-        tarball.add_bulk_dir(builder.compiler_doc_out(host), "share/doc/rust/html/rustc");
-        Some(tarball.generate())
+        tarball.add_bulk_dir(builder.compiler_doc_out(target), "share/doc/rust/html/rustc");
+        tarball.generate()
     }
 }
 
@@ -354,9 +365,13 @@ fn get_cc_search_dirs(
     (bin_path, lib_path)
 }
 
+/// Builds the `rust-mingw` installer component.
+///
+/// This contains all the bits and pieces to run the MinGW Windows targets
+/// without any extra installed software (e.g., we bundle gcc, libraries, etc.).
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct Mingw {
-    pub host: TargetSelection,
+    target: TargetSelection,
 }
 
 impl Step for Mingw {
@@ -368,39 +383,46 @@ impl Step for Mingw {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(Mingw { host: run.target });
+        run.builder.ensure(Mingw { target: run.target });
     }
 
-    /// Builds the `rust-mingw` installer component.
-    ///
-    /// This contains all the bits and pieces to run the MinGW Windows targets
-    /// without any extra installed software (e.g., we bundle gcc, libraries, etc).
     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
-        let host = self.host;
-        if !host.ends_with("pc-windows-gnu") || !builder.config.dist_include_mingw_linker {
+        let target = self.target;
+        if !target.ends_with("pc-windows-gnu") || !builder.config.dist_include_mingw_linker {
             return None;
         }
 
-        let mut tarball = Tarball::new(builder, "rust-mingw", &host.triple);
+        let mut tarball = Tarball::new(builder, "rust-mingw", &target.triple);
         tarball.set_product_name("Rust MinGW");
 
-        make_win_dist(tarball.image_dir(), host, builder);
+        make_win_dist(tarball.image_dir(), target, builder);
 
         Some(tarball.generate())
     }
 
     fn metadata(&self) -> Option<StepMetadata> {
-        Some(StepMetadata::dist("mingw", self.host))
+        Some(StepMetadata::dist("mingw", self.target))
     }
 }
 
+/// Creates the `rustc` installer component.
+///
+/// This includes:
+/// - The compiler and LLVM.
+/// - Debugger scripts.
+/// - Various helper tools, e.g. LLD or Rust Analyzer proc-macro server (if enabled).
+/// - The licenses of all code used by the compiler.
+///
+/// It does not include any standard library.
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct Rustc {
-    pub compiler: Compiler,
+    /// This is the compiler that we will *ship* in this dist step.
+    pub target_compiler: Compiler,
 }
 
 impl Step for Rustc {
     type Output = GeneratedTarball;
+
     const DEFAULT: bool = true;
     const IS_HOST: bool = true;
 
@@ -409,19 +431,19 @@ impl Step for Rustc {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        run.builder
-            .ensure(Rustc { compiler: run.builder.compiler(run.builder.top_stage, run.target) });
+        run.builder.ensure(Rustc {
+            target_compiler: run.builder.compiler(run.builder.top_stage, run.target),
+        });
     }
 
-    /// Creates the `rustc` installer component.
     fn run(self, builder: &Builder<'_>) -> GeneratedTarball {
-        let compiler = self.compiler;
-        let host = self.compiler.host;
+        let target_compiler = self.target_compiler;
+        let target = self.target_compiler.host;
 
-        let tarball = Tarball::new(builder, "rustc", &host.triple);
+        let tarball = Tarball::new(builder, "rustc", &target.triple);
 
         // Prepare the rustc "image", what will actually end up getting installed
-        prepare_image(builder, compiler, tarball.image_dir());
+        prepare_image(builder, target_compiler, tarball.image_dir());
 
         // On MinGW we've got a few runtime DLL dependencies that we need to
         // include.
@@ -430,16 +452,16 @@ impl Step for Rustc {
         // anything requiring us to distribute a license, but it's likely the
         // install will *also* include the rust-mingw package, which also needs
         // licenses, so to be safe we just include it here in all MinGW packages.
-        if host.contains("pc-windows-gnu") && builder.config.dist_include_mingw_linker {
-            runtime_dll_dist(tarball.image_dir(), host, builder);
+        if target.contains("pc-windows-gnu") && builder.config.dist_include_mingw_linker {
+            runtime_dll_dist(tarball.image_dir(), target, builder);
             tarball.add_dir(builder.src.join("src/etc/third-party"), "share/doc");
         }
 
         return tarball.generate();
 
-        fn prepare_image(builder: &Builder<'_>, compiler: Compiler, image: &Path) {
-            let host = compiler.host;
-            let src = builder.sysroot(compiler);
+        fn prepare_image(builder: &Builder<'_>, target_compiler: Compiler, image: &Path) {
+            let target = target_compiler.host;
+            let src = builder.sysroot(target_compiler);
 
             // Copy rustc binary
             t!(fs::create_dir_all(image.join("bin")));
@@ -452,17 +474,11 @@ impl Step for Rustc {
                 .as_ref()
                 .is_none_or(|tools| tools.iter().any(|tool| tool == "rustdoc"))
             {
-                let rustdoc = builder.rustdoc_for_compiler(compiler);
+                let rustdoc = builder.rustdoc_for_compiler(target_compiler);
                 builder.install(&rustdoc, &image.join("bin"), FileType::Executable);
             }
 
-            let ra_proc_macro_srv_compiler =
-                builder.compiler_for(compiler.stage, builder.config.host_target, compiler.host);
-            let compilers = RustcPrivateCompilers::from_build_compiler(
-                builder,
-                ra_proc_macro_srv_compiler,
-                compiler.host,
-            );
+            let compilers = RustcPrivateCompilers::from_target_compiler(builder, target_compiler);
 
             if let Some(ra_proc_macro_srv) = builder.ensure_if_default(
                 tool::RustAnalyzerProcMacroSrv::from_compilers(compilers),
@@ -472,11 +488,11 @@ impl Step for Rustc {
                 builder.install(&ra_proc_macro_srv.tool_path, &dst, FileType::Executable);
             }
 
-            let libdir_relative = builder.libdir_relative(compiler);
+            let libdir_relative = builder.libdir_relative(target_compiler);
 
             // Copy runtime DLLs needed by the compiler
             if libdir_relative.to_str() != Some("bin") {
-                let libdir = builder.rustc_libdir(compiler);
+                let libdir = builder.rustc_libdir(target_compiler);
                 for entry in builder.read_dir(&libdir) {
                     // A safeguard that we will not ship libgccjit.so from the libdir, in case the
                     // GCC codegen backend is enabled by default.
@@ -503,15 +519,15 @@ impl Step for Rustc {
             // components like the llvm tools and LLD. LLD is included below and
             // tools/LLDB come later, so let's just throw it in the rustc
             // component for now.
-            maybe_install_llvm_runtime(builder, host, image);
+            maybe_install_llvm_runtime(builder, target, image);
 
-            let dst_dir = image.join("lib/rustlib").join(host).join("bin");
+            let dst_dir = image.join("lib/rustlib").join(target).join("bin");
             t!(fs::create_dir_all(&dst_dir));
 
             // Copy over lld if it's there
             if builder.config.lld_enabled {
-                let src_dir = builder.sysroot_target_bindir(compiler, host);
-                let rust_lld = exe("rust-lld", compiler.host);
+                let src_dir = builder.sysroot_target_bindir(target_compiler, target);
+                let rust_lld = exe("rust-lld", target_compiler.host);
                 builder.copy_link(
                     &src_dir.join(&rust_lld),
                     &dst_dir.join(&rust_lld),
@@ -521,7 +537,7 @@ impl Step for Rustc {
                 let self_contained_lld_dst_dir = dst_dir.join("gcc-ld");
                 t!(fs::create_dir(&self_contained_lld_dst_dir));
                 for name in crate::LLD_FILE_NAMES {
-                    let exe_name = exe(name, compiler.host);
+                    let exe_name = exe(name, target_compiler.host);
                     builder.copy_link(
                         &self_contained_lld_src_dir.join(&exe_name),
                         &self_contained_lld_dst_dir.join(&exe_name),
@@ -530,10 +546,12 @@ impl Step for Rustc {
                 }
             }
 
-            if builder.config.llvm_enabled(compiler.host) && builder.config.llvm_tools_enabled {
-                let src_dir = builder.sysroot_target_bindir(compiler, host);
-                let llvm_objcopy = exe("llvm-objcopy", compiler.host);
-                let rust_objcopy = exe("rust-objcopy", compiler.host);
+            if builder.config.llvm_enabled(target_compiler.host)
+                && builder.config.llvm_tools_enabled
+            {
+                let src_dir = builder.sysroot_target_bindir(target_compiler, target);
+                let llvm_objcopy = exe("llvm-objcopy", target_compiler.host);
+                let rust_objcopy = exe("rust-objcopy", target_compiler.host);
                 builder.copy_link(
                     &src_dir.join(&llvm_objcopy),
                     &dst_dir.join(&rust_objcopy),
@@ -542,8 +560,8 @@ impl Step for Rustc {
             }
 
             if builder.tool_enabled("wasm-component-ld") {
-                let src_dir = builder.sysroot_target_bindir(compiler, host);
-                let ld = exe("wasm-component-ld", compiler.host);
+                let src_dir = builder.sysroot_target_bindir(target_compiler, target);
+                let ld = exe("wasm-component-ld", target_compiler.host);
                 builder.copy_link(&src_dir.join(&ld), &dst_dir.join(&ld), FileType::Executable);
             }
 
@@ -564,7 +582,7 @@ impl Step for Rustc {
             }
 
             // Debugger scripts
-            builder.ensure(DebuggerScripts { sysroot: image.to_owned(), host });
+            builder.ensure(DebuggerScripts { sysroot: image.to_owned(), target });
 
             // HTML copyright files
             let file_list = builder.ensure(super::run::GenerateCopyright);
@@ -590,14 +608,16 @@ impl Step for Rustc {
     }
 
     fn metadata(&self) -> Option<StepMetadata> {
-        Some(StepMetadata::dist("rustc", self.compiler.host))
+        Some(StepMetadata::dist("rustc", self.target_compiler.host))
     }
 }
 
+/// Copies debugger scripts for `target` into the given compiler `sysroot`.
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct DebuggerScripts {
+    /// Sysroot of a compiler into which will the debugger scripts be copied to.
     pub sysroot: PathBuf,
-    pub host: TargetSelection,
+    pub target: TargetSelection,
 }
 
 impl Step for DebuggerScripts {
@@ -607,16 +627,15 @@ impl Step for DebuggerScripts {
         run.never()
     }
 
-    /// Copies debugger scripts for `target` into the `sysroot` specified.
     fn run(self, builder: &Builder<'_>) {
-        let host = self.host;
+        let target = self.target;
         let sysroot = self.sysroot;
         let dst = sysroot.join("lib/rustlib/etc");
         t!(fs::create_dir_all(&dst));
         let cp_debugger_script = |file: &str| {
             builder.install(&builder.src.join("src/etc/").join(file), &dst, FileType::Regular);
         };
-        if host.contains("windows-msvc") {
+        if target.contains("windows-msvc") {
             // windbg debugger scripts
             builder.install(
                 &builder.src.join("src/etc/rust-windbg.cmd"),
@@ -730,12 +749,40 @@ fn copy_target_libs(
     }
 }
 
+/// Builds the standard library (`rust-std`) dist component for a given `target`.
+/// This includes the standard library dynamic library file (e.g. .so/.dll), along with stdlib
+/// .rlibs.
+///
+/// Note that due to uplifting, we actually ship the stage 1 library
+/// (built using the stage1 compiler) even with a stage 2 dist, unless `full-bootstrap` is enabled.
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct Std {
-    pub compiler: Compiler,
+    /// Compiler that will build the standard library.
+    pub build_compiler: Compiler,
     pub target: TargetSelection,
 }
 
+impl Std {
+    pub fn new(builder: &Builder<'_>, target: TargetSelection) -> Self {
+        // This is an important optimization mainly for CI.
+        // Normally, to build stage N libstd, we need stage N rustc.
+        // However, if we know that we will uplift libstd from stage 1 anyway, building the stage N
+        // rustc can be wasteful.
+        // In particular, if we do a cross-compiling dist stage 2 build from T1 to T2, we need:
+        // - stage 2 libstd for T2 (uplifted from stage 1, where it was built by T1 rustc)
+        // - stage 2 rustc for T2
+        // However, without this optimization, we would also build stage 2 rustc for **T1**, which
+        // is completely wasteful.
+        let build_compiler =
+            if compile::Std::should_be_uplifted_from_stage_1(builder, builder.top_stage, target) {
+                builder.compiler(1, builder.host_target)
+            } else {
+                builder.compiler(builder.top_stage, builder.host_target)
+            };
+        Std { build_compiler, target }
+    }
+}
+
 impl Step for Std {
     type Output = Option<GeneratedTarball>;
     const DEFAULT: bool = true;
@@ -745,31 +792,25 @@ impl Step for Std {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(Std {
-            compiler: run.builder.compiler_for(
-                run.builder.top_stage,
-                run.builder.config.host_target,
-                run.target,
-            ),
-            target: run.target,
-        });
+        run.builder.ensure(Std::new(run.builder, run.target));
     }
 
     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
-        let compiler = self.compiler;
+        let build_compiler = self.build_compiler;
         let target = self.target;
 
-        if skip_host_target_lib(builder, compiler) {
+        if skip_host_target_lib(builder, build_compiler) {
             return None;
         }
 
-        builder.std(compiler, target);
+        // It's possible that std was uplifted and thus built with a different build compiler
+        // So we need to read the stamp that was actually generated when std was built
+        let stamp =
+            builder.std(build_compiler, target).expect("Standard library has to be built for dist");
 
         let mut tarball = Tarball::new(builder, "rust-std", &target.triple);
         tarball.include_target_in_component_name(true);
 
-        let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
-        let stamp = build_stamp::libstd_stamp(builder, compiler_to_use, target);
         verify_uefi_rlib_format(builder, target, &stamp);
         copy_target_libs(builder, target, tarball.image_dir(), &stamp);
 
@@ -777,7 +818,7 @@ impl Step for Std {
     }
 
     fn metadata(&self) -> Option<StepMetadata> {
-        Some(StepMetadata::dist("std", self.target).built_by(self.compiler))
+        Some(StepMetadata::dist("std", self.target).built_by(self.build_compiler))
     }
 }
 
@@ -787,8 +828,9 @@ impl Step for Std {
 /// (Don't confuse this with [`RustDev`], without the `c`!)
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct RustcDev {
-    pub compiler: Compiler,
-    pub target: TargetSelection,
+    /// The compiler that will build rustc which will be shipped in this component.
+    build_compiler: Compiler,
+    target: TargetSelection,
 }
 
 impl Step for RustcDev {
@@ -802,28 +844,27 @@ impl Step for RustcDev {
 
     fn make_run(run: RunConfig<'_>) {
         run.builder.ensure(RustcDev {
-            compiler: run.builder.compiler_for(
-                run.builder.top_stage,
-                run.builder.config.host_target,
-                run.target,
-            ),
+            // We currently always ship a stage 2 rustc-dev component, so we build it with the
+            // stage 1 compiler. This might change in the future.
+            // The precise stage used here is important, so we hard-code it.
+            build_compiler: run.builder.compiler(1, run.builder.config.host_target),
             target: run.target,
         });
     }
 
     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
-        let compiler = self.compiler;
+        let build_compiler = self.build_compiler;
         let target = self.target;
-        if skip_host_target_lib(builder, compiler) {
+        if skip_host_target_lib(builder, build_compiler) {
             return None;
         }
 
-        builder.ensure(compile::Rustc::new(compiler, target));
+        // Build the compiler that we will ship
+        builder.ensure(compile::Rustc::new(build_compiler, target));
 
         let tarball = Tarball::new(builder, "rustc-dev", &target.triple);
 
-        let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target);
-        let stamp = build_stamp::librustc_stamp(builder, compiler_to_use, target);
+        let stamp = build_stamp::librustc_stamp(builder, build_compiler, target);
         copy_target_libs(builder, target, tarball.image_dir(), &stamp);
 
         let src_files = &["Cargo.lock"];
@@ -847,16 +888,25 @@ impl Step for RustcDev {
 
         Some(tarball.generate())
     }
+
+    fn metadata(&self) -> Option<StepMetadata> {
+        Some(StepMetadata::dist("rustc-dev", self.target).built_by(self.build_compiler))
+    }
 }
 
+/// The `rust-analysis` component used to create a tarball of save-analysis metadata.
+///
+/// This component has been deprecated and its contents now only include a warning about
+/// its non-availability.
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct Analysis {
-    pub compiler: Compiler,
-    pub target: TargetSelection,
+    build_compiler: Compiler,
+    target: TargetSelection,
 }
 
 impl Step for Analysis {
     type Output = Option<GeneratedTarball>;
+
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -865,24 +915,17 @@ impl Step for Analysis {
     }
 
     fn make_run(run: RunConfig<'_>) {
+        // The step just produces a deprecation notice, so we just hardcode stage 1
         run.builder.ensure(Analysis {
-            // Find the actual compiler (handling the full bootstrap option) which
-            // produced the save-analysis data because that data isn't copied
-            // through the sysroot uplifting.
-            compiler: run.builder.compiler_for(
-                run.builder.top_stage,
-                run.builder.config.host_target,
-                run.target,
-            ),
+            build_compiler: run.builder.compiler(1, run.builder.config.host_target),
             target: run.target,
         });
     }
 
-    /// Creates a tarball of (degenerate) save-analysis metadata, if available.
     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
-        let compiler = self.compiler;
+        let compiler = self.build_compiler;
         let target = self.target;
-        if !builder.config.is_host_target(compiler.host) {
+        if skip_host_target_lib(builder, compiler) {
             return None;
         }
 
@@ -905,6 +948,10 @@ impl Step for Analysis {
         tarball.add_dir(src, format!("lib/rustlib/{}/analysis", target.triple));
         Some(tarball.generate())
     }
+
+    fn metadata(&self) -> Option<StepMetadata> {
+        Some(StepMetadata::dist("analysis", self.target).built_by(self.build_compiler))
+    }
 }
 
 /// Use the `builder` to make a filtered copy of `base`/X for X in (`src_dirs` - `exclude_dirs`) to
@@ -1251,10 +1298,9 @@ impl Step for Cargo {
 
     fn make_run(run: RunConfig<'_>) {
         run.builder.ensure(Cargo {
-            build_compiler: run.builder.compiler_for(
-                run.builder.top_stage,
-                run.builder.config.host_target,
-                run.target,
+            build_compiler: get_tool_target_compiler(
+                run.builder,
+                ToolTargetBuildMode::Build(run.target),
             ),
             target: run.target,
         });
@@ -1285,11 +1331,16 @@ impl Step for Cargo {
 
         Some(tarball.generate())
     }
+
+    fn metadata(&self) -> Option<StepMetadata> {
+        Some(StepMetadata::dist("cargo", self.target).built_by(self.build_compiler))
+    }
 }
 
+/// Distribute the rust-analyzer component, which is used as a LSP by various IDEs.
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct RustAnalyzer {
-    pub build_compiler: Compiler,
+    pub compilers: RustcPrivateCompilers,
     pub target: TargetSelection,
 }
 
@@ -1305,21 +1356,14 @@ impl Step for RustAnalyzer {
 
     fn make_run(run: RunConfig<'_>) {
         run.builder.ensure(RustAnalyzer {
-            build_compiler: run.builder.compiler_for(
-                run.builder.top_stage,
-                run.builder.config.host_target,
-                run.target,
-            ),
+            compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
             target: run.target,
         });
     }
 
     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
         let target = self.target;
-        let compilers =
-            RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target);
-
-        let rust_analyzer = builder.ensure(tool::RustAnalyzer::from_compilers(compilers));
+        let rust_analyzer = builder.ensure(tool::RustAnalyzer::from_compilers(self.compilers));
 
         let mut tarball = Tarball::new(builder, "rust-analyzer", &target.triple);
         tarball.set_overlay(OverlayKind::RustAnalyzer);
@@ -1328,11 +1372,18 @@ impl Step for RustAnalyzer {
         tarball.add_legal_and_readme_to("share/doc/rust-analyzer");
         Some(tarball.generate())
     }
+
+    fn metadata(&self) -> Option<StepMetadata> {
+        Some(
+            StepMetadata::dist("rust-analyzer", self.target)
+                .built_by(self.compilers.build_compiler()),
+        )
+    }
 }
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct Clippy {
-    pub build_compiler: Compiler,
+    pub compilers: RustcPrivateCompilers,
     pub target: TargetSelection,
 }
 
@@ -1348,25 +1399,19 @@ impl Step for Clippy {
 
     fn make_run(run: RunConfig<'_>) {
         run.builder.ensure(Clippy {
-            build_compiler: run.builder.compiler_for(
-                run.builder.top_stage,
-                run.builder.config.host_target,
-                run.target,
-            ),
+            compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
             target: run.target,
         });
     }
 
     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
         let target = self.target;
-        let compilers =
-            RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, target);
 
         // Prepare the image directory
         // We expect clippy to build, because we've exited this step above if tool
         // state for clippy isn't testing.
-        let clippy = builder.ensure(tool::Clippy::from_compilers(compilers));
-        let cargoclippy = builder.ensure(tool::CargoClippy::from_compilers(compilers));
+        let clippy = builder.ensure(tool::Clippy::from_compilers(self.compilers));
+        let cargoclippy = builder.ensure(tool::CargoClippy::from_compilers(self.compilers));
 
         let mut tarball = Tarball::new(builder, "clippy", &target.triple);
         tarball.set_overlay(OverlayKind::Clippy);
@@ -1376,11 +1421,15 @@ impl Step for Clippy {
         tarball.add_legal_and_readme_to("share/doc/clippy");
         Some(tarball.generate())
     }
+
+    fn metadata(&self) -> Option<StepMetadata> {
+        Some(StepMetadata::dist("clippy", self.target).built_by(self.compilers.build_compiler()))
+    }
 }
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct Miri {
-    pub build_compiler: Compiler,
+    pub compilers: RustcPrivateCompilers,
     pub target: TargetSelection,
 }
 
@@ -1396,11 +1445,7 @@ impl Step for Miri {
 
     fn make_run(run: RunConfig<'_>) {
         run.builder.ensure(Miri {
-            build_compiler: run.builder.compiler_for(
-                run.builder.top_stage,
-                run.builder.config.host_target,
-                run.target,
-            ),
+            compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
             target: run.target,
         });
     }
@@ -1413,10 +1458,8 @@ impl Step for Miri {
             return None;
         }
 
-        let compilers =
-            RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target);
-        let miri = builder.ensure(tool::Miri::from_compilers(compilers));
-        let cargomiri = builder.ensure(tool::CargoMiri::from_compilers(compilers));
+        let miri = builder.ensure(tool::Miri::from_compilers(self.compilers));
+        let cargomiri = builder.ensure(tool::CargoMiri::from_compilers(self.compilers));
 
         let mut tarball = Tarball::new(builder, "miri", &self.target.triple);
         tarball.set_overlay(OverlayKind::Miri);
@@ -1426,11 +1469,15 @@ impl Step for Miri {
         tarball.add_legal_and_readme_to("share/doc/miri");
         Some(tarball.generate())
     }
+
+    fn metadata(&self) -> Option<StepMetadata> {
+        Some(StepMetadata::dist("miri", self.target).built_by(self.compilers.build_compiler()))
+    }
 }
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct CraneliftCodegenBackend {
-    pub build_compiler: Compiler,
+    pub compilers: RustcPrivateCompilers,
     pub target: TargetSelection,
 }
 
@@ -1454,11 +1501,7 @@ impl Step for CraneliftCodegenBackend {
 
     fn make_run(run: RunConfig<'_>) {
         run.builder.ensure(CraneliftCodegenBackend {
-            build_compiler: run.builder.compiler_for(
-                run.builder.top_stage,
-                run.builder.config.host_target,
-                run.target,
-            ),
+            compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
             target: run.target,
         });
     }
@@ -1472,8 +1515,6 @@ impl Step for CraneliftCodegenBackend {
         }
 
         let target = self.target;
-        let compilers =
-            RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, target);
         if !target_supports_cranelift_backend(target) {
             builder.info("target not supported by rustc_codegen_cranelift. skipping");
             return None;
@@ -1484,6 +1525,7 @@ impl Step for CraneliftCodegenBackend {
         tarball.is_preview(true);
         tarball.add_legal_and_readme_to("share/doc/rustc_codegen_cranelift");
 
+        let compilers = self.compilers;
         let stamp = builder.ensure(compile::CraneliftCodegenBackend { compilers });
 
         if builder.config.dry_run() {
@@ -1513,15 +1555,15 @@ impl Step for CraneliftCodegenBackend {
 
     fn metadata(&self) -> Option<StepMetadata> {
         Some(
-            StepMetadata::dist("rustc_codegen_cranelift", self.build_compiler.host)
-                .built_by(self.build_compiler),
+            StepMetadata::dist("rustc_codegen_cranelift", self.target)
+                .built_by(self.compilers.build_compiler()),
         )
     }
 }
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct Rustfmt {
-    pub build_compiler: Compiler,
+    pub compilers: RustcPrivateCompilers,
     pub target: TargetSelection,
 }
 
@@ -1537,21 +1579,14 @@ impl Step for Rustfmt {
 
     fn make_run(run: RunConfig<'_>) {
         run.builder.ensure(Rustfmt {
-            build_compiler: run.builder.compiler_for(
-                run.builder.top_stage,
-                run.builder.config.host_target,
-                run.target,
-            ),
+            compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target),
             target: run.target,
         });
     }
 
     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
-        let compilers =
-            RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target);
-
-        let rustfmt = builder.ensure(tool::Rustfmt::from_compilers(compilers));
-        let cargofmt = builder.ensure(tool::Cargofmt::from_compilers(compilers));
+        let rustfmt = builder.ensure(tool::Rustfmt::from_compilers(self.compilers));
+        let cargofmt = builder.ensure(tool::Cargofmt::from_compilers(self.compilers));
 
         let mut tarball = Tarball::new(builder, "rustfmt", &self.target.triple);
         tarball.set_overlay(OverlayKind::Rustfmt);
@@ -1561,12 +1596,16 @@ impl Step for Rustfmt {
         tarball.add_legal_and_readme_to("share/doc/rustfmt");
         Some(tarball.generate())
     }
+
+    fn metadata(&self) -> Option<StepMetadata> {
+        Some(StepMetadata::dist("rustfmt", self.target).built_by(self.compilers.build_compiler()))
+    }
 }
 
+/// Extended archive that contains the compiler, standard library and a bunch of tools.
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct Extended {
-    stage: u32,
-    host: TargetSelection,
+    build_compiler: Compiler,
     target: TargetSelection,
 }
 
@@ -1582,8 +1621,9 @@ impl Step for Extended {
 
     fn make_run(run: RunConfig<'_>) {
         run.builder.ensure(Extended {
-            stage: run.builder.top_stage,
-            host: run.builder.config.host_target,
+            build_compiler: run
+                .builder
+                .compiler(run.builder.top_stage - 1, run.builder.host_target),
             target: run.target,
         });
     }
@@ -1591,10 +1631,7 @@ impl Step for Extended {
     /// Creates a combined installer for the specified target in the provided stage.
     fn run(self, builder: &Builder<'_>) {
         let target = self.target;
-        let stage = self.stage;
-        let compiler = builder.compiler_for(self.stage, self.host, self.target);
-
-        builder.info(&format!("Dist extended stage{} ({})", compiler.stage, target));
+        builder.info(&format!("Dist extended stage{} ({target})", builder.top_stage));
 
         let mut tarballs = Vec::new();
         let mut built_tools = HashSet::new();
@@ -1607,34 +1644,38 @@ impl Step for Extended {
             };
         }
 
-        let target_compiler = builder.compiler(stage, target);
+        let rustc_private_compilers =
+            RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, target);
+        let build_compiler = rustc_private_compilers.build_compiler();
+        let target_compiler = rustc_private_compilers.target_compiler();
+
         // When rust-std package split from rustc, we needed to ensure that during
         // upgrades rustc was upgraded before rust-std. To avoid rustc clobbering
         // the std files during uninstall. To do this ensure that rustc comes
         // before rust-std in the list below.
-        tarballs.push(builder.ensure(Rustc { compiler: target_compiler }));
-        tarballs.push(builder.ensure(Std { compiler, target }).expect("missing std"));
+        tarballs.push(builder.ensure(Rustc { target_compiler }));
+        tarballs.push(builder.ensure(Std { build_compiler, target }).expect("missing std"));
 
         if target.is_windows_gnu() {
-            tarballs.push(builder.ensure(Mingw { host: target }).expect("missing mingw"));
+            tarballs.push(builder.ensure(Mingw { target }).expect("missing mingw"));
         }
 
         add_component!("rust-docs" => Docs { host: target });
         // Std stage N is documented with compiler stage N
         add_component!("rust-json-docs" => JsonDocs { build_compiler: target_compiler, target });
-        add_component!("cargo" => Cargo { build_compiler: compiler, target });
-        add_component!("rustfmt" => Rustfmt { build_compiler: compiler, target });
-        add_component!("rust-analyzer" => RustAnalyzer { build_compiler: compiler, target });
+        add_component!("cargo" => Cargo { build_compiler, target });
+        add_component!("rustfmt" => Rustfmt { compilers: rustc_private_compilers, target });
+        add_component!("rust-analyzer" => RustAnalyzer { compilers: rustc_private_compilers, target });
         add_component!("llvm-components" => LlvmTools { target });
-        add_component!("clippy" => Clippy { build_compiler: compiler, target });
-        add_component!("miri" => Miri { build_compiler: compiler, target });
-        add_component!("analysis" => Analysis { compiler, target });
+        add_component!("clippy" => Clippy { compilers: rustc_private_compilers, target });
+        add_component!("miri" => Miri { compilers: rustc_private_compilers, target });
+        add_component!("analysis" => Analysis { build_compiler, target });
         add_component!("rustc-codegen-cranelift" => CraneliftCodegenBackend {
-            build_compiler: compiler,
+            compilers: rustc_private_compilers,
             target
         });
         add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker {
-            build_compiler: compiler,
+            build_compiler,
             target
         });
 
@@ -2100,6 +2141,10 @@ impl Step for Extended {
             }
         }
     }
+
+    fn metadata(&self) -> Option<StepMetadata> {
+        Some(StepMetadata::dist("extended", self.target).built_by(self.build_compiler))
+    }
 }
 
 fn add_env(
@@ -2236,6 +2281,7 @@ fn maybe_install_llvm(
     {
         trace!("LLVM already built, installing LLVM files");
         let mut cmd = command(host_llvm_config);
+        cmd.cached();
         cmd.arg("--libfiles");
         builder.verbose(|| println!("running {cmd:?}"));
         let files = cmd.run_capture_stdout(builder).stdout();
@@ -2562,15 +2608,17 @@ impl Step for RustDev {
 
 /// Tarball intended for internal consumption to ease rustc/std development.
 ///
+/// It only packages the binaries that were already compiled when bootstrap itself was built.
+///
 /// Should not be considered stable by end users.
 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
 pub struct Bootstrap {
-    pub target: TargetSelection,
+    target: TargetSelection,
 }
 
 impl Step for Bootstrap {
     type Output = Option<GeneratedTarball>;
-    const DEFAULT: bool = false;
+
     const IS_HOST: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -2597,6 +2645,10 @@ impl Step for Bootstrap {
 
         Some(tarball.generate())
     }
+
+    fn metadata(&self) -> Option<StepMetadata> {
+        Some(StepMetadata::dist("bootstrap", self.target))
+    }
 }
 
 /// Tarball containing a prebuilt version of the build-manifest tool, intended to be used by the
@@ -2605,12 +2657,12 @@ impl Step for Bootstrap {
 /// Should not be considered stable by end users.
 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
 pub struct BuildManifest {
-    pub target: TargetSelection,
+    target: TargetSelection,
 }
 
 impl Step for BuildManifest {
     type Output = GeneratedTarball;
-    const DEFAULT: bool = false;
+
     const IS_HOST: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -2628,16 +2680,20 @@ impl Step for BuildManifest {
         tarball.add_file(&build_manifest, "bin", FileType::Executable);
         tarball.generate()
     }
+
+    fn metadata(&self) -> Option<StepMetadata> {
+        Some(StepMetadata::dist("build-manifest", self.target))
+    }
 }
 
 /// Tarball containing artifacts necessary to reproduce the build of rustc.
 ///
-/// Currently this is the PGO profile data.
+/// Currently this is the PGO (and possibly BOLT) profile data.
 ///
 /// Should not be considered stable by end users.
 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
 pub struct ReproducibleArtifacts {
-    pub target: TargetSelection,
+    target: TargetSelection,
 }
 
 impl Step for ReproducibleArtifacts {
@@ -2670,6 +2726,10 @@ impl Step for ReproducibleArtifacts {
         }
         if added_anything { Some(tarball.generate()) } else { None }
     }
+
+    fn metadata(&self) -> Option<StepMetadata> {
+        Some(StepMetadata::dist("reproducible-artifacts", self.target))
+    }
 }
 
 /// Tarball containing a prebuilt version of the libgccjit library,
@@ -2677,7 +2737,7 @@ impl Step for ReproducibleArtifacts {
 /// backend needing a prebuilt libLLVM).
 #[derive(Clone, Debug, Eq, Hash, PartialEq)]
 pub struct Gcc {
-    pub target: TargetSelection,
+    target: TargetSelection,
 }
 
 impl Step for Gcc {
@@ -2697,4 +2757,8 @@ impl Step for Gcc {
         tarball.add_file(&output.libgccjit, "lib", FileType::NativeLibrary);
         tarball.generate()
     }
+
+    fn metadata(&self) -> Option<StepMetadata> {
+        Some(StepMetadata::dist("gcc", self.target))
+    }
 }
diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs
index 7fe19c00ef5..8c20c8c479a 100644
--- a/src/bootstrap/src/core/build_steps/doc.rs
+++ b/src/bootstrap/src/core/build_steps/doc.rs
@@ -784,7 +784,7 @@ fn doc_std(
 
     let description =
         format!("library{} in {} format", crate_description(requested_crates), format.as_str());
-    let _guard = builder.msg(Kind::Doc, description, None, build_compiler, target);
+    let _guard = builder.msg(Kind::Doc, description, Mode::Std, build_compiler, target);
 
     cargo.into_cmd().run(builder);
     builder.cp_link_r(&out_dir, out);
@@ -994,7 +994,7 @@ macro_rules! tool_doc {
                     (compilers.build_compiler(), Mode::ToolRustc)
                 } else {
                     // bootstrap/host tools have to be documented with the stage 0 compiler
-                    (prepare_doc_compiler(run.builder, target, 1), Mode::ToolBootstrap)
+                    (prepare_doc_compiler(run.builder, run.builder.host_target, 1), Mode::ToolBootstrap)
                 };
 
                 run.builder.ensure($tool { build_compiler, mode, target });
diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs
index 4457258e9cd..ce68dbf5a20 100644
--- a/src/bootstrap/src/core/build_steps/install.rs
+++ b/src/bootstrap/src/core/build_steps/install.rs
@@ -7,6 +7,7 @@ use std::path::{Component, Path, PathBuf};
 use std::{env, fs};
 
 use crate::core::build_steps::dist;
+use crate::core::build_steps::tool::RustcPrivateCompilers;
 use crate::core::builder::{Builder, RunConfig, ShouldRun, Step};
 use crate::core::config::{Config, TargetSelection};
 use crate::utils::exec::command;
@@ -64,17 +65,14 @@ fn is_dir_writable_for_user(dir: &Path) -> bool {
 fn install_sh(
     builder: &Builder<'_>,
     package: &str,
-    stage: u32,
-    host: Option<TargetSelection>,
+    build_compiler: impl Into<Option<Compiler>>,
+    target: Option<TargetSelection>,
     tarball: &GeneratedTarball,
 ) {
-    let _guard = builder.msg(
-        Kind::Install,
-        package,
-        None,
-        (host.unwrap_or(builder.host_target), stage),
-        host,
-    );
+    let _guard = match build_compiler.into() {
+        Some(build_compiler) => builder.msg(Kind::Install, package, None, build_compiler, target),
+        None => builder.msg_unstaged(Kind::Install, package, target.unwrap_or(builder.host_target)),
+    };
 
     let prefix = default_path(&builder.config.prefix, "/usr/local");
     let sysconfdir = prefix.join(default_path(&builder.config.sysconfdir, "/etc"));
@@ -166,10 +164,10 @@ macro_rules! install {
        IS_HOST: $IS_HOST:expr,
        $run_item:block $(, $c:ident)*;)+) => {
         $(
-            #[derive(Debug, Clone, Hash, PartialEq, Eq)]
+        #[derive(Debug, Clone, Hash, PartialEq, Eq)]
         pub struct $name {
-            pub compiler: Compiler,
-            pub target: TargetSelection,
+            build_compiler: Compiler,
+            target: TargetSelection,
         }
 
         impl $name {
@@ -193,7 +191,7 @@ macro_rules! install {
 
             fn make_run(run: RunConfig<'_>) {
                 run.builder.ensure($name {
-                    compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.host_target),
+                    build_compiler: run.builder.compiler(run.builder.top_stage - 1, run.builder.config.host_target),
                     target: run.target,
                 });
             }
@@ -208,96 +206,95 @@ macro_rules! install {
 install!((self, builder, _config),
     Docs, path = "src/doc", _config.docs, IS_HOST: false, {
         let tarball = builder.ensure(dist::Docs { host: self.target }).expect("missing docs");
-        install_sh(builder, "docs", self.compiler.stage, Some(self.target), &tarball);
+        install_sh(builder, "docs", self.build_compiler, Some(self.target), &tarball);
     };
     Std, path = "library/std", true, IS_HOST: false, {
         // `expect` should be safe, only None when host != build, but this
         // only runs when host == build
-        let tarball = builder.ensure(dist::Std {
-            compiler: self.compiler,
-            target: self.target
-        }).expect("missing std");
-        install_sh(builder, "std", self.compiler.stage, Some(self.target), &tarball);
+        let std = dist::Std::new(builder, self.target);
+        let build_compiler = std.build_compiler;
+        let tarball = builder.ensure(std).expect("missing std");
+        install_sh(builder, "std", build_compiler, Some(self.target), &tarball);
     };
     Cargo, alias = "cargo", Self::should_build(_config), IS_HOST: true, {
         let tarball = builder
-            .ensure(dist::Cargo { build_compiler: self.compiler, target: self.target })
+            .ensure(dist::Cargo { build_compiler: self.build_compiler, target: self.target })
             .expect("missing cargo");
-        install_sh(builder, "cargo", self.compiler.stage, Some(self.target), &tarball);
+        install_sh(builder, "cargo", self.build_compiler, Some(self.target), &tarball);
     };
     RustAnalyzer, alias = "rust-analyzer", Self::should_build(_config), IS_HOST: true, {
         if let Some(tarball) =
-            builder.ensure(dist::RustAnalyzer { build_compiler: self.compiler, target: self.target })
+            builder.ensure(dist::RustAnalyzer { compilers: RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target), target: self.target })
         {
-            install_sh(builder, "rust-analyzer", self.compiler.stage, Some(self.target), &tarball);
+            install_sh(builder, "rust-analyzer", self.build_compiler, Some(self.target), &tarball);
         } else {
             builder.info(
-                &format!("skipping Install rust-analyzer stage{} ({})", self.compiler.stage, self.target),
+                &format!("skipping Install rust-analyzer stage{} ({})", self.build_compiler.stage + 1, self.target),
             );
         }
     };
     Clippy, alias = "clippy", Self::should_build(_config), IS_HOST: true, {
         let tarball = builder
-            .ensure(dist::Clippy { build_compiler: self.compiler, target: self.target })
+            .ensure(dist::Clippy { compilers: RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target), target: self.target })
             .expect("missing clippy");
-        install_sh(builder, "clippy", self.compiler.stage, Some(self.target), &tarball);
+        install_sh(builder, "clippy", self.build_compiler, Some(self.target), &tarball);
     };
     Miri, alias = "miri", Self::should_build(_config), IS_HOST: true, {
-        if let Some(tarball) = builder.ensure(dist::Miri { build_compiler: self.compiler, target: self.target }) {
-            install_sh(builder, "miri", self.compiler.stage, Some(self.target), &tarball);
+        if let Some(tarball) = builder.ensure(dist::Miri { compilers: RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target) , target: self.target }) {
+            install_sh(builder, "miri", self.build_compiler, Some(self.target), &tarball);
         } else {
             // Miri is only available on nightly
             builder.info(
-                &format!("skipping Install miri stage{} ({})", self.compiler.stage, self.target),
+                &format!("skipping Install miri stage{} ({})", self.build_compiler.stage + 1, self.target),
             );
         }
     };
     LlvmTools, alias = "llvm-tools", _config.llvm_tools_enabled && _config.llvm_enabled(_config.host_target), IS_HOST: true, {
         if let Some(tarball) = builder.ensure(dist::LlvmTools { target: self.target }) {
-            install_sh(builder, "llvm-tools", self.compiler.stage, Some(self.target), &tarball);
+            install_sh(builder, "llvm-tools", None, Some(self.target), &tarball);
         } else {
             builder.info(
-                &format!("skipping llvm-tools stage{} ({}): external LLVM", self.compiler.stage, self.target),
+                &format!("skipping llvm-tools ({}): external LLVM", self.target),
             );
         }
     };
     Rustfmt, alias = "rustfmt", Self::should_build(_config), IS_HOST: true, {
         if let Some(tarball) = builder.ensure(dist::Rustfmt {
-            build_compiler: self.compiler,
+            compilers: RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target),
             target: self.target
         }) {
-            install_sh(builder, "rustfmt", self.compiler.stage, Some(self.target), &tarball);
+            install_sh(builder, "rustfmt", self.build_compiler, Some(self.target), &tarball);
         } else {
             builder.info(
-                &format!("skipping Install Rustfmt stage{} ({})", self.compiler.stage, self.target),
+                &format!("skipping Install Rustfmt stage{} ({})", self.build_compiler.stage + 1, self.target),
             );
         }
     };
     Rustc, path = "compiler/rustc", true, IS_HOST: true, {
         let tarball = builder.ensure(dist::Rustc {
-            compiler: builder.compiler(builder.top_stage, self.target),
+            target_compiler: builder.compiler(self.build_compiler.stage + 1, self.target),
         });
-        install_sh(builder, "rustc", self.compiler.stage, Some(self.target), &tarball);
+        install_sh(builder, "rustc", self.build_compiler, Some(self.target), &tarball);
     };
     RustcCodegenCranelift, alias = "rustc-codegen-cranelift", Self::should_build(_config), IS_HOST: true, {
         if let Some(tarball) = builder.ensure(dist::CraneliftCodegenBackend {
-            build_compiler: self.compiler,
+            compilers: RustcPrivateCompilers::from_build_compiler(builder, self.build_compiler, self.target),
             target: self.target
         }) {
-            install_sh(builder, "rustc-codegen-cranelift", self.compiler.stage, Some(self.target), &tarball);
+            install_sh(builder, "rustc-codegen-cranelift", self.build_compiler, Some(self.target), &tarball);
         } else {
             builder.info(
                 &format!("skipping Install CodegenBackend(\"cranelift\") stage{} ({})",
-                         self.compiler.stage, self.target),
+                         self.build_compiler.stage + 1, self.target),
             );
         }
     };
     LlvmBitcodeLinker, alias = "llvm-bitcode-linker", Self::should_build(_config), IS_HOST: true, {
-        if let Some(tarball) = builder.ensure(dist::LlvmBitcodeLinker { build_compiler: self.compiler, target: self.target }) {
-            install_sh(builder, "llvm-bitcode-linker", self.compiler.stage, Some(self.target), &tarball);
+        if let Some(tarball) = builder.ensure(dist::LlvmBitcodeLinker { build_compiler: self.build_compiler, target: self.target }) {
+            install_sh(builder, "llvm-bitcode-linker", self.build_compiler, Some(self.target), &tarball);
         } else {
             builder.info(
-                &format!("skipping llvm-bitcode-linker stage{} ({})", self.compiler.stage, self.target),
+                &format!("skipping llvm-bitcode-linker stage{} ({})", self.build_compiler.stage + 1, self.target),
             );
         }
     };
@@ -305,7 +302,7 @@ install!((self, builder, _config),
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct Src {
-    pub stage: u32,
+    stage: u32,
 }
 
 impl Step for Src {
@@ -325,6 +322,6 @@ impl Step for Src {
 
     fn run(self, builder: &Builder<'_>) {
         let tarball = builder.ensure(dist::Src);
-        install_sh(builder, "src", self.stage, None, &tarball);
+        install_sh(builder, "src", None, None, &tarball);
     }
 }
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index 70259f0d1d7..d47c1495838 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -486,8 +486,11 @@ impl Step for Llvm {
             let LlvmResult { host_llvm_config, .. } =
                 builder.ensure(Llvm { target: builder.config.host_target });
             if !builder.config.dry_run() {
-                let llvm_bindir =
-                    command(&host_llvm_config).arg("--bindir").run_capture_stdout(builder).stdout();
+                let llvm_bindir = command(&host_llvm_config)
+                    .arg("--bindir")
+                    .cached()
+                    .run_capture_stdout(builder)
+                    .stdout();
                 let host_bin = Path::new(llvm_bindir.trim());
                 cfg.define(
                     "LLVM_TABLEGEN",
@@ -593,7 +596,13 @@ impl Step for Llvm {
 }
 
 pub fn get_llvm_version(builder: &Builder<'_>, llvm_config: &Path) -> String {
-    command(llvm_config).arg("--version").run_capture_stdout(builder).stdout().trim().to_owned()
+    command(llvm_config)
+        .arg("--version")
+        .cached()
+        .run_capture_stdout(builder)
+        .stdout()
+        .trim()
+        .to_owned()
 }
 
 pub fn get_llvm_version_major(builder: &Builder<'_>, llvm_config: &Path) -> u8 {
diff --git a/src/bootstrap/src/core/build_steps/run.rs b/src/bootstrap/src/core/build_steps/run.rs
index c6288f63847..d9de6b7ef96 100644
--- a/src/bootstrap/src/core/build_steps/run.rs
+++ b/src/bootstrap/src/core/build_steps/run.rs
@@ -5,13 +5,14 @@
 
 use std::path::PathBuf;
 
+use build_helper::exit;
 use clap_complete::{Generator, shells};
 
 use crate::core::build_steps::dist::distdir;
 use crate::core::build_steps::test;
 use crate::core::build_steps::tool::{self, RustcPrivateCompilers, SourceType, Tool};
 use crate::core::build_steps::vendor::{Vendor, default_paths_to_vendor};
-use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
+use crate::core::builder::{Builder, Kind, RunConfig, ShouldRun, Step, StepMetadata};
 use crate::core::config::TargetSelection;
 use crate::core::config::flags::get_completion;
 use crate::utils::exec::command;
@@ -100,8 +101,17 @@ impl Step for ReplaceVersionPlaceholder {
     }
 }
 
+/// Invoke the Miri tool on a specified file.
+///
+/// Note that Miri always executed on the host, as it is an interpreter.
+/// That means that `x run miri --target FOO` will build miri for the host,
+/// prepare a miri sysroot for the target `FOO` and then execute miri with
+/// the target `FOO`.
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct Miri {
+    /// The build compiler that will build miri and the target compiler to which miri links.
+    compilers: RustcPrivateCompilers,
+    /// The target which will miri interpret.
     target: TargetSelection,
 }
 
@@ -113,14 +123,9 @@ impl Step for Miri {
     }
 
     fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(Miri { target: run.target });
-    }
-
-    fn run(self, builder: &Builder<'_>) {
-        let host = builder.build.host_target;
-        let target = self.target;
+        let builder = run.builder;
 
-        // `x run` uses stage 0 by default but miri does not work well with stage 0.
+        // `x run` uses stage 0 by default, but miri does not work well with stage 0.
         // Change the stage to 1 if it's not set explicitly.
         let stage = if builder.config.is_explicit_stage() || builder.top_stage >= 1 {
             builder.top_stage
@@ -129,14 +134,22 @@ impl Step for Miri {
         };
 
         if stage == 0 {
-            eprintln!("miri cannot be run at stage 0");
-            std::process::exit(1);
+            eprintln!("ERROR: miri cannot be run at stage 0");
+            exit!(1);
         }
 
-        // This compiler runs on the host, we'll just use it for the target.
-        let compilers = RustcPrivateCompilers::new(builder, stage, target);
-        let miri_build = builder.ensure(tool::Miri::from_compilers(compilers));
-        let host_compiler = miri_build.build_compiler;
+        // Miri always runs on the host, because it can interpret code for any target
+        let compilers = RustcPrivateCompilers::new(builder, stage, builder.host_target);
+
+        run.builder.ensure(Miri { compilers, target: run.target });
+    }
+
+    fn run(self, builder: &Builder<'_>) {
+        let host = builder.build.host_target;
+        let compilers = self.compilers;
+        let target = self.target;
+
+        builder.ensure(tool::Miri::from_compilers(compilers));
 
         // Get a target sysroot for Miri.
         let miri_sysroot =
@@ -147,7 +160,7 @@ impl Step for Miri {
         // add_rustc_lib_path does not add the path that contains librustc_driver-<...>.so.
         let mut miri = tool::prepare_tool_cargo(
             builder,
-            host_compiler,
+            compilers.build_compiler(),
             Mode::ToolRustc,
             host,
             Kind::Run,
@@ -167,6 +180,10 @@ impl Step for Miri {
 
         miri.into_cmd().run(builder);
     }
+
+    fn metadata(&self) -> Option<StepMetadata> {
+        Some(StepMetadata::run("miri", self.target).built_by(self.compilers.build_compiler()))
+    }
 }
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 269e7da8d7b..26b4aaa8b5b 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -153,7 +153,7 @@ You can skip linkcheck with --skip src/tools/linkchecker"
         }
 
         // Build all the default documentation.
-        builder.default_doc(&[]);
+        builder.run_default_doc_steps();
 
         // Build the linkchecker before calling `msg`, since GHA doesn't support nested groups.
         let linkchecker = builder.tool_cmd(Tool::Linkchecker);
@@ -208,7 +208,7 @@ impl Step for HtmlCheck {
             panic!("Cannot run html-check tests");
         }
         // Ensure that a few different kinds of documentation are available.
-        builder.default_doc(&[]);
+        builder.run_default_doc_steps();
         builder.ensure(crate::core::build_steps::doc::Rustc::for_stage(
             builder,
             builder.top_stage,
@@ -1719,7 +1719,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
         if suite == "debuginfo" {
             builder.ensure(dist::DebuggerScripts {
                 sysroot: builder.sysroot(compiler).to_path_buf(),
-                host: target,
+                target,
             });
         }
         if suite == "run-make" {
@@ -1850,7 +1850,7 @@ HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?}
             // Tells compiletest which codegen backend to use.
             // It is used to e.g. ignore tests that don't support that codegen backend.
             cmd.arg("--default-codegen-backend")
-                .arg(builder.config.default_codegen_backend(compiler.host).unwrap().name());
+                .arg(builder.config.default_codegen_backend(compiler.host).name());
         }
 
         if builder.build.config.llvm_enzyme {
@@ -2025,8 +2025,6 @@ HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?}
             cmd.arg("--verbose");
         }
 
-        cmd.arg("--json");
-
         if builder.config.rustc_debug_assertions {
             cmd.arg("--with-rustc-debug-assertions");
         }
@@ -2043,6 +2041,7 @@ HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?}
             if !builder.config.dry_run() {
                 let llvm_version = get_llvm_version(builder, &host_llvm_config);
                 let llvm_components = command(&host_llvm_config)
+                    .cached()
                     .arg("--components")
                     .run_capture_stdout(builder)
                     .stdout();
@@ -2062,8 +2061,11 @@ HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?}
             // separate compilations. We can add LLVM's library path to the
             // rustc args as a workaround.
             if !builder.config.dry_run() && suite.ends_with("fulldeps") {
-                let llvm_libdir =
-                    command(&host_llvm_config).arg("--libdir").run_capture_stdout(builder).stdout();
+                let llvm_libdir = command(&host_llvm_config)
+                    .cached()
+                    .arg("--libdir")
+                    .run_capture_stdout(builder)
+                    .stdout();
                 let link_llvm = if target.is_msvc() {
                     format!("-Clink-arg=-LIBPATH:{llvm_libdir}")
                 } else {
@@ -3117,45 +3119,55 @@ impl Step for Distcheck {
     ///
     /// FIXME(#136822): dist components are under-tested.
     fn run(self, builder: &Builder<'_>) {
-        builder.info("Distcheck");
-        let dir = builder.tempdir().join("distcheck");
-        let _ = fs::remove_dir_all(&dir);
-        t!(fs::create_dir_all(&dir));
-
-        // Guarantee that these are built before we begin running.
-        builder.ensure(dist::PlainSourceTarball);
-        builder.ensure(dist::Src);
+        // Use a temporary directory completely outside the current checkout, to avoid reusing any
+        // local source code, built artifacts or configuration by accident
+        let root_dir = std::env::temp_dir().join("distcheck");
+
+        // Check that we can build some basic things from the plain source tarball
+        builder.info("Distcheck plain source tarball");
+        let plain_src_tarball = builder.ensure(dist::PlainSourceTarball);
+        let plain_src_dir = root_dir.join("distcheck-plain-src");
+        builder.clear_dir(&plain_src_dir);
+
+        let configure_args: Vec<String> = std::env::var("DISTCHECK_CONFIGURE_ARGS")
+            .map(|args| args.split(" ").map(|s| s.to_string()).collect::<Vec<String>>())
+            .unwrap_or_default();
 
         command("tar")
             .arg("-xf")
-            .arg(builder.ensure(dist::PlainSourceTarball).tarball())
+            .arg(plain_src_tarball.tarball())
             .arg("--strip-components=1")
-            .current_dir(&dir)
+            .current_dir(&plain_src_dir)
             .run(builder);
         command("./configure")
-            .args(&builder.config.configure_args)
+            .arg("--set")
+            .arg("rust.omit-git-hash=false")
+            .args(&configure_args)
             .arg("--enable-vendor")
-            .current_dir(&dir)
+            .current_dir(&plain_src_dir)
             .run(builder);
         command(helpers::make(&builder.config.host_target.triple))
             .arg("check")
-            .current_dir(&dir)
+            // Do not run the build as if we were in CI, otherwise git would be assumed to be
+            // present, but we build from a tarball here
+            .env("GITHUB_ACTIONS", "0")
+            .current_dir(&plain_src_dir)
             .run(builder);
 
         // Now make sure that rust-src has all of libstd's dependencies
         builder.info("Distcheck rust-src");
-        let dir = builder.tempdir().join("distcheck-src");
-        let _ = fs::remove_dir_all(&dir);
-        t!(fs::create_dir_all(&dir));
+        let src_tarball = builder.ensure(dist::Src);
+        let src_dir = root_dir.join("distcheck-src");
+        builder.clear_dir(&src_dir);
 
         command("tar")
             .arg("-xf")
-            .arg(builder.ensure(dist::Src).tarball())
+            .arg(src_tarball.tarball())
             .arg("--strip-components=1")
-            .current_dir(&dir)
+            .current_dir(&src_dir)
             .run(builder);
 
-        let toml = dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
+        let toml = src_dir.join("rust-src/lib/rustlib/src/rust/library/std/Cargo.toml");
         command(&builder.initial_cargo)
             // Will read the libstd Cargo.toml
             // which uses the unstable `public-dependency` feature.
@@ -3163,7 +3175,7 @@ impl Step for Distcheck {
             .arg("generate-lockfile")
             .arg("--manifest-path")
             .arg(&toml)
-            .current_dir(&dir)
+            .current_dir(&src_dir)
             .run(builder);
     }
 }
diff --git a/src/bootstrap/src/core/build_steps/vendor.rs b/src/bootstrap/src/core/build_steps/vendor.rs
index 7b860ceb943..0e9d4e7e32b 100644
--- a/src/bootstrap/src/core/build_steps/vendor.rs
+++ b/src/bootstrap/src/core/build_steps/vendor.rs
@@ -19,6 +19,7 @@ pub const VENDOR_DIR: &str = "vendor";
 pub fn default_paths_to_vendor(builder: &Builder<'_>) -> Vec<(PathBuf, Vec<&'static str>)> {
     [
         ("src/tools/cargo/Cargo.toml", vec!["src/tools/cargo"]),
+        ("src/tools/clippy/clippy_test_deps/Cargo.toml", vec![]),
         ("src/tools/rust-analyzer/Cargo.toml", vec![]),
         ("compiler/rustc_codegen_cranelift/Cargo.toml", vec![]),
         ("compiler/rustc_codegen_gcc/Cargo.toml", vec![]),
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index 72192403412..cdf6fe573e5 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -132,10 +132,7 @@ impl Cargo {
     }
 
     pub fn into_cmd(self) -> BootstrapCommand {
-        let mut cmd: BootstrapCommand = self.into();
-        // Disable caching for commands originating from Cargo-related operations.
-        cmd.do_not_cache();
-        cmd
+        self.into()
     }
 
     /// Same as [`Cargo::new`] except this one doesn't configure the linker with
@@ -1085,7 +1082,7 @@ impl Builder<'_> {
             && let Some(llvm_config) = self.llvm_config(target)
         {
             let llvm_libdir =
-                command(llvm_config).arg("--libdir").run_capture_stdout(self).stdout();
+                command(llvm_config).cached().arg("--libdir").run_capture_stdout(self).stdout();
             if target.is_msvc() {
                 rustflags.arg(&format!("-Clink-arg=-LIBPATH:{llvm_libdir}"));
             } else {
@@ -1326,12 +1323,7 @@ impl Builder<'_> {
 
             if let Some(limit) = limit
                 && (build_compiler_stage == 0
-                    || self
-                        .config
-                        .default_codegen_backend(target)
-                        .cloned()
-                        .unwrap_or_default()
-                        .is_llvm())
+                    || self.config.default_codegen_backend(target).is_llvm())
             {
                 rustflags.arg(&format!("-Cllvm-args=-import-instr-limit={limit}"));
             }
diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs
index 40460bf168d..f794f4e079a 100644
--- a/src/bootstrap/src/core/builder/mod.rs
+++ b/src/bootstrap/src/core/builder/mod.rs
@@ -22,6 +22,7 @@ use crate::core::build_steps::{
 };
 use crate::core::config::flags::Subcommand;
 use crate::core::config::{DryRun, TargetSelection};
+use crate::utils::build_stamp::BuildStamp;
 use crate::utils::cache::Cache;
 use crate::utils::exec::{BootstrapCommand, ExecutionContext, command};
 use crate::utils::helpers::{self, LldThreads, add_dylib_path, exe, libdir, linker_args, t};
@@ -144,8 +145,7 @@ pub trait Step: 'static + Clone + Debug + PartialEq + Eq + Hash {
 }
 
 /// Metadata that describes an executed step, mostly for testing and tracing.
-#[allow(unused)]
-#[derive(Debug, PartialEq, Eq)]
+#[derive(Clone, Debug, PartialEq, Eq)]
 pub struct StepMetadata {
     name: String,
     kind: Kind,
@@ -181,6 +181,10 @@ impl StepMetadata {
         Self::new(name, target, Kind::Test)
     }
 
+    pub fn run(name: &str, target: TargetSelection) -> Self {
+        Self::new(name, target, Kind::Run)
+    }
+
     fn new(name: &str, target: TargetSelection, kind: Kind) -> Self {
         Self { name: name.to_string(), kind, target, built_by: None, stage: None, metadata: None }
     }
@@ -1308,8 +1312,9 @@ impl<'a> Builder<'a> {
         self.run_step_descriptions(&Builder::get_step_descriptions(self.kind), &self.paths);
     }
 
-    pub fn default_doc(&self, paths: &[PathBuf]) {
-        self.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), paths);
+    /// Run all default documentation steps to build documentation.
+    pub fn run_default_doc_steps(&self) {
+        self.run_step_descriptions(&Builder::get_step_descriptions(Kind::Doc), &[]);
     }
 
     pub fn doc_rust_lang_org_channel(&self) -> String {
@@ -1411,6 +1416,8 @@ impl<'a> Builder<'a> {
     /// The standard library will be linked to the sysroot of the passed compiler.
     ///
     /// Prefer using this method rather than manually invoking `Std::new`.
+    ///
+    /// Returns an optional build stamp, if libstd was indeed built.
     #[cfg_attr(
         feature = "tracing",
         instrument(
@@ -1424,29 +1431,38 @@ impl<'a> Builder<'a> {
             ),
         ),
     )]
-    pub fn std(&self, compiler: Compiler, target: TargetSelection) {
+    pub fn std(&self, compiler: Compiler, target: TargetSelection) -> Option<BuildStamp> {
         // FIXME: make the `Std` step return some type-level "proof" that std was indeed built,
         // and then require passing that to all Cargo invocations that we do.
 
-        // The "stage 0" std is always precompiled and comes with the stage0 compiler, so we have
-        // special logic for it, to avoid creating needless and confusing Std steps that don't
+        // The "stage 0" std is almost always precompiled and comes with the stage0 compiler, so we
+        // have special logic for it, to avoid creating needless and confusing Std steps that don't
         // actually build anything.
+        // We only allow building the stage0 stdlib if we do a local rebuild, so the stage0 compiler
+        // actually comes from in-tree sources, and we're cross-compiling, so the stage0 for the
+        // given `target` is not available.
         if compiler.stage == 0 {
             if target != compiler.host {
-                panic!(
-                    r"It is not possible to build the standard library for `{target}` using the stage0 compiler.
+                if self.local_rebuild {
+                    self.ensure(Std::new(compiler, target))
+                } else {
+                    panic!(
+                        r"It is not possible to build the standard library for `{target}` using the stage0 compiler.
 You have to build a stage1 compiler for `{}` first, and then use it to build a standard library for `{target}`.
+Alternatively, you can set `build.local-rebuild=true` and use a stage0 compiler built from in-tree sources.
 ",
-                    compiler.host
-                )
+                        compiler.host
+                    )
+                }
+            } else {
+                // We still need to link the prebuilt standard library into the ephemeral stage0 sysroot
+                self.ensure(StdLink::from_std(Std::new(compiler, target), compiler));
+                None
             }
-
-            // We still need to link the prebuilt standard library into the ephemeral stage0 sysroot
-            self.ensure(StdLink::from_std(Std::new(compiler, target), compiler));
         } else {
             // This step both compiles the std and links it into the compiler's sysroot.
             // Yes, it's quite magical and side-effecty.. would be nice to refactor later.
-            self.ensure(Std::new(compiler, target));
+            self.ensure(Std::new(compiler, target))
         }
     }
 
diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index 2afba25ae59..3c2cb782850 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -854,6 +854,18 @@ mod snapshot {
     }
 
     #[test]
+    fn build_library_stage_0_local_rebuild() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("build")
+                .path("library")
+                .stage(0)
+                .targets(&[TEST_TRIPLE_1])
+                .args(&["--set", "build.local-rebuild=true"])
+                .render_steps(), @"[build] rustc 0 <host> -> std 0 <target1>");
+    }
+
+    #[test]
     fn build_library_stage_1() {
         let ctx = TestCtx::new();
         insta::assert_snapshot!(
@@ -1134,7 +1146,9 @@ mod snapshot {
         [build] rustc 0 <host> -> GenerateCopyright 1 <host>
         [dist] rustc <host>
         [dist] rustc 1 <host> -> std 1 <host>
+        [dist] rustc 1 <host> -> rustc-dev 2 <host>
         [dist] src <>
+        [dist] reproducible-artifacts <host>
         "
         );
     }
@@ -1196,15 +1210,24 @@ mod snapshot {
         [build] rustc 0 <host> -> GenerateCopyright 1 <host>
         [dist] rustc <host>
         [dist] rustc 1 <host> -> std 1 <host>
+        [dist] rustc 1 <host> -> rustc-dev 2 <host>
+        [dist] rustc 1 <host> -> analysis 2 <host>
         [dist] src <>
         [build] rustc 1 <host> -> cargo 2 <host>
+        [dist] rustc 1 <host> -> cargo 2 <host>
         [build] rustc 1 <host> -> rust-analyzer 2 <host>
+        [dist] rustc 1 <host> -> rust-analyzer 2 <host>
         [build] rustc 1 <host> -> rustfmt 2 <host>
         [build] rustc 1 <host> -> cargo-fmt 2 <host>
+        [dist] rustc 1 <host> -> rustfmt 2 <host>
         [build] rustc 1 <host> -> clippy-driver 2 <host>
         [build] rustc 1 <host> -> cargo-clippy 2 <host>
+        [dist] rustc 1 <host> -> clippy 2 <host>
         [build] rustc 1 <host> -> miri 2 <host>
         [build] rustc 1 <host> -> cargo-miri 2 <host>
+        [dist] rustc 1 <host> -> miri 2 <host>
+        [dist] rustc 1 <host> -> extended 2 <host>
+        [dist] reproducible-artifacts <host>
         ");
     }
 
@@ -1276,7 +1299,9 @@ mod snapshot {
         [dist] rustc 1 <host> -> std 1 <host>
         [build] rustc 2 <host> -> std 2 <target1>
         [dist] rustc 2 <host> -> std 2 <target1>
+        [dist] rustc 1 <host> -> rustc-dev 2 <host>
         [dist] src <>
+        [dist] reproducible-artifacts <host>
         "
         );
     }
@@ -1334,7 +1359,11 @@ mod snapshot {
         [build] rustdoc 2 <target1>
         [dist] rustc <target1>
         [dist] rustc 1 <host> -> std 1 <host>
+        [dist] rustc 1 <host> -> rustc-dev 2 <host>
+        [dist] rustc 1 <host> -> rustc-dev 2 <target1>
         [dist] src <>
+        [dist] reproducible-artifacts <host>
+        [dist] reproducible-artifacts <target1>
         "
         );
     }
@@ -1413,7 +1442,11 @@ mod snapshot {
         [dist] rustc <target1>
         [dist] rustc 1 <host> -> std 1 <host>
         [dist] rustc 1 <host> -> std 1 <target1>
+        [dist] rustc 1 <host> -> rustc-dev 2 <host>
+        [dist] rustc 1 <host> -> rustc-dev 2 <target1>
         [dist] src <>
+        [dist] reproducible-artifacts <host>
+        [dist] reproducible-artifacts <target1>
         "
         );
     }
@@ -1462,10 +1495,8 @@ mod snapshot {
         ");
     }
 
-    /// This also serves as an important regression test for <https://github.com/rust-lang/rust/issues/138123>
-    /// and <https://github.com/rust-lang/rust/issues/138004>.
     #[test]
-    fn dist_all_cross() {
+    fn dist_all_cross_extended() {
         let ctx = TestCtx::new();
         insta::assert_snapshot!(
             ctx
@@ -1518,22 +1549,99 @@ mod snapshot {
         [build] rustc 0 <host> -> GenerateCopyright 1 <host>
         [dist] rustc <target1>
         [dist] rustc 1 <host> -> std 1 <target1>
+        [dist] rustc 1 <host> -> rustc-dev 2 <target1>
+        [dist] rustc 1 <host> -> analysis 2 <target1>
         [dist] src <>
         [build] rustc 1 <host> -> cargo 2 <target1>
+        [dist] rustc 1 <host> -> cargo 2 <target1>
         [build] rustc 1 <host> -> rust-analyzer 2 <target1>
+        [dist] rustc 1 <host> -> rust-analyzer 2 <target1>
         [build] rustc 1 <host> -> rustfmt 2 <target1>
         [build] rustc 1 <host> -> cargo-fmt 2 <target1>
+        [dist] rustc 1 <host> -> rustfmt 2 <target1>
         [build] rustc 1 <host> -> clippy-driver 2 <target1>
         [build] rustc 1 <host> -> cargo-clippy 2 <target1>
+        [dist] rustc 1 <host> -> clippy 2 <target1>
         [build] rustc 1 <host> -> miri 2 <target1>
         [build] rustc 1 <host> -> cargo-miri 2 <target1>
+        [dist] rustc 1 <host> -> miri 2 <target1>
         [build] rustc 1 <host> -> LlvmBitcodeLinker 2 <target1>
         [doc] rustc 2 <target1> -> std 2 <target1> crates=[]
+        [dist] rustc 1 <host> -> extended 2 <target1>
+        [dist] reproducible-artifacts <target1>
         ");
     }
 
-    // Enable dist cranelift tarball by default with `x dist` if cranelift is enabled in
-    // `rust.codegen-backends`.
+    /// Simulates e.g. the powerpc64 builder, which is fully cross-compiled from x64, but it does
+    /// not build docs. Crutically, it shouldn't build host stage 2 rustc.
+    ///
+    /// This is a regression test for <https://github.com/rust-lang/rust/issues/138123>
+    /// and <https://github.com/rust-lang/rust/issues/138004>.
+    #[test]
+    fn dist_all_cross_extended_no_docs() {
+        let ctx = TestCtx::new();
+        let steps = ctx
+            .config("dist")
+            .hosts(&[TEST_TRIPLE_1])
+            .targets(&[TEST_TRIPLE_1])
+            .args(&[
+                "--set",
+                "rust.channel=nightly",
+                "--set",
+                "build.extended=true",
+                "--set",
+                "build.docs=false",
+            ])
+            .get_steps();
+
+        // Make sure that we don't build stage2 host rustc
+        steps.assert_no_match(|m| {
+            m.name == "rustc"
+                && m.built_by.map(|b| b.stage) == Some(1)
+                && *m.target.triple == host_target()
+        });
+
+        insta::assert_snapshot!(
+                steps.render(), @r"
+        [dist] mingw <target1>
+        [build] llvm <host>
+        [build] llvm <target1>
+        [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustc 0 <host> -> WasmComponentLd 1 <host>
+        [build] rustc 1 <host> -> std 1 <target1>
+        [build] rustc 1 <host> -> std 1 <host>
+        [build] rustc 1 <host> -> rustc 2 <target1>
+        [build] rustc 1 <host> -> WasmComponentLd 2 <target1>
+        [build] rustdoc 2 <target1>
+        [build] rustc 1 <host> -> rust-analyzer-proc-macro-srv 2 <target1>
+        [build] rustc 0 <host> -> GenerateCopyright 1 <host>
+        [build] rustc 0 <host> -> RustInstaller 1 <host>
+        [dist] rustc <target1>
+        [dist] rustc 1 <host> -> std 1 <target1>
+        [dist] rustc 1 <host> -> rustc-dev 2 <target1>
+        [dist] rustc 1 <host> -> analysis 2 <target1>
+        [dist] src <>
+        [build] rustc 1 <host> -> cargo 2 <target1>
+        [dist] rustc 1 <host> -> cargo 2 <target1>
+        [build] rustc 1 <host> -> rust-analyzer 2 <target1>
+        [dist] rustc 1 <host> -> rust-analyzer 2 <target1>
+        [build] rustc 1 <host> -> rustfmt 2 <target1>
+        [build] rustc 1 <host> -> cargo-fmt 2 <target1>
+        [dist] rustc 1 <host> -> rustfmt 2 <target1>
+        [build] rustc 1 <host> -> clippy-driver 2 <target1>
+        [build] rustc 1 <host> -> cargo-clippy 2 <target1>
+        [dist] rustc 1 <host> -> clippy 2 <target1>
+        [build] rustc 1 <host> -> miri 2 <target1>
+        [build] rustc 1 <host> -> cargo-miri 2 <target1>
+        [dist] rustc 1 <host> -> miri 2 <target1>
+        [build] rustc 1 <host> -> LlvmBitcodeLinker 2 <target1>
+        [dist] rustc 1 <host> -> extended 2 <target1>
+        [dist] reproducible-artifacts <target1>
+        ");
+    }
+
+    /// Enable dist cranelift tarball by default with `x dist` if cranelift is enabled in
+    /// `rust.codegen-backends`.
     #[test]
     fn dist_cranelift_by_default() {
         let ctx = TestCtx::new();
@@ -1581,7 +1689,38 @@ mod snapshot {
         [dist] rustc <host>
         [dist] rustc 1 <host> -> rustc_codegen_cranelift 2 <host>
         [dist] rustc 1 <host> -> std 1 <host>
+        [dist] rustc 1 <host> -> rustc-dev 2 <host>
         [dist] src <>
+        [dist] reproducible-artifacts <host>
+        ");
+    }
+
+    #[test]
+    fn dist_bootstrap() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx
+                .config("dist")
+                .path("bootstrap")
+                .render_steps(), @r"
+        [build] rustc 0 <host> -> RustInstaller 1 <host>
+        [dist] bootstrap <host>
+        ");
+    }
+
+    #[test]
+    fn dist_library_stage_0_local_rebuild() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("dist")
+                .path("rust-std")
+                .stage(0)
+                .targets(&[TEST_TRIPLE_1])
+                .args(&["--set", "build.local-rebuild=true"])
+                .render_steps(), @r"
+        [build] rustc 0 <host> -> std 0 <target1>
+        [build] rustc 0 <host> -> RustInstaller 1 <host>
+        [dist] rustc 0 <host> -> std 0 <target1>
         ");
     }
 
@@ -2126,6 +2265,214 @@ mod snapshot {
         [doc] rustc 1 <host> -> reference (book) 2 <host>
         ");
     }
+
+    #[test]
+    fn clippy_ci() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("clippy")
+                .path("ci")
+                .stage(2)
+                .render_steps(), @r"
+        [build] llvm <host>
+        [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustc 1 <host> -> std 1 <host>
+        [build] rustc 0 <host> -> clippy-driver 1 <host>
+        [build] rustc 0 <host> -> cargo-clippy 1 <host>
+        [clippy] rustc 1 <host> -> bootstrap 2 <host>
+        [clippy] rustc 1 <host> -> std 1 <host>
+        [clippy] rustc 1 <host> -> rustc 2 <host>
+        [check] rustc 1 <host> -> rustc 2 <host>
+        [clippy] rustc 1 <host> -> rustc_codegen_gcc 2 <host>
+        ");
+    }
+
+    #[test]
+    fn clippy_compiler_stage1() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("clippy")
+                .path("compiler")
+                .render_steps(), @r"
+        [build] llvm <host>
+        [clippy] rustc 0 <host> -> rustc 1 <host>
+        ");
+    }
+
+    #[test]
+    fn clippy_compiler_stage2() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("clippy")
+                .path("compiler")
+                .stage(2)
+                .render_steps(), @r"
+        [build] llvm <host>
+        [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustc 1 <host> -> std 1 <host>
+        [build] rustc 0 <host> -> clippy-driver 1 <host>
+        [build] rustc 0 <host> -> cargo-clippy 1 <host>
+        [clippy] rustc 1 <host> -> rustc 2 <host>
+        ");
+    }
+
+    #[test]
+    fn clippy_std_stage1() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("clippy")
+                .path("std")
+                .render_steps(), @r"
+        [build] llvm <host>
+        [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustc 0 <host> -> clippy-driver 1 <host>
+        [build] rustc 0 <host> -> cargo-clippy 1 <host>
+        [clippy] rustc 1 <host> -> std 1 <host>
+        ");
+    }
+
+    #[test]
+    fn clippy_std_stage2() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("clippy")
+                .path("std")
+                .stage(2)
+                .render_steps(), @r"
+        [build] llvm <host>
+        [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustc 1 <host> -> std 1 <host>
+        [build] rustc 1 <host> -> rustc 2 <host>
+        [build] rustc 1 <host> -> clippy-driver 2 <host>
+        [build] rustc 1 <host> -> cargo-clippy 2 <host>
+        [clippy] rustc 2 <host> -> std 2 <host>
+        ");
+    }
+
+    #[test]
+    fn clippy_miri_stage1() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("clippy")
+                .path("miri")
+                .stage(1)
+                .render_steps(), @r"
+        [build] llvm <host>
+        [check] rustc 0 <host> -> rustc 1 <host>
+        [clippy] rustc 0 <host> -> miri 1 <host>
+        ");
+    }
+
+    #[test]
+    fn clippy_miri_stage2() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("clippy")
+                .path("miri")
+                .stage(2)
+                .render_steps(), @r"
+        [build] llvm <host>
+        [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustc 1 <host> -> std 1 <host>
+        [check] rustc 1 <host> -> rustc 2 <host>
+        [build] rustc 0 <host> -> clippy-driver 1 <host>
+        [build] rustc 0 <host> -> cargo-clippy 1 <host>
+        [clippy] rustc 1 <host> -> miri 2 <host>
+        ");
+    }
+
+    #[test]
+    fn clippy_bootstrap() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("clippy")
+                .path("bootstrap")
+                .render_steps(), @"[clippy] rustc 0 <host> -> bootstrap 1 <host>");
+    }
+
+    #[test]
+    fn install_extended() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("install")
+                .args(&[
+                    // Using backslashes fails with `--set`
+                    "--set", &format!("install.prefix={}", ctx.dir().display()).replace("\\", "/"),
+                    "--set", &format!("install.sysconfdir={}", ctx.dir().display()).replace("\\", "/"),
+                    "--set", "build.extended=true"
+                ])
+                .render_steps(), @r"
+        [build] llvm <host>
+        [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustc 0 <host> -> WasmComponentLd 1 <host>
+        [build] rustc 0 <host> -> UnstableBookGen 1 <host>
+        [build] rustc 0 <host> -> Rustbook 1 <host>
+        [doc] unstable-book (book) <host>
+        [build] rustc 1 <host> -> std 1 <host>
+        [doc] book (book) <host>
+        [doc] book/first-edition (book) <host>
+        [doc] book/second-edition (book) <host>
+        [doc] book/2018-edition (book) <host>
+        [build] rustdoc 1 <host>
+        [doc] rustc 1 <host> -> standalone 2 <host>
+        [build] rustc 1 <host> -> rustc 2 <host>
+        [build] rustc 1 <host> -> WasmComponentLd 2 <host>
+        [build] rustdoc 2 <host>
+        [doc] rustc 2 <host> -> std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind]
+        [build] rustc 1 <host> -> error-index 2 <host>
+        [doc] rustc 1 <host> -> error-index 2 <host>
+        [doc] nomicon (book) <host>
+        [doc] rustc 1 <host> -> reference (book) 2 <host>
+        [doc] rustdoc (book) <host>
+        [doc] rust-by-example (book) <host>
+        [build] rustc 0 <host> -> LintDocs 1 <host>
+        [doc] rustc (book) <host>
+        [doc] cargo (book) <host>
+        [doc] clippy (book) <host>
+        [doc] embedded-book (book) <host>
+        [doc] edition-guide (book) <host>
+        [doc] style-guide (book) <host>
+        [doc] rustc 1 <host> -> releases 2 <host>
+        [build] rustc 0 <host> -> RustInstaller 1 <host>
+        [dist] docs <host>
+        [dist] rustc 1 <host> -> std 1 <host>
+        [build] rustc 1 <host> -> rust-analyzer-proc-macro-srv 2 <host>
+        [build] rustc 0 <host> -> GenerateCopyright 1 <host>
+        [dist] rustc <host>
+        [build] rustc 1 <host> -> cargo 2 <host>
+        [dist] rustc 1 <host> -> cargo 2 <host>
+        [build] rustc 1 <host> -> rust-analyzer 2 <host>
+        [dist] rustc 1 <host> -> rust-analyzer 2 <host>
+        [build] rustc 1 <host> -> rustfmt 2 <host>
+        [build] rustc 1 <host> -> cargo-fmt 2 <host>
+        [dist] rustc 1 <host> -> rustfmt 2 <host>
+        [build] rustc 1 <host> -> clippy-driver 2 <host>
+        [build] rustc 1 <host> -> cargo-clippy 2 <host>
+        [dist] rustc 1 <host> -> clippy 2 <host>
+        [build] rustc 1 <host> -> miri 2 <host>
+        [build] rustc 1 <host> -> cargo-miri 2 <host>
+        [dist] rustc 1 <host> -> miri 2 <host>
+        [dist] src <>
+        ");
+    }
+
+    // Check that `x run miri --target FOO` actually builds miri for the host.
+    #[test]
+    fn run_miri() {
+        let ctx = TestCtx::new();
+        insta::assert_snapshot!(
+            ctx.config("run")
+                .path("miri")
+                .stage(1)
+                .targets(&[TEST_TRIPLE_1])
+                .render_steps(), @r"
+        [build] llvm <host>
+        [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustc 0 <host> -> miri 1 <host>
+        [build] rustc 0 <host> -> cargo-miri 1 <host>
+        [run] rustc 0 <host> -> miri 1 <target1>
+        ");
+    }
 }
 
 struct ExecutedSteps {
@@ -2180,6 +2527,21 @@ impl ExecutedSteps {
         }
     }
 
+    /// Make sure that no metadata matches the given `func`.
+    #[track_caller]
+    fn assert_no_match<F>(&self, func: F)
+    where
+        F: Fn(StepMetadata) -> bool,
+    {
+        for metadata in self.steps.iter().filter_map(|s| s.metadata.clone()) {
+            if func(metadata.clone()) {
+                panic!(
+                    "Metadata {metadata:?} was found, even though it should have not been present"
+                );
+            }
+        }
+    }
+
     fn contains(&self, metadata: &StepMetadata) -> bool {
         self.steps
             .iter()
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index f579bdd847f..a8eb563015f 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -46,8 +46,8 @@ use crate::core::config::toml::rust::{
 };
 use crate::core::config::toml::target::Target;
 use crate::core::config::{
-    DebuginfoLevel, DryRun, GccCiMode, LlvmLibunwind, Merge, ReplaceOpt, RustcLto, SplitDebuginfo,
-    StringOrBool, threads_from_config,
+    CompilerBuiltins, DebuginfoLevel, DryRun, GccCiMode, LlvmLibunwind, Merge, ReplaceOpt,
+    RustcLto, SplitDebuginfo, StringOrBool, threads_from_config,
 };
 use crate::core::download::{
     DownloadContext, download_beta_toolchain, is_download_ci_available, maybe_download_rustfmt,
@@ -121,8 +121,7 @@ pub struct Config {
     pub patch_binaries_for_nix: Option<bool>,
     pub stage0_metadata: build_helper::stage0_parser::Stage0,
     pub android_ndk: Option<PathBuf>,
-    /// Whether to use the `c` feature of the `compiler_builtins` crate.
-    pub optimized_compiler_builtins: bool,
+    pub optimized_compiler_builtins: CompilerBuiltins,
 
     pub stdout_is_tty: bool,
     pub stderr_is_tty: bool,
@@ -327,59 +326,6 @@ pub struct Config {
 }
 
 impl Config {
-    #[cfg_attr(
-        feature = "tracing",
-        instrument(target = "CONFIG_HANDLING", level = "trace", name = "Config::default_opts")
-    )]
-    pub fn default_opts() -> Config {
-        #[cfg(feature = "tracing")]
-        span!(target: "CONFIG_HANDLING", tracing::Level::TRACE, "constructing default config");
-
-        Config {
-            bypass_bootstrap_lock: false,
-            llvm_optimize: true,
-            ninja_in_file: true,
-            llvm_static_stdcpp: false,
-            llvm_libzstd: false,
-            backtrace: true,
-            rust_optimize: RustOptimize::Bool(true),
-            rust_optimize_tests: true,
-            rust_randomize_layout: false,
-            submodules: None,
-            docs: true,
-            docs_minification: true,
-            rust_rpath: true,
-            rust_strip: false,
-            channel: "dev".to_string(),
-            codegen_tests: true,
-            rust_dist_src: true,
-            rust_codegen_backends: vec![CodegenBackendKind::Llvm],
-            deny_warnings: true,
-            bindir: "bin".into(),
-            dist_include_mingw_linker: true,
-            dist_compression_profile: "fast".into(),
-
-            stdout_is_tty: std::io::stdout().is_terminal(),
-            stderr_is_tty: std::io::stderr().is_terminal(),
-
-            // set by build.rs
-            host_target: get_host_target(),
-
-            src: {
-                let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
-                // Undo `src/bootstrap`
-                manifest_dir.parent().unwrap().parent().unwrap().to_owned()
-            },
-            out: PathBuf::from("build"),
-
-            // This is needed by codegen_ssa on macOS to ship `llvm-objcopy` aliased to
-            // `rust-objcopy` to workaround bad `strip`s on macOS.
-            llvm_tools_enabled: true,
-
-            ..Default::default()
-        }
-    }
-
     pub fn set_dry_run(&mut self, dry_run: DryRun) {
         self.exec_ctx.set_dry_run(dry_run);
     }
@@ -1014,8 +960,8 @@ impl Config {
             Subcommand::Dist => flags_stage.or(build_dist_stage).unwrap_or(2),
             Subcommand::Install => flags_stage.or(build_install_stage).unwrap_or(2),
             Subcommand::Perf { .. } => flags_stage.unwrap_or(1),
-            // These are all bootstrap tools, which don't depend on the compiler.
-            // The stage we pass shouldn't matter, but use 0 just in case.
+            // Most of the run commands execute bootstrap tools, which don't depend on the compiler.
+            // Other commands listed here should always use bootstrap tools.
             Subcommand::Clean { .. }
             | Subcommand::Run { .. }
             | Subcommand::Setup { .. }
@@ -1023,23 +969,38 @@ impl Config {
             | Subcommand::Vendor { .. } => flags_stage.unwrap_or(0),
         };
 
-        // Now check that the selected stage makes sense, and if not, print a warning and end
+        let local_rebuild = build_local_rebuild.unwrap_or(false);
+
+        let check_stage0 = |kind: &str| {
+            if local_rebuild {
+                eprintln!("WARNING: running {kind} in stage 0. This might not work as expected.");
+            } else {
+                eprintln!(
+                    "ERROR: cannot {kind} anything on stage 0. Use at least stage 1 or set build.local-rebuild=true and use a stage0 compiler built from in-tree sources."
+                );
+                exit!(1);
+            }
+        };
+
+        // Now check that the selected stage makes sense, and if not, print an error and end
         match (stage, &flags_cmd) {
             (0, Subcommand::Build { .. }) => {
-                eprintln!("ERROR: cannot build anything on stage 0. Use at least stage 1.");
-                exit!(1);
+                check_stage0("build");
             }
             (0, Subcommand::Check { .. }) => {
-                eprintln!("ERROR: cannot check anything on stage 0. Use at least stage 1.");
-                exit!(1);
+                check_stage0("check");
             }
             (0, Subcommand::Doc { .. }) => {
-                eprintln!("ERROR: cannot document anything on stage 0. Use at least stage 1.");
-                exit!(1);
+                check_stage0("doc");
             }
             (0, Subcommand::Clippy { .. }) => {
-                eprintln!("ERROR: cannot run clippy on stage 0. Use at least stage 1.");
-                exit!(1);
+                check_stage0("clippy");
+            }
+            (0, Subcommand::Dist) => {
+                check_stage0("dist");
+            }
+            (0, Subcommand::Install) => {
+                check_stage0("install");
             }
             _ => {}
         }
@@ -1154,7 +1115,11 @@ impl Config {
         let rustfmt_info = git_info(&exec_ctx, omit_git_hash, &src.join("src/tools/rustfmt"));
 
         let optimized_compiler_builtins =
-            build_optimized_compiler_builtins.unwrap_or(channel != "dev");
+            build_optimized_compiler_builtins.unwrap_or(if channel == "dev" {
+                CompilerBuiltins::BuildRustOnly
+            } else {
+                CompilerBuiltins::BuildLLVMFuncs
+            });
         let vendor = build_vendor.unwrap_or(
             rust_info.is_from_tarball()
                 && src.join("vendor").exists()
@@ -1276,7 +1241,7 @@ impl Config {
             llvm_use_libcxx: llvm_use_libcxx.unwrap_or(false),
             llvm_use_linker,
             llvm_version_suffix,
-            local_rebuild: build_local_rebuild.unwrap_or(false),
+            local_rebuild,
             locked_deps: build_locked_deps.unwrap_or(false),
             low_priority: build_low_priority.unwrap_or(false),
             mandir: install_mandir.map(PathBuf::from),
@@ -1705,8 +1670,9 @@ impl Config {
 
     /// Returns the codegen backend that should be configured as the *default* codegen backend
     /// for a rustc compiled by bootstrap.
-    pub fn default_codegen_backend(&self, target: TargetSelection) -> Option<&CodegenBackendKind> {
-        self.enabled_codegen_backends(target).first()
+    pub fn default_codegen_backend(&self, target: TargetSelection) -> &CodegenBackendKind {
+        // We're guaranteed to have always at least one codegen backend listed.
+        self.enabled_codegen_backends(target).first().unwrap()
     }
 
     pub fn jemalloc(&self, target: TargetSelection) -> bool {
@@ -1717,11 +1683,11 @@ impl Config {
         self.target_config.get(&target).and_then(|t| t.rpath).unwrap_or(self.rust_rpath)
     }
 
-    pub fn optimized_compiler_builtins(&self, target: TargetSelection) -> bool {
+    pub fn optimized_compiler_builtins(&self, target: TargetSelection) -> &CompilerBuiltins {
         self.target_config
             .get(&target)
-            .and_then(|t| t.optimized_compiler_builtins)
-            .unwrap_or(self.optimized_compiler_builtins)
+            .and_then(|t| t.optimized_compiler_builtins.as_ref())
+            .unwrap_or(&self.optimized_compiler_builtins)
     }
 
     pub fn llvm_enabled(&self, target: TargetSelection) -> bool {
diff --git a/src/bootstrap/src/core/config/mod.rs b/src/bootstrap/src/core/config/mod.rs
index dbd05fd2519..5999348a7fe 100644
--- a/src/bootstrap/src/core/config/mod.rs
+++ b/src/bootstrap/src/core/config/mod.rs
@@ -218,6 +218,33 @@ impl<T> Merge for Option<T> {
     }
 }
 
+#[derive(Clone, Debug, Default, Eq, PartialEq)]
+pub enum CompilerBuiltins {
+    #[default]
+    // Only build native rust intrinsic compiler functions.
+    BuildRustOnly,
+    // Some intrinsic functions have a C implementation provided by LLVM's
+    // compiler-rt builtins library. Build them from the LLVM source included
+    // with Rust.
+    BuildLLVMFuncs,
+    // Similar to BuildLLVMFuncs, but specify a path to an existing library
+    // containing LLVM's compiler-rt builtins instead of compiling them.
+    LinkLLVMBuiltinsLib(String),
+}
+
+impl<'de> Deserialize<'de> for CompilerBuiltins {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: Deserializer<'de>,
+    {
+        Ok(match Deserialize::deserialize(deserializer)? {
+            StringOrBool::Bool(false) => Self::BuildRustOnly,
+            StringOrBool::Bool(true) => Self::BuildLLVMFuncs,
+            StringOrBool::String(path) => Self::LinkLLVMBuiltinsLib(path),
+        })
+    }
+}
+
 #[derive(Copy, Clone, Default, Debug, Eq, PartialEq)]
 pub enum DebuginfoLevel {
     #[default]
diff --git a/src/bootstrap/src/core/config/tests.rs b/src/bootstrap/src/core/config/tests.rs
index 50eba12aba7..e93525fbd09 100644
--- a/src/bootstrap/src/core/config/tests.rs
+++ b/src/bootstrap/src/core/config/tests.rs
@@ -17,7 +17,7 @@ use crate::core::build_steps::clippy::{LintConfig, get_clippy_rules_in_order};
 use crate::core::build_steps::llvm;
 use crate::core::build_steps::llvm::LLVM_INVALIDATION_PATHS;
 use crate::core::config::toml::TomlConfig;
-use crate::core::config::{LldMode, Target, TargetSelection};
+use crate::core::config::{CompilerBuiltins, LldMode, StringOrBool, Target, TargetSelection};
 use crate::utils::tests::git::git_test;
 
 pub(crate) fn parse(config: &str) -> Config {
@@ -183,7 +183,11 @@ runner = "x86_64-runner"
     );
     assert_eq!(config.gdb, Some("bar".into()), "setting string value with quotes");
     assert!(!config.deny_warnings, "setting boolean value");
-    assert!(config.optimized_compiler_builtins, "setting boolean value");
+    assert_eq!(
+        config.optimized_compiler_builtins,
+        CompilerBuiltins::BuildLLVMFuncs,
+        "setting boolean value"
+    );
     assert_eq!(
         config.tools,
         Some(["cargo".to_string()].into_iter().collect()),
@@ -212,7 +216,7 @@ runner = "x86_64-runner"
     let darwin = TargetSelection::from_user("aarch64-apple-darwin");
     let darwin_values = Target {
         runner: Some("apple".into()),
-        optimized_compiler_builtins: Some(false),
+        optimized_compiler_builtins: Some(CompilerBuiltins::BuildRustOnly),
         ..Default::default()
     };
     assert_eq!(
diff --git a/src/bootstrap/src/core/config/toml/build.rs b/src/bootstrap/src/core/config/toml/build.rs
index 728367b3972..25c19f1070a 100644
--- a/src/bootstrap/src/core/config/toml/build.rs
+++ b/src/bootstrap/src/core/config/toml/build.rs
@@ -11,7 +11,7 @@ use std::collections::HashMap;
 use serde::{Deserialize, Deserializer};
 
 use crate::core::config::toml::ReplaceOpt;
-use crate::core::config::{Merge, StringOrBool};
+use crate::core::config::{CompilerBuiltins, Merge, StringOrBool};
 use crate::{HashSet, PathBuf, define_config, exit};
 
 define_config! {
@@ -65,7 +65,7 @@ define_config! {
         // NOTE: only parsed by bootstrap.py, `--feature build-metrics` enables metrics unconditionally
         metrics: Option<bool> = "metrics",
         android_ndk: Option<PathBuf> = "android-ndk",
-        optimized_compiler_builtins: Option<bool> = "optimized-compiler-builtins",
+        optimized_compiler_builtins: Option<CompilerBuiltins> = "optimized-compiler-builtins",
         jobs: Option<u32> = "jobs",
         compiletest_diff_tool: Option<String> = "compiletest-diff-tool",
         compiletest_allow_stage0: Option<bool> = "compiletest-allow-stage0",
diff --git a/src/bootstrap/src/core/config/toml/rust.rs b/src/bootstrap/src/core/config/toml/rust.rs
index 3dab8d1d96d..c54df456d52 100644
--- a/src/bootstrap/src/core/config/toml/rust.rs
+++ b/src/bootstrap/src/core/config/toml/rust.rs
@@ -269,9 +269,9 @@ pub fn check_incompatible_options_for_ci_rustc(
     err!(current_profiler, profiler, "build");
 
     let current_optimized_compiler_builtins =
-        current_config_toml.build.as_ref().and_then(|b| b.optimized_compiler_builtins);
+        current_config_toml.build.as_ref().and_then(|b| b.optimized_compiler_builtins.clone());
     let optimized_compiler_builtins =
-        ci_config_toml.build.as_ref().and_then(|b| b.optimized_compiler_builtins);
+        ci_config_toml.build.as_ref().and_then(|b| b.optimized_compiler_builtins.clone());
     err!(current_optimized_compiler_builtins, optimized_compiler_builtins, "build");
 
     // We always build the in-tree compiler on cross targets, so we only care
@@ -415,6 +415,10 @@ pub(crate) fn parse_codegen_backends(
         };
         found_backends.push(backend);
     }
+    if found_backends.is_empty() {
+        eprintln!("ERROR: `{section}.codegen-backends` should not be set to `[]`");
+        exit!(1);
+    }
     found_backends
 }
 
diff --git a/src/bootstrap/src/core/config/toml/target.rs b/src/bootstrap/src/core/config/toml/target.rs
index 2c06fd083a8..020602e6a19 100644
--- a/src/bootstrap/src/core/config/toml/target.rs
+++ b/src/bootstrap/src/core/config/toml/target.rs
@@ -11,7 +11,9 @@
 
 use serde::{Deserialize, Deserializer};
 
-use crate::core::config::{LlvmLibunwind, Merge, ReplaceOpt, SplitDebuginfo, StringOrBool};
+use crate::core::config::{
+    CompilerBuiltins, LlvmLibunwind, Merge, ReplaceOpt, SplitDebuginfo, StringOrBool,
+};
 use crate::{CodegenBackendKind, HashSet, PathBuf, define_config, exit};
 
 define_config! {
@@ -39,7 +41,7 @@ define_config! {
         no_std: Option<bool> = "no-std",
         codegen_backends: Option<Vec<String>> = "codegen-backends",
         runner: Option<String> = "runner",
-        optimized_compiler_builtins: Option<bool> = "optimized-compiler-builtins",
+        optimized_compiler_builtins: Option<CompilerBuiltins> = "optimized-compiler-builtins",
         jemalloc: Option<bool> = "jemalloc",
     }
 }
@@ -71,7 +73,7 @@ pub struct Target {
     pub runner: Option<String>,
     pub no_std: bool,
     pub codegen_backends: Option<Vec<CodegenBackendKind>>,
-    pub optimized_compiler_builtins: Option<bool>,
+    pub optimized_compiler_builtins: Option<CompilerBuiltins>,
     pub jemalloc: Option<bool>,
 }
 
diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs
index de7cada93f2..099ec488397 100644
--- a/src/bootstrap/src/core/sanity.rs
+++ b/src/bootstrap/src/core/sanity.rs
@@ -18,7 +18,7 @@ use crate::builder::Builder;
 use crate::builder::Kind;
 #[cfg(not(test))]
 use crate::core::build_steps::tool;
-use crate::core::config::Target;
+use crate::core::config::{CompilerBuiltins, Target};
 use crate::utils::exec::command;
 use crate::{Build, Subcommand};
 
@@ -34,6 +34,7 @@ pub struct Finder {
 // Targets can be removed from this list once they are present in the stage0 compiler (usually by updating the beta compiler of the bootstrap).
 const STAGE0_MISSING_TARGETS: &[&str] = &[
     "armv7a-vex-v5",
+    "riscv64a23-unknown-linux-gnu",
     // just a dummy comment so the list doesn't get onelined
     "aarch64_be-unknown-hermit",
     "aarch64_be-unknown-none-softfloat",
@@ -330,7 +331,8 @@ than building it.
 
         // compiler-rt c fallbacks for wasm cannot be built with gcc
         if target.contains("wasm")
-            && (build.config.optimized_compiler_builtins(*target)
+            && (*build.config.optimized_compiler_builtins(*target)
+                != CompilerBuiltins::BuildRustOnly
                 || build.config.rust_std_features.contains("compiler-builtins-c"))
         {
             let cc_tool = build.cc_tool(*target);
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index ec7edbf7531..b8ee83b20e4 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -1950,6 +1950,20 @@ impl Build {
         t!(fs::remove_dir_all(dir))
     }
 
+    /// Make sure that `dir` will be an empty existing directory after this function ends.
+    /// If it existed before, it will be first deleted.
+    fn clear_dir(&self, dir: &Path) {
+        if self.config.dry_run() {
+            return;
+        }
+
+        #[cfg(feature = "tracing")]
+        let _span = trace_io!("dir-clear", ?dir);
+
+        let _ = std::fs::remove_dir_all(dir);
+        self.create_dir(dir);
+    }
+
     fn read_dir(&self, dir: &Path) -> impl Iterator<Item = fs::DirEntry> {
         let iter = match fs::read_dir(dir) {
             Ok(v) => v,
diff --git a/src/bootstrap/src/utils/build_stamp.rs b/src/bootstrap/src/utils/build_stamp.rs
index 6c79385190e..4c35388a181 100644
--- a/src/bootstrap/src/utils/build_stamp.rs
+++ b/src/bootstrap/src/utils/build_stamp.rs
@@ -136,13 +136,13 @@ pub fn codegen_backend_stamp(
 }
 
 /// Cargo's output path for the standard library in a given stage, compiled
-/// by a particular compiler for the specified target.
+/// by a particular `build_compiler` for the specified `target`.
 pub fn libstd_stamp(
     builder: &Builder<'_>,
-    compiler: Compiler,
+    build_compiler: Compiler,
     target: TargetSelection,
 ) -> BuildStamp {
-    BuildStamp::new(&builder.cargo_out(compiler, Mode::Std, target)).with_prefix("libstd")
+    BuildStamp::new(&builder.cargo_out(build_compiler, Mode::Std, target)).with_prefix("libstd")
 }
 
 /// Cargo's output path for librustc in a given stage, compiled by a particular
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index 4fb5891ed18..606d88d3db4 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -516,4 +516,19 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Info,
         summary: "Build/check now supports forwarding `--timings` flag to cargo.",
     },
+    ChangeInfo {
+        change_id: 145472,
+        severity: ChangeSeverity::Warning,
+        summary: "It is no longer possible to `x dist` or `x install` with stage 0. All dist and install commands have to be on stage 1+.",
+    },
+    ChangeInfo {
+        change_id: 143689,
+        severity: ChangeSeverity::Info,
+        summary: "The `optimized-compiler-builtins` option now accepts a path to an existing compiler-rt builtins library.",
+    },
+    ChangeInfo {
+        change_id: 145876,
+        severity: ChangeSeverity::Info,
+        summary: "It is now possible to `check/build/dist` the standard stage 0 library if you use a stage0 rustc built from in-tree sources. This is useful for quickly cross-compiling the standard library. You have to enable build.local-rebuild for this to work.",
+    },
 ];
diff --git a/src/bootstrap/src/utils/exec.rs b/src/bootstrap/src/utils/exec.rs
index 9a536f75ab7..e09f3086b77 100644
--- a/src/bootstrap/src/utils/exec.rs
+++ b/src/bootstrap/src/utils/exec.rs
@@ -264,8 +264,11 @@ impl<'a> BootstrapCommand {
         self
     }
 
-    pub fn do_not_cache(&mut self) -> &mut Self {
-        self.should_cache = false;
+    /// Cache the command. If it will be executed multiple times with the exact same arguments
+    /// and environment variables in the same bootstrap invocation, the previous result will be
+    /// loaded from memory.
+    pub fn cached(&mut self) -> &mut Self {
+        self.should_cache = true;
         self
     }
 
@@ -425,7 +428,7 @@ impl From<Command> for BootstrapCommand {
     fn from(command: Command) -> Self {
         let program = command.get_program().to_owned();
         Self {
-            should_cache: true,
+            should_cache: false,
             command,
             failure_behavior: BehaviorOnFailure::Exit,
             run_in_dry_run: false,
diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs
index 451482717b6..e802c0214dd 100644
--- a/src/bootstrap/src/utils/helpers.rs
+++ b/src/bootstrap/src/utils/helpers.rs
@@ -510,6 +510,8 @@ pub fn check_cfg_arg(name: &str, values: Option<&[&str]>) -> String {
 #[track_caller]
 pub fn git(source_dir: Option<&Path>) -> BootstrapCommand {
     let mut git = command("git");
+    // git commands are almost always read-only, so cache them by default
+    git.cached();
 
     if let Some(source_dir) = source_dir {
         git.current_dir(source_dir);
diff --git a/src/bootstrap/src/utils/tests/mod.rs b/src/bootstrap/src/utils/tests/mod.rs
index 983680b0385..3332187e2a8 100644
--- a/src/bootstrap/src/utils/tests/mod.rs
+++ b/src/bootstrap/src/utils/tests/mod.rs
@@ -31,6 +31,10 @@ impl TestCtx {
         Self { directory }
     }
 
+    pub fn dir(&self) -> &Path {
+        self.directory.path()
+    }
+
     /// Starts a new invocation of bootstrap that executes `kind` as its top level command
     /// (i.e. `x <kind>`). Returns a builder that configures the created config through CLI flags.
     pub fn config(&self, kind: &str) -> ConfigBuilder {
diff --git a/src/build_helper/src/npm.rs b/src/build_helper/src/npm.rs
index 86cf6183bd0..5a7df0999bd 100644
--- a/src/build_helper/src/npm.rs
+++ b/src/build_helper/src/npm.rs
@@ -27,7 +27,7 @@ pub fn install(src_root_path: &Path, out_dir: &Path, npm: &Path) -> Result<PathB
     }
     // disable a bunch of things we don't want.
     // this makes tidy output less noisy, and also significantly improves runtime
-    // of repeated tidy invokations.
+    // of repeated tidy invocations.
     cmd.args(&["--audit=false", "--save=false", "--fund=false"]);
     cmd.current_dir(out_dir);
     let exit_status = cmd.spawn()?.wait()?;
diff --git a/src/ci/citool/src/analysis.rs b/src/ci/citool/src/analysis.rs
index 62974be2dbe..8ba8f1ab564 100644
--- a/src/ci/citool/src/analysis.rs
+++ b/src/ci/citool/src/analysis.rs
@@ -75,7 +75,7 @@ fn format_build_step_diffs(current: &BuildStep, parent: &BuildStep) -> String {
         }
     }
 
-    fn get_steps(step: &BuildStep) -> Vec<StepByName> {
+    fn get_steps(step: &BuildStep) -> Vec<StepByName<'_>> {
         step.linearize_steps().into_iter().map(|v| StepByName(v)).collect()
     }
 
diff --git a/src/ci/citool/src/test_dashboard.rs b/src/ci/citool/src/test_dashboard.rs
index 8fbd0d3f200..c9de38852e5 100644
--- a/src/ci/citool/src/test_dashboard.rs
+++ b/src/ci/citool/src/test_dashboard.rs
@@ -33,7 +33,7 @@ fn write_page<T: Template>(dir: &Path, name: &str, template: &T) -> anyhow::Resu
     Ok(())
 }
 
-fn gather_test_suites(job_metrics: &HashMap<JobName, JobMetrics>) -> TestSuites {
+fn gather_test_suites(job_metrics: &HashMap<JobName, JobMetrics>) -> TestSuites<'_> {
     struct CoarseTestSuite<'a> {
         tests: BTreeMap<String, Test<'a>>,
     }
diff --git a/src/ci/citool/src/utils.rs b/src/ci/citool/src/utils.rs
index 0367d349a1e..3176cb62f60 100644
--- a/src/ci/citool/src/utils.rs
+++ b/src/ci/citool/src/utils.rs
@@ -31,6 +31,6 @@ where
 }
 
 /// Normalizes Windows-style path delimiters to Unix-style paths.
-pub fn normalize_path_delimiters(name: &str) -> Cow<str> {
+pub fn normalize_path_delimiters(name: &str) -> Cow<'_, str> {
     if name.contains("\\") { name.replace('\\', "/").into() } else { name.into() }
 }
diff --git a/src/ci/docker/host-x86_64/dist-aarch64-windows-gnullvm/Dockerfile b/src/ci/docker/host-x86_64/dist-aarch64-windows-gnullvm/Dockerfile
index cdbc1cda025..0bb51af817a 100644
--- a/src/ci/docker/host-x86_64/dist-aarch64-windows-gnullvm/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-aarch64-windows-gnullvm/Dockerfile
@@ -26,23 +26,10 @@ ENV CC_aarch64_pc_windows_gnullvm=aarch64-w64-mingw32-clang \
 
 ENV HOST=aarch64-pc-windows-gnullvm
 
-# We are bootstrapping this target and cannot use previously built artifacts.
-# Without this option Clang is given `"-I/checkout/obj/build/aarch64-pc-windows-gnullvm/ci-llvm/include"`
-# despite no such directory existing:
-# $ ls obj/dist-windows-gnullvm/build/aarch64-pc-windows-gnullvm/ -1
-# llvm
-# stage2
-ENV NO_DOWNLOAD_CI_LLVM 1
-
 ENV RUST_CONFIGURE_ARGS \
-    --enable-extended \
+    --enable-full-tools \
     --enable-profiler \
     --enable-sanitizers \
-    --disable-docs \
-    --set llvm.download-ci-llvm=false \
-    --set rust.llvm-tools=false
-# LLVM cross tools are not installed into expected location so copying fails.
-# Probably will solve itself once this target can host itself on Windows.
-# --enable-full-tools \
+    --disable-docs
 
 ENV SCRIPT python3 ../x.py dist --host $HOST --target $HOST
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-windows-gnullvm/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-windows-gnullvm/Dockerfile
index 1ee3951beb5..da0c065c854 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-windows-gnullvm/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-windows-gnullvm/Dockerfile
@@ -28,23 +28,10 @@ ENV CC_i686_pc_windows_gnullvm=i686-w64-mingw32-clang \
 ENV HOST=x86_64-pc-windows-gnullvm
 ENV TARGETS=i686-pc-windows-gnullvm,x86_64-pc-windows-gnullvm
 
-# We are bootstrapping this target and cannot use previously built artifacts.
-# Without this option Clang is given `"-I/checkout/obj/build/aarch64-pc-windows-gnullvm/ci-llvm/include"`
-# despite no such directory existing:
-# $ ls obj/dist-windows-gnullvm/build/aarch64-pc-windows-gnullvm/ -1
-# llvm
-# stage2
-ENV NO_DOWNLOAD_CI_LLVM 1
-
 ENV RUST_CONFIGURE_ARGS \
-    --enable-extended \
+    --enable-full-tools \
     --enable-profiler \
     --enable-sanitizers \
-    --disable-docs \
-    --set llvm.download-ci-llvm=false \
-    --set rust.llvm-tools=false
-# LLVM cross tools are not installed into expected location so copying fails.
-# Probably will solve itself once these targets can host themselves on Windows.
-# --enable-full-tools \
+    --disable-docs
 
 ENV SCRIPT python3 ../x.py dist --host $HOST --target $TARGETS
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
index b97568b0819..5052d86f0ac 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
@@ -38,11 +38,15 @@ ENV RUST_CONFIGURE_ARGS \
       --build=x86_64-unknown-linux-gnu \
       --enable-debug \
       --enable-lld \
+      --set rust.debuginfo-level-tests=1 \
       --set llvm.use-linker=lld \
       --set target.x86_64-unknown-linux-gnu.linker=clang \
       --set target.x86_64-unknown-linux-gnu.cc=clang \
       --set target.x86_64-unknown-linux-gnu.cxx=clang++
 
+# This job checks:
+# - That ui tests can be built with `-Cdebuginfo=1`
+
 # This job appears to be checking two separate things:
 # - That we can build the compiler with `--enable-debug`
 #   (without necessarily testing the result).
@@ -51,4 +55,5 @@ ENV RUST_CONFIGURE_ARGS \
 
 ENV SCRIPT \
   python3 ../x.py --stage 2 build && \
+  python3 ../x.py --stage 2 test tests/ui && \
   python3 ../x.py --stage 2 test tests/run-make
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
index 98fd31a22e9..5bafd89cfd9 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
@@ -33,9 +33,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-# We are disabling CI LLVM since distcheck is an offline build.
-ENV NO_DOWNLOAD_CI_LLVM 1
+# Make distcheck builds faster
+ENV DISTCHECK_CONFIGURE_ARGS "--enable-sccache"
 
-ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --set rust.omit-git-hash=false
-ENV SCRIPT python3 ../x.py --stage 2 test distcheck
-ENV DIST_SRC 1
+ENV SCRIPT python3 ../x.py test distcheck
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index 409d2cba821..35b9456d37d 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -104,10 +104,10 @@ jobs:
 # These jobs automatically inherit envs.pr, to avoid repeating it in each job
 # definition.
 #
-# PR CI jobs will be automatically registered as Auto CI jobs or overriden. When
+# PR CI jobs will be automatically registered as Auto CI jobs or overridden. When
 # automatically registered, the PR CI job configuration will be copied as an
-# Auto CI job but with `continue_on_error` overriden to `false` (to fail-fast).
-# When overriden, `citool` will check for equivalence between the PR and CI job
+# Auto CI job but with `continue_on_error` overridden to `false` (to fail-fast).
+# When overridden, `citool` will check for equivalence between the PR and CI job
 # of the same name modulo `continue_on_error` and `env`.
 pr:
   - name: pr-check-1
@@ -166,7 +166,7 @@ optional:
 #
 # Auto jobs may not specify `continue_on_error: true`, and thus will fail-fast.
 #
-# Unless explicitly overriden, PR CI jobs will be automatically registered as
+# Unless explicitly overridden, PR CI jobs will be automatically registered as
 # Auto CI jobs.
 auto:
   #############################
diff --git a/src/ci/scripts/free-disk-space-linux.sh b/src/ci/scripts/free-disk-space-linux.sh
index 32649fe0d9b..ac3c9cfb28b 100755
--- a/src/ci/scripts/free-disk-space-linux.sh
+++ b/src/ci/scripts/free-disk-space-linux.sh
@@ -221,10 +221,13 @@ cleanPackages() {
         )
     fi
 
-    sudo apt-get -qq remove -y --fix-missing "${packages[@]}"
+    WAIT_DPKG_LOCK="-o DPkg::Lock::Timeout=60"
+    sudo apt-get ${WAIT_DPKG_LOCK} -qq remove -y --fix-missing "${packages[@]}"
 
-    sudo apt-get autoremove -y || echo "::warning::The command [sudo apt-get autoremove -y] failed"
-    sudo apt-get clean || echo "::warning::The command [sudo apt-get clean] failed failed"
+    sudo apt-get ${WAIT_DPKG_LOCK} autoremove -y \
+        || echo "::warning::The command [sudo apt-get autoremove -y] failed"
+    sudo apt-get ${WAIT_DPKG_LOCK} clean \
+        || echo "::warning::The command [sudo apt-get clean] failed"
 }
 
 # Remove Docker images.
diff --git a/src/doc/nomicon b/src/doc/nomicon
-Subproject 3ff384320598bbe8d8cfe5cb8f18f78a3a3e6b1
+Subproject 57ed4473660565d9357fcae176b358d7e8724eb
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 59b8af811886313577615c2cf0e045f01faed88
+Subproject 89f67b3c1b904cbcd9ed55e443d6fc67c8ca276
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject adc1f3b9012ad3255eea2054ca30596a953d053
+Subproject ad27f82c18464525c761a4a8db2e01785da59e1
diff --git a/src/doc/rustc-dev-guide/.github/workflows/rustc-pull.yml b/src/doc/rustc-dev-guide/.github/workflows/rustc-pull.yml
index 04d6469aeaa..5ff3118960d 100644
--- a/src/doc/rustc-dev-guide/.github/workflows/rustc-pull.yml
+++ b/src/doc/rustc-dev-guide/.github/workflows/rustc-pull.yml
@@ -3,8 +3,8 @@ name: rustc-pull
 on:
   workflow_dispatch:
   schedule:
-    # Run at 04:00 UTC every Monday and Thursday
-    - cron: '0 4 * * 1,4'
+    # Run at 04:00 UTC every Monday
+    - cron: '0 4 * * 1'
 
 jobs:
   pull:
diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version
index 6ec700b9b4d..f412399cc8c 100644
--- a/src/doc/rustc-dev-guide/rust-version
+++ b/src/doc/rustc-dev-guide/rust-version
@@ -1 +1 @@
-6bcdcc73bd11568fd85f5a38b58e1eda054ad1cd
+a1dbb443527bd126452875eb5d5860c1d001d761
diff --git a/src/doc/rustc-dev-guide/src/SUMMARY.md b/src/doc/rustc-dev-guide/src/SUMMARY.md
index 025a078ae5b..a1612738537 100644
--- a/src/doc/rustc-dev-guide/src/SUMMARY.md
+++ b/src/doc/rustc-dev-guide/src/SUMMARY.md
@@ -103,6 +103,7 @@
 	- [The `rustdoc-json` test suite](./rustdoc-internals/rustdoc-json-test-suite.md)
 - [GPU offload internals](./offload/internals.md)
     - [Installation](./offload/installation.md)
+    - [Usage](./offload/usage.md)
 - [Autodiff internals](./autodiff/internals.md)
     - [Installation](./autodiff/installation.md)
     - [How to debug](./autodiff/debugging.md)
diff --git a/src/doc/rustc-dev-guide/src/about-this-guide.md b/src/doc/rustc-dev-guide/src/about-this-guide.md
index 057e4a4ccee..f3957724967 100644
--- a/src/doc/rustc-dev-guide/src/about-this-guide.md
+++ b/src/doc/rustc-dev-guide/src/about-this-guide.md
@@ -74,7 +74,6 @@ You might also find the following sites useful:
   of the team procedures, active working groups, and the team calendar.
 - [std-dev-guide] -- a similar guide for developing the standard library.
 - [The t-compiler zulip][z]
-- `#contribute` and `#wg-rustup` on [Discord](https://discord.gg/rust-lang).
 - The [Rust Internals forum][rif], a place to ask questions and
   discuss Rust's internals
 - The [Rust reference][rr], even though it doesn't specifically talk about
diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md b/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md
index da425d8d39b..bfd75ebda40 100644
--- a/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md
+++ b/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md
@@ -23,7 +23,7 @@ Note that this documentation mostly covers user-facing information. See
 
 ### Overview
 
-- Stage 0: the pre-compiled compiler
+- Stage 0: the pre-compiled compiler and standard library
 - Stage 1: from current code, by an earlier compiler
 - Stage 2: the truly current compiler
 - Stage 3: the same-result test
@@ -192,7 +192,7 @@ include, but are not limited to:
   artifacts'). If you're working on the standard library, this is normally the
   test command you want.
 - `./x build --stage 0` means to build with the stage0 `rustc`.
-- `./x doc --stage 0` means to document using the stage0 `rustdoc`.
+- `./x doc --stage 1` means to document using the stage0 `rustdoc`.
 
 #### Examples of what *not* to do
 
@@ -211,7 +211,7 @@ include, but are not limited to:
 In short, _stage 0 uses the `stage0` compiler to create `stage0` artifacts which
 will later be uplifted to be the stage1 compiler_.
 
-In each stage, two major steps are performed:
+In each stage besides 0, two major steps are performed:
 
 1. `std` is compiled by the stage N compiler.
 2. That `std` is linked to programs built by the stage N compiler, including the
diff --git a/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md b/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md
index 1b6b87e4c8d..1693432b90d 100644
--- a/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md
+++ b/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md
@@ -20,7 +20,7 @@ explanations should help users understand why their code cannot be accepted by
 the compiler. Rust prides itself on helpful error messages and long-form
 explanations are no exception. However, before error explanations are
 overhauled[^new-explanations] it is a bit open as to how exactly they should be
-written, as always: ask your reviewer or ask around on the Rust Discord or Zulip.
+written, as always: ask your reviewer or ask around on the Rust Zulip.
 
 [^new-explanations]: See the draft RFC [here][new-explanations-rfc].
 
diff --git a/src/doc/rustc-dev-guide/src/getting-started.md b/src/doc/rustc-dev-guide/src/getting-started.md
index 04d2e37732f..87e26d37968 100644
--- a/src/doc/rustc-dev-guide/src/getting-started.md
+++ b/src/doc/rustc-dev-guide/src/getting-started.md
@@ -11,7 +11,6 @@ quick guide for the most useful things. For more information, [see this
 chapter on how to build and run the compiler](./building/how-to-build-and-run.md).
 
 [internals]: https://internals.rust-lang.org
-[rust-discord]: http://discord.gg/rust-lang
 [rust-zulip]: https://rust-lang.zulipchat.com
 [coc]: https://www.rust-lang.org/policies/code-of-conduct
 [walkthrough]: ./walkthrough.md
@@ -20,8 +19,7 @@ chapter on how to build and run the compiler](./building/how-to-build-and-run.md
 ## Asking Questions
 
 If you have questions, please make a post on the [Rust Zulip server][rust-zulip] or
-[internals.rust-lang.org][internals]. If you are contributing to Rustup, be aware they are not on
-Zulip - you can ask questions in `#wg-rustup` [on Discord][rust-discord].
+[internals.rust-lang.org][internals].
 See the [list of teams and working groups][governance] and [the Community page][community] on the
 official website for more resources.
 
@@ -30,19 +28,23 @@ official website for more resources.
 
 As a reminder, all contributors are expected to follow our [Code of Conduct][coc].
 
-The compiler team (or `t-compiler`) usually hangs out in Zulip [in this
-"stream"][z]; it will be easiest to get questions answered there.
+The compiler team (or `t-compiler`) usually hangs out in Zulip in
+[the #t-compiler channel][z-t-compiler];
+questions about how the compiler works can go in [#t-compiler/help][z-help].
 
-[z]: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler
+[z-t-compiler]: https://rust-lang.zulipchat.com/#narrow/channel/131828-t-compiler
+[z-help]: https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp
 
 **Please ask questions!** A lot of people report feeling that they are "wasting
-expert time", but nobody on `t-compiler` feels this way. Contributors are
+expert's time", but nobody on `t-compiler` feels this way. Contributors are
 important to us.
 
 Also, if you feel comfortable, prefer public topics, as this means others can
 see the questions and answers, and perhaps even integrate them back into this
 guide :)
 
+**Tip**: If you're not a native English speaker and feel unsure about writing, try using a translator to help. But avoid using LLM tools that generate long, complex words. In daily teamwork, **simple and clear words** are best for easy understanding. Even small typos or grammar mistakes can make you seem more human, and people connect better with humans.
+
 ### Experts
 
 Not all `t-compiler` members are experts on all parts of `rustc`; it's a
@@ -162,15 +164,12 @@ incredibly helpful:
 - [Triaging issues][triage]: categorizing, replicating, and minimizing issues is very helpful to the Rust maintainers.
 - [Working groups][wg]: there are a bunch of working groups on a wide variety
   of rust-related things.
-- Answer questions in the _Get Help!_ channels on the [Rust Discord
-  server][rust-discord], on [users.rust-lang.org][users], or on
-  [StackOverflow][so].
+- Answer questions on [users.rust-lang.org][users], or on [Stack Overflow][so].
 - Participate in the [RFC process](https://github.com/rust-lang/rfcs).
 - Find a [requested community library][community-library], build it, and publish
   it to [Crates.io](http://crates.io). Easier said than done, but very, very
   valuable!
 
-[rust-discord]: https://discord.gg/rust-lang
 [users]: https://users.rust-lang.org/
 [so]: http://stackoverflow.com/questions/tagged/rust
 [community-library]: https://github.com/rust-lang/rfcs/labels/A-community-library
diff --git a/src/doc/rustc-dev-guide/src/git.md b/src/doc/rustc-dev-guide/src/git.md
index 447c6fd4546..8f0511a4548 100644
--- a/src/doc/rustc-dev-guide/src/git.md
+++ b/src/doc/rustc-dev-guide/src/git.md
@@ -338,13 +338,13 @@ your fork with `git push --force-with-lease`.
 
 ### Keeping things up to date
 
-The above section on [Rebasing](#rebasing) is a specific
+The [above section](#rebasing) is a specific
 guide on rebasing work and dealing with merge conflicts.
 Here is some general advice about how to keep your local repo
 up-to-date with upstream changes:
 
 Using `git pull upstream master` while on your local master branch regularly
-will keep it up-to-date. You will also want to rebase your feature branches
+will keep it up-to-date. You will also want to keep your feature branches
 up-to-date as well. After pulling, you can checkout the feature branches
 and rebase them:
 
diff --git a/src/doc/rustc-dev-guide/src/img/coverage-branch-counting-01.png b/src/doc/rustc-dev-guide/src/img/coverage-branch-counting-01.png
index c445f3552a6..7c6c845f2cb 100644
--- a/src/doc/rustc-dev-guide/src/img/coverage-branch-counting-01.png
+++ b/src/doc/rustc-dev-guide/src/img/coverage-branch-counting-01.png
Binary files differdiff --git a/src/doc/rustc-dev-guide/src/img/dataflow-graphviz-example.png b/src/doc/rustc-dev-guide/src/img/dataflow-graphviz-example.png
index 718411a8c42..7baa37e4323 100644
--- a/src/doc/rustc-dev-guide/src/img/dataflow-graphviz-example.png
+++ b/src/doc/rustc-dev-guide/src/img/dataflow-graphviz-example.png
Binary files differdiff --git a/src/doc/rustc-dev-guide/src/img/github-cli.png b/src/doc/rustc-dev-guide/src/img/github-cli.png
index c3b0e7707eb..88ba95f90a8 100644
--- a/src/doc/rustc-dev-guide/src/img/github-cli.png
+++ b/src/doc/rustc-dev-guide/src/img/github-cli.png
Binary files differdiff --git a/src/doc/rustc-dev-guide/src/img/github-whitespace-changes.png b/src/doc/rustc-dev-guide/src/img/github-whitespace-changes.png
index 9a19a10aace..e235a30b33e 100644
--- a/src/doc/rustc-dev-guide/src/img/github-whitespace-changes.png
+++ b/src/doc/rustc-dev-guide/src/img/github-whitespace-changes.png
Binary files differdiff --git a/src/doc/rustc-dev-guide/src/img/llvm-cov-show-01.png b/src/doc/rustc-dev-guide/src/img/llvm-cov-show-01.png
index 35f04594347..ce4dec128b6 100644
--- a/src/doc/rustc-dev-guide/src/img/llvm-cov-show-01.png
+++ b/src/doc/rustc-dev-guide/src/img/llvm-cov-show-01.png
Binary files differdiff --git a/src/doc/rustc-dev-guide/src/img/other-peoples-commits.png b/src/doc/rustc-dev-guide/src/img/other-peoples-commits.png
index e4fc2c7972e..0c949d8844d 100644
--- a/src/doc/rustc-dev-guide/src/img/other-peoples-commits.png
+++ b/src/doc/rustc-dev-guide/src/img/other-peoples-commits.png
Binary files differdiff --git a/src/doc/rustc-dev-guide/src/img/rustbot-submodules.png b/src/doc/rustc-dev-guide/src/img/rustbot-submodules.png
index c2e6937cbeb..c099fdfcb46 100644
--- a/src/doc/rustc-dev-guide/src/img/rustbot-submodules.png
+++ b/src/doc/rustc-dev-guide/src/img/rustbot-submodules.png
Binary files differdiff --git a/src/doc/rustc-dev-guide/src/img/submodule-conflicts.png b/src/doc/rustc-dev-guide/src/img/submodule-conflicts.png
index e90a6bbe8fd..5d4caf0b142 100644
--- a/src/doc/rustc-dev-guide/src/img/submodule-conflicts.png
+++ b/src/doc/rustc-dev-guide/src/img/submodule-conflicts.png
Binary files differdiff --git a/src/doc/rustc-dev-guide/src/img/wpa-initial-memory.png b/src/doc/rustc-dev-guide/src/img/wpa-initial-memory.png
index b6020667ef0..177d92c794c 100644
--- a/src/doc/rustc-dev-guide/src/img/wpa-initial-memory.png
+++ b/src/doc/rustc-dev-guide/src/img/wpa-initial-memory.png
Binary files differdiff --git a/src/doc/rustc-dev-guide/src/img/wpa-stack.png b/src/doc/rustc-dev-guide/src/img/wpa-stack.png
index 29eb5a54b5d..a4a71358ac1 100644
--- a/src/doc/rustc-dev-guide/src/img/wpa-stack.png
+++ b/src/doc/rustc-dev-guide/src/img/wpa-stack.png
Binary files differdiff --git a/src/doc/rustc-dev-guide/src/macro-expansion.md b/src/doc/rustc-dev-guide/src/macro-expansion.md
index 54d6d2b4e81..96f12b76416 100644
--- a/src/doc/rustc-dev-guide/src/macro-expansion.md
+++ b/src/doc/rustc-dev-guide/src/macro-expansion.md
@@ -517,8 +517,9 @@ We use these items in macro parser:
   are about to ask the MBE parser to parse. We will consume the raw stream of
   tokens and output a binding of metavariables to corresponding token trees.
   The parsing session can be used to report parser errors.
-- a `matcher` variable is a sequence of [`MatcherLoc`]s that we want to match
-  the token stream against. They're converted from token trees before matching.
+- a `matcher` variable is a sequence of [`MatcherLoc`]s that we want to match the token stream
+  against. They're converted from the original token trees in the macro's definition before
+  matching.
 
 [`MatcherLoc`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_expand/mbe/macro_parser/enum.MatcherLoc.html
 
@@ -544,41 +545,26 @@ The full interface is defined [here][code_parse_int].
 The macro parser does pretty much exactly the same as a normal regex parser
 with one exception: in order to parse different types of metavariables, such as
 `ident`, `block`, `expr`, etc., the macro parser must call back to the normal
-Rust parser. Both the definition and invocation of macros are parsed using
-the parser in a process which is non-intuitively self-referential. 
-
-The code to parse macro _definitions_ is in
-[`compiler/rustc_expand/src/mbe/macro_rules.rs`][code_mr]. It defines the
-pattern for matching a macro definition as `$( $lhs:tt => $rhs:tt );+`. In
-other words, a `macro_rules` definition should have in its body at least one
-occurrence of a token tree followed by `=>` followed by another token tree.
-When the compiler comes to a `macro_rules` definition, it uses this pattern to
-match the two token trees per the rules of the definition of the macro, _thereby
-utilizing the macro parser itself_. In our example definition, the
-metavariable `$lhs` would match the patterns of both arms: `(print
-$mvar:ident)` and `(print twice $mvar:ident)`. And `$rhs` would match the
-bodies of both arms: `{ println!("{}", $mvar); }` and `{ println!("{}", $mvar);
-println!("{}", $mvar); }`. The parser keeps this knowledge around for when it
-needs to expand a macro invocation.
-
-When the compiler comes to a macro invocation, it parses that invocation using
-a NFA-based macro parser described above. However, the matcher variable
-used is the first token tree (`$lhs`) extracted from the arms of the macro
-_definition_. Using our example, we would try to match the token stream `print
-foo` from the invocation against the matchers `print $mvar:ident` and `print
-twice $mvar:ident` that we previously extracted from the definition. The
-algorithm is exactly the same, but when the macro parser comes to a place in the
-current matcher where it needs to match a _non-terminal_ (e.g. `$mvar:ident`),
-it calls back to the normal Rust parser to get the contents of that
-non-terminal. In this case, the Rust parser would look for an `ident` token,
-which it finds (`foo`) and returns to the macro parser. Then, the macro parser
-proceeds in parsing as normal. Also, note that exactly one of the matchers from
-the various arms should match the invocation; if there is more than one match,
-the parse is ambiguous, while if there are no matches at all, there is a syntax
+Rust parser.
+
+The code to parse macro definitions is in [`compiler/rustc_expand/src/mbe/macro_rules.rs`][code_mr].
+For more information about the macro parser's implementation, see the comments in
+[`compiler/rustc_expand/src/mbe/macro_parser.rs`][code_mp].
+
+Using our example, we would try to match the token stream `print foo` from the invocation against
+the matchers `print $mvar:ident` and `print twice $mvar:ident` that we previously extracted from the
+rules in the macro definition. When the macro parser comes to a place in the current matcher where
+it needs to match a _non-terminal_ (e.g. `$mvar:ident`), it calls back to the normal Rust parser to
+get the contents of that non-terminal. In this case, the Rust parser would look for an `ident`
+token, which it finds (`foo`) and returns to the macro parser. Then, the macro parser continues
+parsing.
+
+Note that exactly one of the matchers from the various rules should match the invocation; if there is
+more than one match, the parse is ambiguous, while if there are no matches at all, there is a syntax
 error.
 
-For more information about the macro parser's implementation, see the comments
-in [`compiler/rustc_expand/src/mbe/macro_parser.rs`][code_mp].
+Assuming exactly one rule matches, macro expansion will then *transcribe* the right-hand side of the
+rule, substituting the values of any matches it captured when matching against the left-hand side.
 
 ## Procedural Macros
 
diff --git a/src/doc/rustc-dev-guide/src/offload/installation.md b/src/doc/rustc-dev-guide/src/offload/installation.md
index b376e962ff6..d1ebf33ac17 100644
--- a/src/doc/rustc-dev-guide/src/offload/installation.md
+++ b/src/doc/rustc-dev-guide/src/offload/installation.md
@@ -1,6 +1,6 @@
 # Installation
 
-In the future, `std::offload` should become available in nightly builds for users. For now, everyone still needs to build rustc from source. 
+`std::offload` is partly available in nightly builds for users. For now, everyone however still needs to build rustc from source to use all features of it. 
 
 ## Build instructions
 
@@ -42,30 +42,3 @@ run
 ```
 ./x test --stage 1 tests/codegen-llvm/gpu_offload
 ```
-
-## Usage
-It is important to use a clang compiler build on the same llvm as rustc. Just calling clang without the full path will likely use your system clang, which probably will be incompatible.
-```
-/absolute/path/to/rust/build/x86_64-unknown-linux-gnu/stage1/bin/rustc --edition=2024 --crate-type cdylib src/main.rs --emit=llvm-ir  -O -C lto=fat -Cpanic=abort -Zoffload=Enable
-/absolute/path/to/rust/build/x86_64-unknown-linux-gnu/llvm/bin/clang++ -fopenmp --offload-arch=native -g  -O3 main.ll -o main -save-temps
-LIBOMPTARGET_INFO=-1  ./main
-```
-The first step will generate a `main.ll` file, which has enough instructions to cause the offload runtime to move data to and from a gpu.
-The second step will use clang as the compilation driver to compile our IR file down to a working binary. Only a very small Rust subset will work out of the box here, unless
-you use features like build-std, which are not covered by this guide. Look at the codegen test to get a feeling for how to write a working example.
-In the last step you can run your binary, if all went well you will see a data transfer being reported:
-```
-omptarget device 0 info: Entering OpenMP data region with being_mapper at unknown:0:0 with 1 arguments:
-omptarget device 0 info: tofrom(unknown)[1024]
-omptarget device 0 info: Creating new map entry with HstPtrBase=0x00007fffffff9540, HstPtrBegin=0x00007fffffff9540, TgtAllocBegin=0x0000155547200000, TgtPtrBegin=0x0000155547200000, Size=1024, DynRefCount=1, HoldRefCount=0, Name=unknown
-omptarget device 0 info: Copying data from host to device, HstPtr=0x00007fffffff9540, TgtPtr=0x0000155547200000, Size=1024, Name=unknown
-omptarget device 0 info: OpenMP Host-Device pointer mappings after block at unknown:0:0:
-omptarget device 0 info: Host Ptr           Target Ptr         Size (B) DynRefCount HoldRefCount Declaration
-omptarget device 0 info: 0x00007fffffff9540 0x0000155547200000 1024     1           0            unknown at unknown:0:0
-// some other output
-omptarget device 0 info: Exiting OpenMP data region with end_mapper at unknown:0:0 with 1 arguments:
-omptarget device 0 info: tofrom(unknown)[1024]
-omptarget device 0 info: Mapping exists with HstPtrBegin=0x00007fffffff9540, TgtPtrBegin=0x0000155547200000, Size=1024, DynRefCount=0 (decremented, delayed deletion), HoldRefCount=0
-omptarget device 0 info: Copying data from device to host, TgtPtr=0x0000155547200000, HstPtr=0x00007fffffff9540, Size=1024, Name=unknown
-omptarget device 0 info: Removing map entry with HstPtrBegin=0x00007fffffff9540, TgtPtrBegin=0x0000155547200000, Size=1024, Name=unknown
-```
diff --git a/src/doc/rustc-dev-guide/src/offload/usage.md b/src/doc/rustc-dev-guide/src/offload/usage.md
new file mode 100644
index 00000000000..9f519984d9b
--- /dev/null
+++ b/src/doc/rustc-dev-guide/src/offload/usage.md
@@ -0,0 +1,112 @@
+# Usage
+
+This feature is work-in-progress, and not ready for usage. The instructions here are for contributors, or people interested in following the latest progress.
+We currently work on launching the following Rust kernel on the GPU. To follow along, copy it to a `src/lib.rs` file.
+
+```rust
+#![feature(abi_gpu_kernel)]
+#![no_std]
+
+#[cfg(target_os = "linux")]
+extern crate libc;
+#[cfg(target_os = "linux")]
+use libc::c_char;
+
+use core::mem;
+
+#[panic_handler]
+fn panic(_: &core::panic::PanicInfo) -> ! {
+    loop {}
+}
+
+#[cfg(target_os = "linux")]
+#[unsafe(no_mangle)]
+#[inline(never)]
+fn main() {
+    let array_c: *mut [f64; 256] =
+        unsafe { libc::calloc(256, (mem::size_of::<f64>()) as libc::size_t) as *mut [f64; 256] };
+    let output = c"The first element is zero %f\n";
+    let output2 = c"The first element is NOT zero %f\n";
+    let output3 = c"The second element is %f\n";
+    unsafe {
+        let val: *const c_char = if (*array_c)[0] < 0.1 {
+            output.as_ptr()
+        } else {
+            output2.as_ptr()
+        };
+        libc::printf(val, (*array_c)[0]);
+    }
+
+    unsafe {
+        kernel_1(array_c);
+    }
+    core::hint::black_box(&array_c);
+    unsafe {
+        let val: *const c_char = if (*array_c)[0] < 0.1 {
+            output.as_ptr()
+        } else {
+            output2.as_ptr()
+        };
+        libc::printf(val, (*array_c)[0]);
+        libc::printf(output3.as_ptr(), (*array_c)[1]);
+    }
+}
+
+#[cfg(target_os = "linux")]
+unsafe extern "C" {
+    pub fn kernel_1(array_b: *mut [f64; 256]);
+}
+```
+
+## Compile instructions
+It is important to use a clang compiler build on the same llvm as rustc. Just calling clang without the full path will likely use your system clang, which probably will be incompatible. So either substitute clang/lld invocations below with absolute path, or set your `PATH` accordingly.
+
+First we generate the host (cpu) code. The first build is just to compile libc, take note of the hashed path. Then we call rustc directly to build our host code, while providing the libc artifact to rustc.
+```
+cargo +offload build -r -v
+rustc +offload --edition 2024 src/lib.rs -g --crate-type cdylib -C opt-level=3 -C panic=abort -C lto=fat -L dependency=/absolute_path_to/target/release/deps --extern libc=/absolute_path_to/target/release/deps/liblibc-<HASH>.rlib --emit=llvm-bc,llvm-ir  -Zoffload=Enable -Zunstable-options
+```
+
+Now we generate the device code. Replace the target-cpu with the right code for your gpu.
+```
+RUSTFLAGS="-Ctarget-cpu=gfx90a --emit=llvm-bc,llvm-ir" cargo +offload build -Zunstable-options -r -v --target amdgcn-amd-amdhsa -Zbuild-std=core
+```
+
+Now find the <libname>.ll under target/amdgcn-amd-amdhsa folder and copy it to a device.ll file (or adjust the file names below).
+If you work on an NVIDIA or Intel gpu, please adjust the names acordingly and open an issue to share your results (either if you succeed or fail).
+First we compile our .ll files (good for manual inspections) to .bc files and clean up leftover artifacts. The cleanup is important, otherwise caching might interfere on following runs.
+```
+opt lib.ll -o lib.bc
+opt device.ll -o device.bc
+rm *.o
+rm bare.amdgcn.gfx90a.img*
+```
+
+```
+clang-offload-packager" "-o" "host.out" "--image=file=device.bc,triple=amdgcn-amd-amdhsa,arch=gfx90a,kind=openmp"
+
+clang-21" "-cc1" "-triple" "x86_64-unknown-linux-gnu" "-S" "-save-temps=cwd" "-disable-free" "-clear-ast-before-backend" "-main-file-name" "lib.rs" "-mrelocation-model" "pic" "-pic-level" "2" "-pic-is-pie" "-mframe-pointer=all" "-fmath-errno" "-ffp-contract=on" "-fno-rounding-math" "-mconstructor-aliases" "-funwind-tables=2" "-target-cpu" "x86-64" "-tune-cpu" "generic" "-resource-dir" "/<ABSOLUTE_PATH_TO>/rust/build/x86_64-unknown-linux-gnu/llvm/lib/clang/21" "-ferror-limit" "19" "-fopenmp" "-fopenmp-offload-mandatory" "-fgnuc-version=4.2.1" "-fskip-odr-check-in-gmf" "-fembed-offload-object=host.out" "-fopenmp-targets=amdgcn-amd-amdhsa" "-faddrsig" "-D__GCC_HAVE_DWARF2_CFI_ASM=1" "-o" "host.s" "-x" "ir" "lib.bc"
+
+clang-21" "-cc1as" "-triple" "x86_64-unknown-linux-gnu" "-filetype" "obj" "-main-file-name" "lib.rs" "-target-cpu" "x86-64" "-mrelocation-model" "pic" "-o" "host.o" "host.s"
+
+clang-linker-wrapper" "--should-extract=gfx90a" "--device-compiler=amdgcn-amd-amdhsa=-g" "--device-compiler=amdgcn-amd-amdhsa=-save-temps=cwd" "--device-linker=amdgcn-amd-amdhsa=-lompdevice" "--host-triple=x86_64-unknown-linux-gnu" "--save-temps" "--linker-path=/ABSOlUTE_PATH_TO/rust/build/x86_64-unknown-linux-gnu/lld/bin/ld.lld" "--hash-style=gnu" "--eh-frame-hdr" "-m" "elf_x86_64" "-pie" "-dynamic-linker" "/lib64/ld-linux-x86-64.so.2" "-o" "bare" "/lib/../lib64/Scrt1.o" "/lib/../lib64/crti.o" "/ABSOLUTE_PATH_TO/crtbeginS.o" "-L/ABSOLUTE_PATH_TO/rust/build/x86_64-unknown-linux-gnu/llvm/bin/../lib/x86_64-unknown-linux-gnu" "-L/ABSOLUTE_PATH_TO/rust/build/x86_64-unknown-linux-gnu/llvm/lib/clang/21/lib/x86_64-unknown-linux-gnu" "-L/lib/../lib64" "-L/usr/lib64" "-L/lib" "-L/usr/lib" "host.o" "-lstdc++" "-lm" "-lomp" "-lomptarget" "-L/ABSOLUTE_PATH_TO/rust/build/x86_64-unknown-linux-gnu/llvm/lib" "-lgcc_s" "-lgcc" "-lpthread" "-lc" "-lgcc_s" "-lgcc" "/ABSOLUTE_PATH_TO/crtendS.o" "/lib/../lib64/crtn.o"
+```
+
+Especially for the last command I recommend to not fix the paths, but rather just re-generate them by copying a bare-mode openmp example and compiling it with your clang. By adding `-###` to your clang invocation, you can see the invidual steps.
+```
+myclang++ -fuse-ld=lld -O3 -fopenmp  -fopenmp-offload-mandatory --offload-arch=gfx90a omp_bare.cpp -o main -###
+```
+
+In the final step, you can now run your binary
+
+```
+./main
+The first element is zero 0.000000
+The first element is NOT zero 21.000000
+The second element is  0.000000
+```
+
+To receive more information about the memory transfer, you can enable info printing with
+```
+LIBOMPTARGET_INFO=-1  ./main
+```
diff --git a/src/doc/rustc-dev-guide/src/queries/example-0.png b/src/doc/rustc-dev-guide/src/queries/example-0.png
index 14b46c44f7d..dd67d5f2ef1 100644
--- a/src/doc/rustc-dev-guide/src/queries/example-0.png
+++ b/src/doc/rustc-dev-guide/src/queries/example-0.png
Binary files differdiff --git a/src/doc/rustc-dev-guide/src/tests/ci.md b/src/doc/rustc-dev-guide/src/tests/ci.md
index 750e4fa1a0f..a8cc959124f 100644
--- a/src/doc/rustc-dev-guide/src/tests/ci.md
+++ b/src/doc/rustc-dev-guide/src/tests/ci.md
@@ -84,16 +84,15 @@ resources to run the full test suite for each commit on every PR.
 > Thus, it is a good idea to run `./x doc xxx` locally for any doc comment
 > changes to help catch these early.
 
-PR jobs are defined in the `pr` section of [`jobs.yml`]. They run under the
-`rust-lang/rust` repository, and their results can be observed directly on the
-PR, in the "CI checks" section at the bottom of the PR page.
+PR jobs are defined in the `pr` section of [`jobs.yml`]. Their results can be observed
+directly on the PR, in the "CI checks" section at the bottom of the PR page.
 
 ### Auto builds
 
 Before a commit can be merged into the `master` branch, it needs to pass our
 complete test suite. We call this an `auto` build. This build runs tens of CI
 jobs that exercise various tests across operating systems and targets. The full
-test suite is quite slow; it can take two hours or more until all the `auto` CI
+test suite is quite slow; it can take several hours until all the `auto` CI
 jobs finish.
 
 Most platforms only run the build steps, some run a restricted set of tests,
@@ -136,14 +135,21 @@ By default, if you send a comment with `@bors try`, the jobs defined in the `try
 [`jobs.yml`] will be executed. We call this mode a "fast try build". Such a try build
 will not execute any tests, and it will allow compilation warnings. It is useful when you want to
 get an optimized toolchain as fast as possible, for a crater run or performance benchmarks,
-even if it might not be working fully correctly.
-
-If you want to run a custom CI job in a try build and make sure that it passes all tests and does
-not produce any compilation warnings, you can select CI jobs to be executed by adding lines
-containing `try-job: <job pattern>` to the PR description. All such specified jobs will be executed
-in the try build once the `@bors try` command is used on the PR.
-
-Each pattern can either be an exact name of a job or a glob pattern that matches multiple jobs,
+even if it might not be working fully correctly. If you want to do a full build for the default try job,
+specify its job name in a job pattern (explained below).
+
+If you want to run custom CI job(s) in a try build and make sure that they pass all tests and do
+not produce any compilation warnings, you can select CI jobs to be executed by specifying a *job pattern*,
+which can be used in one of two ways:
+- You can add a set of `try-job: <job pattern>` directives to the PR description (described below) and then
+  simply run `@bors try`. CI will read these directives and run the jobs that you have specified. This is
+  useful if you want to rerun the same set of try jobs multiple times, after incrementally modifying a PR.
+- You can specify the job pattern using the `jobs` parameter of the try command: `@bors try jobs=<job pattern>`.
+  This is useful for one-off try builds with specific jobs. Note that the `jobs` parameter has a higher priority
+  than the PR description directives.
+  - There can also be multiple patterns specified, e.g. `@bors try jobs=job1,job2,job3`.
+
+Each job pattern can either be an exact name of a job or a glob pattern that matches multiple jobs,
 for example `*msvc*` or `*-alt`. You can start at most 20 jobs in a single try build. When using
 glob patterns, you might want to wrap them in backticks (`` ` ``) to avoid GitHub rendering
 the pattern as Markdown.
@@ -182,26 +188,19 @@ of [`jobs.yml`]:
 > However, it can be less flexible because you cannot adjust the set of tests
 > that are exercised this way.
 
-Try jobs are defined in the `try` section of [`jobs.yml`]. They are executed on
-the `try` branch under the `rust-lang/rust` repository and
+Try builds are executed on the `try` branch under the `rust-lang/rust` repository and
 their results can be seen [here](https://github.com/rust-lang/rust/actions),
 although usually you will be notified of the result by a comment made by bors on
 the corresponding PR.
 
-Note that if you start the default try job using `@bors try`, it will skip building several `dist` components and running post-optimization tests, to make the build duration shorter. If you want to execute the full build as it would happen before a merge, add an explicit `try-job` pattern with the name of the default try job (currently `dist-x86_64-linux`).
+Multiple try builds can execute concurrently across different PRs, but there can be at most
+a single try build running on a single PR at any given time.
 
-Multiple try builds can execute concurrently across different PRs.
-
-<div class="warning">
-
-Bors identifies try jobs by commit hash. This means that if you have two PRs
-containing the same (latest) commits, running `@bors try` will result in the
-*same* try job and it really confuses `bors`. Please refrain from doing so.
-
-</div>
+Note that try builds are handled using the new [bors][new-bors] implementation.
 
 [rustc-perf]: https://github.com/rust-lang/rustc-perf
 [crater]: https://github.com/rust-lang/crater
+[new-bors]: https://github.com/rust-lang/bors
 
 ### Modifying CI jobs
 
diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md
index f4ba9a044e6..fbbeb7e97d3 100644
--- a/src/doc/rustc-dev-guide/src/tests/directives.md
+++ b/src/doc/rustc-dev-guide/src/tests/directives.md
@@ -111,6 +111,7 @@ for more details.
 | `forbid-output`                   | A pattern which must not appear in stderr/`cfail` output                                                                 | `ui`, `incremental`                          | Regex pattern                                                                           |
 | `run-flags`                       | Flags passed to the test executable                                                                                      | `ui`                                         | Arbitrary flags                                                                         |
 | `known-bug`                       | No error annotation needed due to known bug                                                                              | `ui`, `crashes`, `incremental`               | Issue number `#123456`                                                                  |
+| `compare-output-by-lines`         | Compare the output by lines, rather than as a single string                                                              | All                                          | N/A                                                                                     |
 
 [^check_stdout]: presently <!-- date-check: Oct 2024 --> this has a weird quirk
     where the test binary's stdout and stderr gets concatenated and then
diff --git a/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md
index b19d94d6ff7..75cf782a770 100644
--- a/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md
+++ b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md
@@ -18,12 +18,8 @@ Fuchsia builds as part of the suite of bors tests that run before a pull request
 is merged.
 
 If you are worried that a pull request might break the Fuchsia builder and want
-to test it out before submitting it to the bors queue, simply add this line to
-your PR description:
-
-> try-job: x86_64-fuchsia
-
-Then when you `@bors try` it will pick the job that builds Fuchsia.
+to test it out before submitting it to the bors queue, simply ask bors to run
+the try job that builds the Fuchsia integration: `@bors try jobs=x86_64-fuchsia`.
 
 ## Building Fuchsia locally
 
diff --git a/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/rust-for-linux.md b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/rust-for-linux.md
index d549ec6fca5..a6a7374b811 100644
--- a/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/rust-for-linux.md
+++ b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/rust-for-linux.md
@@ -40,12 +40,8 @@ this sysroot. RfL uses several unstable compiler/language features, therefore
 this workflow notifies us if a given compiler change would break it.
 
 If you are worried that a pull request might break the Rust for Linux builder
-and want to test it out before submitting it to the bors queue, simply add this
-line to your PR description:
-
-> try-job: x86_64-rust-for-linux
-
-Then when you `@bors try` it will pick the job that builds the Rust for Linux
-integration.
+and want to test it out before submitting it to the bors queue, simply ask
+bors to run the try job that builds the Rust for Linux integration:
+`@bors try jobs=x86_64-rust-for-linux`.
 
 [rfl-ping]: ../../notification-groups/rust-for-linux.md
diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md
index 25dd5814cf6..d3a2c406402 100644
--- a/src/doc/rustc-dev-guide/src/tests/ui.md
+++ b/src/doc/rustc-dev-guide/src/tests/ui.md
@@ -95,6 +95,7 @@ will check for output files:
   [Normalization](#normalization)).
 - `dont-check-compiler-stderr` — Ignores stderr from the compiler.
 - `dont-check-compiler-stdout` — Ignores stdout from the compiler.
+- `compare-output-by-lines` — Some tests have non-deterministic orders of output, so we need to compare by lines.
 
 UI tests run with `-Zdeduplicate-diagnostics=no` flag which disables rustc's
 built-in diagnostic deduplication mechanism. This means you may see some
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index b53494ed98d..e0d637a2a67 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -49,6 +49,7 @@
     - [aarch64-nintendo-switch-freestanding](platform-support/aarch64-nintendo-switch-freestanding.md)
     - [aarch64-unknown-linux-musl](platform-support/aarch64-unknown-linux-musl.md)
     - [aarch64_be-unknown-none-softfloat](platform-support/aarch64_be-unknown-none-softfloat.md)
+    - [aarch64_be-unknown-linux-musl](platform-support/aarch64_be-unknown-linux-musl.md)
     - [amdgcn-amd-amdhsa](platform-support/amdgcn-amd-amdhsa.md)
     - [armeb-unknown-linux-gnueabi](platform-support/armeb-unknown-linux-gnueabi.md)
     - [arm-none-eabi](platform-support/arm-none-eabi.md)
@@ -106,6 +107,7 @@
     - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md)
     - [riscv64gc-unknown-linux-gnu](platform-support/riscv64gc-unknown-linux-gnu.md)
     - [riscv64gc-unknown-linux-musl](platform-support/riscv64gc-unknown-linux-musl.md)
+    - [riscv64a23-unknown-linux-gnu](platform-support/riscv64a23-unknown-linux-gnu.md)
     - [s390x-unknown-linux-gnu](platform-support/s390x-unknown-linux-gnu.md)
     - [s390x-unknown-linux-musl](platform-support/s390x-unknown-linux-musl.md)
     - [sparc-unknown-none-elf](./platform-support/sparc-unknown-none-elf.md)
diff --git a/src/doc/rustc/src/command-line-arguments/print-options.md b/src/doc/rustc/src/command-line-arguments/print-options.md
index 1f33e91e5d1..fed19d6b667 100644
--- a/src/doc/rustc/src/command-line-arguments/print-options.md
+++ b/src/doc/rustc/src/command-line-arguments/print-options.md
@@ -32,7 +32,7 @@ The names of the files created by the `link` emit kind.
 
 ## `sysroot`
 
-Abosulte path to the sysroot.
+Absolute path to the sysroot.
 
 Example (with rustup and the stable toolchain):
 
diff --git a/src/doc/rustc/src/images/image1.png b/src/doc/rustc/src/images/image1.png
index 0da45e56620..3aad6359389 100644
--- a/src/doc/rustc/src/images/image1.png
+++ b/src/doc/rustc/src/images/image1.png
Binary files differdiff --git a/src/doc/rustc/src/images/image2.png b/src/doc/rustc/src/images/image2.png
index a9cf23f8737..085b1c490b8 100644
--- a/src/doc/rustc/src/images/image2.png
+++ b/src/doc/rustc/src/images/image2.png
Binary files differdiff --git a/src/doc/rustc/src/images/image3.png b/src/doc/rustc/src/images/image3.png
index 844a2fe6747..ee332f51055 100644
--- a/src/doc/rustc/src/images/image3.png
+++ b/src/doc/rustc/src/images/image3.png
Binary files differdiff --git a/src/doc/rustc/src/images/llvm-cov-show-01.png b/src/doc/rustc/src/images/llvm-cov-show-01.png
index 35f04594347..ce4dec128b6 100644
--- a/src/doc/rustc/src/images/llvm-cov-show-01.png
+++ b/src/doc/rustc/src/images/llvm-cov-show-01.png
Binary files differdiff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 3bf87994297..edfc2db7d6f 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -103,7 +103,6 @@ target | notes
 [`powerpc64le-unknown-linux-gnu`](platform-support/powerpc64le-unknown-linux-gnu.md) | PPC64LE Linux (kernel 3.10+, glibc 2.17)
 [`powerpc64le-unknown-linux-musl`](platform-support/powerpc64le-unknown-linux-musl.md) | PPC64LE Linux (kernel 4.19+, musl 1.2.3)
 [`riscv64gc-unknown-linux-gnu`](platform-support/riscv64gc-unknown-linux-gnu.md) | RISC-V Linux (kernel 4.20+, glibc 2.29)
-[`riscv64gc-unknown-linux-musl`](platform-support/riscv64gc-unknown-linux-musl.md) | RISC-V Linux (kernel 4.20+, musl 1.2.3)
 [`s390x-unknown-linux-gnu`](platform-support/s390x-unknown-linux-gnu.md) | S390x Linux (kernel 3.2+, glibc 2.17)
 [`x86_64-apple-darwin`](platform-support/apple-darwin.md) | 64-bit macOS (10.12+, Sierra+)
 [`x86_64-pc-windows-gnullvm`](platform-support/windows-gnullvm.md) | 64-bit x86 MinGW (Windows 10+), LLVM ABI
@@ -183,6 +182,7 @@ target | std | notes
 [`riscv32imac-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAC ISA)
 [`riscv32imafc-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | Bare RISC-V (RV32IMAFC ISA)
 [`riscv32imc-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | Bare RISC-V (RV32IMC ISA)
+[`riscv64gc-unknown-linux-musl`](platform-support/riscv64gc-unknown-linux-musl.md) | RISC-V Linux (kernel 4.20+, musl 1.2.3)
 `riscv64gc-unknown-none-elf` | * | Bare RISC-V (RV64IMAFDC ISA)
 `riscv64imac-unknown-none-elf` | * | Bare RISC-V (RV64IMAC ISA)
 `sparc64-unknown-linux-gnu` | ✓ | SPARC Linux (kernel 4.4+, glibc 2.23)
@@ -273,6 +273,7 @@ target | std | host | notes
 [`aarch64_be-unknown-hermit`](platform-support/hermit.md) | ✓ |  | ARM64 Hermit (big-endian)
 `aarch64_be-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (big-endian)
 `aarch64_be-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (big-endian, ILP32 ABI)
+[`aarch64_be-unknown-linux-musl`](platform-support/aarch64_be-unknown-linux-musl.md) | ✓ | ✓ | ARM64 Linux (big-endian) with musl-libc 1.2.5
 [`aarch64_be-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | ARM64 NetBSD (big-endian)
 [`aarch64_be-unknown-none-softfloat`](platform-support/aarch64_be-unknown-none-softfloat.md) | * |  | Bare big-endian ARM64, softfloat
 [`amdgcn-amd-amdhsa`](platform-support/amdgcn-amd-amdhsa.md) | * |  | `-Ctarget-cpu=gfx...` to specify [the AMD GPU] to compile for
@@ -327,8 +328,8 @@ target | std | host | notes
 [`i686-win7-windows-msvc`](platform-support/win7-windows-msvc.md) | ✓ |   | 32-bit Windows 7 support [^x86_32-floats-return-ABI] [^win32-msvc-alignment]
 [`i686-wrs-vxworks`](platform-support/vxworks.md) | ✓ |  | [^x86_32-floats-return-ABI]
 [`loongarch64-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ |   | LoongArch64 OpenHarmony
-[`loongarch32-unknown-none`](platform-support/loongarch-none.md) | * | LoongArch32 Bare-metal (ILP32D ABI)
-[`loongarch32-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | LoongArch32 Bare-metal (ILP32S ABI)
+[`loongarch32-unknown-none`](platform-support/loongarch-none.md) | * |   | LoongArch32 Bare-metal (ILP32D ABI)
+[`loongarch32-unknown-none-softfloat`](platform-support/loongarch-none.md) | * |   | LoongArch32 Bare-metal (ILP32S ABI)
 [`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? |  | Motorola 680x0 Linux
 [`m68k-unknown-none-elf`](platform-support/m68k-unknown-none-elf.md) |  |  | Motorola 680x0
 `mips-unknown-linux-gnu` | ✓ | ✓ | MIPS Linux (kernel 4.4, glibc 2.23)
@@ -391,6 +392,7 @@ target | std | host | notes
 [`riscv64gc-unknown-nuttx-elf`](platform-support/nuttx.md) | ✓ |  | RISC-V 64bit with NuttX
 [`riscv64gc-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/riscv64
 [`riscv64imac-unknown-nuttx-elf`](platform-support/nuttx.md) | ✓ |  | RISC-V 64bit with NuttX
+[`riscv64a23-unknown-linux-gnu`](platform-support/riscv64a23-unknown-linux-gnu.md) | ✓ | ✓ | RISC-V Linux (kernel 6.8.0+, glibc 2.39)
 [`s390x-unknown-linux-musl`](platform-support/s390x-unknown-linux-musl.md) | ✓ |  | S390x Linux (kernel 3.2, musl 1.2.3)
 `sparc-unknown-linux-gnu` | ✓ |  | 32-bit SPARC Linux
 [`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * |  | Bare 32-bit SPARC V7+
diff --git a/src/doc/rustc/src/platform-support/aarch64_be-unknown-linux-musl.md b/src/doc/rustc/src/platform-support/aarch64_be-unknown-linux-musl.md
new file mode 100644
index 00000000000..3e816dc8bfb
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/aarch64_be-unknown-linux-musl.md
@@ -0,0 +1,49 @@
+# aarch64_be-unknown-linux-musl
+
+**Tier: 3**
+
+ARM64 Linux (big-endian) with musl-libc.
+
+## Target maintainers
+
+[@neuschaefer](https://github.com/neuschaefer)
+[@Gelbpunkt](https://github.com/Gelbpunkt)
+
+## Requirements
+
+The target requires a `aarch64_be-*-linux-musl` toolchain, which likely has to
+be built from source because this is a rare combination.  [Buildroot] provides
+a way of doing so:
+
+- select _Target options_ → _Target Architecture_ → _AArch64 (big endian)_
+- select _Toolchain_ → _C library_ → _musl_
+- select _Toolchain_ → _Enable C++ support_
+
+Host tools are supported.
+
+[Buildroot]: https://buildroot.org/
+
+
+## Building the target
+
+The target can be enabled in bootstrap.toml:
+
+```toml
+[build]
+target = ["aarch64_be-unknown-linux-musl"]
+
+[target.aarch64_be-unknown-linux-musl]
+cc          = "/path/to/buildroot/host/bin/aarch64_be-buildroot-linux-musl-cc"
+cxx         = "/path/to/buildroot/host/bin/aarch64_be-buildroot-linux-musl-c++"
+linker      = "/path/to/buildroot/host/bin/aarch64_be-buildroot-linux-musl-cc"
+ar          = "/path/to/buildroot/host/bin/aarch64_be-buildroot-linux-musl-ar"
+ranlib      = "/path/to/buildroot/host/bin/aarch64_be-buildroot-linux-musl-ranlib"
+musl-root   = "/path/to/buildroot/staging"
+runner      = "qemu-aarch64_be -L /path/to/buildroot/target"
+crt-static  = "/path/to/buildroot/target"
+```
+
+
+## Testing
+
+Binaries can be run under `qemu-aarch64_be` or under a big-endian Linux kernel.
diff --git a/src/doc/rustc/src/platform-support/riscv64a23-unknown-linux-gnu.md b/src/doc/rustc/src/platform-support/riscv64a23-unknown-linux-gnu.md
new file mode 100644
index 00000000000..2cbaaa86654
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/riscv64a23-unknown-linux-gnu.md
@@ -0,0 +1,41 @@
+# `riscv64a23-unknown-linux-gnu`
+
+**Tier: 3**
+
+RISC-V target using the ratified [RVA23 Profile](https://github.com/riscv/riscv-profiles/blob/main/src/rva23-profile.adoc).
+This target will enable all mandary features of rva23u64 by default.
+
+## Target maintainers
+
+[@ZhongyaoChen](https://github.com/ZhongyaoChen)
+[@CaiWeiran](https://github.com/CaiWeiran)
+
+## Requirements
+
+This target can be sucessfully build on the following platform: ubuntu 24.04 (Linux Kernel version 6.8.0, glibc 2.39).
+
+Other platforms may work, but are not tested. Please contanct if you encounter any issues.
+
+## Building the target
+
+Tier-3 target is not distributed through `rustup`.
+
+You need to build your own Rust, the target can be build with:
+
+```bash
+./x build --target riscv64a23-unknown-linux-gnu
+```
+
+## Building Rust programs
+
+Add the toolchain:
+
+```bash
+rustup toolchain link rva23-toolchain {path-to-rust}/build/host/stage2
+```
+
+Then cross compile crates with:
+
+```bash
+RUSTFLAGS="-C linker=riscv64-linux-gnu-gcc" cargo +rva23-toolchain build --target=riscv64a23-unknown-linux-gnu
+```
diff --git a/src/doc/rustdoc/src/images/collapsed-long-item.png b/src/doc/rustdoc/src/images/collapsed-long-item.png
index c382870c64a..6de759fbeb9 100644
--- a/src/doc/rustdoc/src/images/collapsed-long-item.png
+++ b/src/doc/rustdoc/src/images/collapsed-long-item.png
Binary files differdiff --git a/src/doc/rustdoc/src/images/collapsed-trait-impls.png b/src/doc/rustdoc/src/images/collapsed-trait-impls.png
index f685656e09a..96cc7db6798 100644
--- a/src/doc/rustdoc/src/images/collapsed-trait-impls.png
+++ b/src/doc/rustdoc/src/images/collapsed-trait-impls.png
Binary files differdiff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md
index 7bd2970eee7..bb28e3abbf3 100644
--- a/src/doc/rustdoc/src/unstable-features.md
+++ b/src/doc/rustdoc/src/unstable-features.md
@@ -796,3 +796,7 @@ will be split as follows:
     "you today?",
 ]
 ```
+
+## `--generate-macro-expansion`: Generate macros expansion toggles in source code
+
+This flag enables the generation of toggles to expand macros in the HTML source code pages.
diff --git a/src/etc/installer/gfx/rust-logo.png b/src/etc/installer/gfx/rust-logo.png
index 99ee7507fa2..49d8d0d9485 100644
--- a/src/etc/installer/gfx/rust-logo.png
+++ b/src/etc/installer/gfx/rust-logo.png
Binary files differdiff --git a/src/gcc b/src/gcc
-Subproject 04ce66d8c918de9273bd7101638ad8724edf5e2
+Subproject 4e995bd73c4490edfe5080ec6014d63aa9abed5
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index 5d36ffc2d3a..02a3a4e0de4 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -13,7 +13,7 @@ arrayvec = { version = "0.7", default-features = false }
 askama = { version = "0.14", default-features = false, features = ["alloc", "config", "derive"] }
 base64 = "0.21.7"
 indexmap = "2"
-itertools = "0.12"
+itertools.workspace = true
 minifier = { version = "0.3.5", default-features = false }
 pulldown-cmark-escape = { version = "0.11.0", features = ["simd"] }
 regex = "1"
@@ -24,8 +24,8 @@ smallvec = "1.8.1"
 stringdex = { version = "0.0.1-alpha4" }
 tempfile = "3"
 threadpool = "1.8.1"
-tracing = "0.1"
 tracing-tree = "0.3.0"
+tracing.workspace = true
 unicode-segmentation = "1.9"
 # tidy-alphabetical-end
 
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 0d98c64bbde..8461e15c6c3 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -572,30 +572,30 @@ pub(crate) fn build_impl(
         super::build_deref_target_impls(cx, &trait_items, ret);
     }
 
-    // Return if the trait itself or any types of the generic parameters are doc(hidden).
-    let mut stack: Vec<&Type> = vec![&for_];
+    if !document_hidden {
+        // Return if the trait itself or any types of the generic parameters are doc(hidden).
+        let mut stack: Vec<&Type> = vec![&for_];
 
-    if let Some(did) = trait_.as_ref().map(|t| t.def_id())
-        && !document_hidden
-        && tcx.is_doc_hidden(did)
-    {
-        return;
-    }
-
-    if let Some(generics) = trait_.as_ref().and_then(|t| t.generics()) {
-        stack.extend(generics);
-    }
-
-    while let Some(ty) = stack.pop() {
-        if let Some(did) = ty.def_id(&cx.cache)
-            && !document_hidden
+        if let Some(did) = trait_.as_ref().map(|t| t.def_id())
             && tcx.is_doc_hidden(did)
         {
             return;
         }
-        if let Some(generics) = ty.generics() {
+
+        if let Some(generics) = trait_.as_ref().and_then(|t| t.generics()) {
             stack.extend(generics);
         }
+
+        while let Some(ty) = stack.pop() {
+            if let Some(did) = ty.def_id(&cx.cache)
+                && tcx.is_doc_hidden(did)
+            {
+                return;
+            }
+            if let Some(generics) = ty.generics() {
+                stack.extend(generics);
+            }
+        }
     }
 
     if let Some(did) = trait_.as_ref().map(|t| t.def_id()) {
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index c52c7236883..450ac04b40d 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -305,6 +305,8 @@ pub(crate) struct RenderOptions {
     pub(crate) parts_out_dir: Option<PathToParts>,
     /// disable minification of CSS/JS
     pub(crate) disable_minification: bool,
+    /// If `true`, HTML source pages will generate the possibility to expand macros.
+    pub(crate) generate_macro_expansion: bool,
 }
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -786,6 +788,7 @@ impl Options {
         let show_type_layout = matches.opt_present("show-type-layout");
         let nocapture = matches.opt_present("nocapture");
         let generate_link_to_definition = matches.opt_present("generate-link-to-definition");
+        let generate_macro_expansion = matches.opt_present("generate-macro-expansion");
         let extern_html_root_takes_precedence =
             matches.opt_present("extern-html-root-takes-precedence");
         let html_no_source = matches.opt_present("html-no-source");
@@ -801,6 +804,13 @@ impl Options {
             .with_note("`--generate-link-to-definition` option will be ignored")
             .emit();
         }
+        if generate_macro_expansion && (show_coverage || output_format != OutputFormat::Html) {
+            dcx.struct_warn(
+                "`--generate-macro-expansion` option can only be used with HTML output format",
+            )
+            .with_note("`--generate-macro-expansion` option will be ignored")
+            .emit();
+        }
 
         let scrape_examples_options = ScrapeExamplesOptions::new(matches, dcx);
         let with_examples = matches.opt_strs("with-examples");
@@ -881,6 +891,7 @@ impl Options {
             unstable_features,
             emit,
             generate_link_to_definition,
+            generate_macro_expansion,
             call_locations,
             no_emit_shared: false,
             html_no_source,
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index e89733b2f6d..b8aaafcb517 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -31,6 +31,7 @@ use crate::clean::inline::build_trait;
 use crate::clean::{self, ItemId};
 use crate::config::{Options as RustdocOptions, OutputFormat, RenderOptions};
 use crate::formats::cache::Cache;
+use crate::html::macro_expansion::{ExpandedCode, source_macro_expansion};
 use crate::passes;
 use crate::passes::Condition::*;
 use crate::passes::collect_intra_doc_links::LinkCollector;
@@ -334,11 +335,19 @@ pub(crate) fn run_global_ctxt(
     show_coverage: bool,
     render_options: RenderOptions,
     output_format: OutputFormat,
-) -> (clean::Crate, RenderOptions, Cache) {
+) -> (clean::Crate, RenderOptions, Cache, FxHashMap<rustc_span::BytePos, Vec<ExpandedCode>>) {
     // Certain queries assume that some checks were run elsewhere
     // (see https://github.com/rust-lang/rust/pull/73566#issuecomment-656954425),
     // so type-check everything other than function bodies in this crate before running lints.
 
+    let expanded_macros = {
+        // We need for these variables to be removed to ensure that the `Crate` won't be "stolen"
+        // anymore.
+        let (_resolver, krate) = &*tcx.resolver_for_lowering().borrow();
+
+        source_macro_expansion(&krate, &render_options, output_format, tcx.sess.source_map())
+    };
+
     // NOTE: this does not call `tcx.analysis()` so that we won't
     // typeck function bodies or run the default rustc lints.
     // (see `override_queries` in the `config`)
@@ -448,7 +457,7 @@ pub(crate) fn run_global_ctxt(
 
     tcx.dcx().abort_if_errors();
 
-    (krate, ctxt.render_options, ctxt.cache)
+    (krate, ctxt.render_options, ctxt.cache, expanded_macros)
 }
 
 /// Due to <https://github.com/rust-lang/rust/pull/73566>,
diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs
index aa4be4db997..305c8c39ba7 100644
--- a/src/librustdoc/formats/renderer.rs
+++ b/src/librustdoc/formats/renderer.rs
@@ -31,15 +31,6 @@ pub(crate) trait FormatRenderer<'tcx>: Sized {
     /// reset the information between each call to `item` by using `restore_module_data`.
     type ModuleData;
 
-    /// Sets up any state required for the renderer. When this is called the cache has already been
-    /// populated.
-    fn init(
-        krate: clean::Crate,
-        options: RenderOptions,
-        cache: Cache,
-        tcx: TyCtxt<'tcx>,
-    ) -> Result<(Self, clean::Crate), Error>;
-
     /// This method is called right before call [`Self::item`]. This method returns a type
     /// containing information that needs to be reset after the [`Self::item`] method has been
     /// called with the [`Self::restore_module_data`] method.
@@ -105,18 +96,23 @@ fn run_format_inner<'tcx, T: FormatRenderer<'tcx>>(
 }
 
 /// Main method for rendering a crate.
-pub(crate) fn run_format<'tcx, T: FormatRenderer<'tcx>>(
+pub(crate) fn run_format<
+    'tcx,
+    T: FormatRenderer<'tcx>,
+    F: FnOnce(clean::Crate, RenderOptions, Cache, TyCtxt<'tcx>) -> Result<(T, clean::Crate), Error>,
+>(
     krate: clean::Crate,
     options: RenderOptions,
     cache: Cache,
     tcx: TyCtxt<'tcx>,
+    init: F,
 ) -> Result<(), Error> {
     let prof = &tcx.sess.prof;
 
     let emit_crate = options.should_emit_crate();
     let (mut format_renderer, krate) = prof
         .verbose_generic_activity_with_arg("create_renderer", T::descr())
-        .run(|| T::init(krate, options, cache, tcx))?;
+        .run(|| init(krate, options, cache, tcx))?;
 
     if !emit_crate {
         return Ok(());
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index 272180fb990..feafb41dc99 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -5,6 +5,7 @@
 //!
 //! Use the `render_with_highlighting` to highlight some rust code.
 
+use std::borrow::Cow;
 use std::collections::VecDeque;
 use std::fmt::{self, Display, Write};
 
@@ -17,6 +18,7 @@ use rustc_span::{BytePos, DUMMY_SP, Span};
 use super::format::{self, write_str};
 use crate::clean::PrimitiveType;
 use crate::html::escape::EscapeBodyText;
+use crate::html::macro_expansion::ExpandedCode;
 use crate::html::render::{Context, LinkFromSrc};
 
 /// This type is needed in case we want to render links on items to allow to go to their definition.
@@ -163,11 +165,22 @@ struct TokenHandler<'a, 'tcx, F: Write> {
     current_class: Option<Class>,
     /// We need to keep the `Class` for each element because it could contain a `Span` which is
     /// used to generate links.
-    pending_elems: Vec<(&'a str, Option<Class>)>,
+    pending_elems: Vec<(Cow<'a, str>, Option<Class>)>,
     href_context: Option<HrefContext<'a, 'tcx>>,
     write_line_number: fn(&mut F, u32, &'static str),
 }
 
+impl<F: Write> std::fmt::Debug for TokenHandler<'_, '_, F> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        f.debug_struct("TokenHandler")
+            .field("closing_tags", &self.closing_tags)
+            .field("pending_exit_span", &self.pending_exit_span)
+            .field("current_class", &self.current_class)
+            .field("pending_elems", &self.pending_elems)
+            .finish()
+    }
+}
+
 impl<F: Write> TokenHandler<'_, '_, F> {
     fn handle_exit_span(&mut self) {
         // We can't get the last `closing_tags` element using `pop()` because `closing_tags` is
@@ -220,6 +233,10 @@ impl<F: Write> TokenHandler<'_, '_, F> {
             } else {
                 None
             };
+            // To prevent opening a macro expansion span being closed right away because
+            // the currently open item is replaced by a new class.
+            let last_pending =
+                self.pending_elems.pop_if(|(_, class)| *class == Some(Class::Expansion));
             for (text, class) in self.pending_elems.iter() {
                 string(
                     self.out,
@@ -233,6 +250,16 @@ impl<F: Write> TokenHandler<'_, '_, F> {
             if let Some(close_tag) = close_tag {
                 exit_span(self.out, close_tag);
             }
+            if let Some((text, class)) = last_pending {
+                string(
+                    self.out,
+                    EscapeBodyText(&text),
+                    class,
+                    &self.href_context,
+                    close_tag.is_none(),
+                    self.write_line_number,
+                );
+            }
         }
         self.pending_elems.clear();
         true
@@ -271,6 +298,100 @@ fn empty_line_number(out: &mut impl Write, _: u32, extra: &'static str) {
     out.write_str(extra).unwrap();
 }
 
+fn get_next_expansion(
+    expanded_codes: &[ExpandedCode],
+    line: u32,
+    span: Span,
+) -> Option<&ExpandedCode> {
+    expanded_codes.iter().find(|code| code.start_line == line && code.span.lo() > span.lo())
+}
+
+fn get_expansion<'a, W: Write>(
+    token_handler: &mut TokenHandler<'_, '_, W>,
+    expanded_codes: &'a [ExpandedCode],
+    line: u32,
+    span: Span,
+) -> Option<&'a ExpandedCode> {
+    if let Some(expanded_code) = get_next_expansion(expanded_codes, line, span) {
+        let (closing, reopening) = if let Some(current_class) = token_handler.current_class
+            && let class = current_class.as_html()
+            && !class.is_empty()
+        {
+            ("</span>", format!("<span class=\"{class}\">"))
+        } else {
+            ("", String::new())
+        };
+        let id = format!("expand-{line}");
+        token_handler.pending_elems.push((
+            Cow::Owned(format!(
+                "{closing}\
+<span class=expansion>\
+    <input id={id} \
+           tabindex=0 \
+           type=checkbox \
+           aria-label=\"Collapse/expand macro\" \
+           title=\"\"Collapse/expand macro\">{reopening}",
+            )),
+            Some(Class::Expansion),
+        ));
+        Some(expanded_code)
+    } else {
+        None
+    }
+}
+
+fn start_expansion(out: &mut Vec<(Cow<'_, str>, Option<Class>)>, expanded_code: &ExpandedCode) {
+    out.push((
+        Cow::Owned(format!(
+            "<span class=expanded>{}</span><span class=original>",
+            expanded_code.code,
+        )),
+        Some(Class::Expansion),
+    ));
+}
+
+fn end_expansion<'a, W: Write>(
+    token_handler: &mut TokenHandler<'_, '_, W>,
+    expanded_codes: &'a [ExpandedCode],
+    expansion_start_tags: &[(&'static str, Class)],
+    line: u32,
+    span: Span,
+) -> Option<&'a ExpandedCode> {
+    if let Some(expanded_code) = get_next_expansion(expanded_codes, line, span) {
+        // We close the current "original" content.
+        token_handler.pending_elems.push((Cow::Borrowed("</span>"), Some(Class::Expansion)));
+        return Some(expanded_code);
+    }
+    if expansion_start_tags.is_empty() && token_handler.closing_tags.is_empty() {
+        // No need tag opened so we can just close expansion.
+        token_handler.pending_elems.push((Cow::Borrowed("</span></span>"), Some(Class::Expansion)));
+        return None;
+    }
+
+    // If tags were opened inside the expansion, we need to close them and re-open them outside
+    // of the expansion span.
+    let mut out = String::new();
+    let mut end = String::new();
+
+    let mut closing_tags = token_handler.closing_tags.iter().peekable();
+    let mut start_closing_tags = expansion_start_tags.iter().peekable();
+
+    while let (Some(tag), Some(start_tag)) = (closing_tags.peek(), start_closing_tags.peek())
+        && tag == start_tag
+    {
+        closing_tags.next();
+        start_closing_tags.next();
+    }
+    for (tag, class) in start_closing_tags.chain(closing_tags) {
+        out.push_str(tag);
+        end.push_str(&format!("<span class=\"{}\">", class.as_html()));
+    }
+    token_handler
+        .pending_elems
+        .push((Cow::Owned(format!("</span></span>{out}{end}")), Some(Class::Expansion)));
+    None
+}
+
 #[derive(Clone, Copy)]
 pub(super) struct LineInfo {
     pub(super) start_line: u32,
@@ -317,7 +438,7 @@ pub(super) fn write_code(
         closing_tags: Vec::new(),
         pending_exit_span: None,
         current_class: None,
-        pending_elems: Vec::new(),
+        pending_elems: Vec::with_capacity(20),
         href_context,
         write_line_number: match line_info {
             Some(line_info) => {
@@ -338,12 +459,23 @@ pub(super) fn write_code(
         (0, u32::MAX)
     };
 
+    let (expanded_codes, file_span) = match token_handler.href_context.as_ref().and_then(|c| {
+        let expanded_codes = c.context.shared.expanded_codes.get(&c.file_span.lo())?;
+        Some((expanded_codes, c.file_span))
+    }) {
+        Some((expanded_codes, file_span)) => (expanded_codes.as_slice(), file_span),
+        None => (&[] as &[ExpandedCode], DUMMY_SP),
+    };
+    let mut current_expansion = get_expansion(&mut token_handler, expanded_codes, line, file_span);
+    token_handler.write_pending_elems(None);
+    let mut expansion_start_tags = Vec::new();
+
     Classifier::new(
         &src,
         token_handler.href_context.as_ref().map(|c| c.file_span).unwrap_or(DUMMY_SP),
         decoration_info,
     )
-    .highlight(&mut |highlight| {
+    .highlight(&mut |span, highlight| {
         match highlight {
             Highlight::Token { text, class } => {
                 // If we received a `ExitSpan` event and then have a non-compatible `Class`, we
@@ -369,10 +501,42 @@ pub(super) fn write_code(
                 if text == "\n" {
                     line += 1;
                     if line < max_lines {
-                        token_handler.pending_elems.push((text, Some(Class::Backline(line))));
+                        token_handler
+                            .pending_elems
+                            .push((Cow::Borrowed(text), Some(Class::Backline(line))));
+                    }
+                    if current_expansion.is_none() {
+                        current_expansion =
+                            get_expansion(&mut token_handler, expanded_codes, line, span);
+                        expansion_start_tags = token_handler.closing_tags.clone();
+                    }
+                    if let Some(ref current_expansion) = current_expansion
+                        && current_expansion.span.lo() == span.hi()
+                    {
+                        start_expansion(&mut token_handler.pending_elems, current_expansion);
                     }
                 } else {
-                    token_handler.pending_elems.push((text, class));
+                    token_handler.pending_elems.push((Cow::Borrowed(text), class));
+
+                    let mut need_end = false;
+                    if let Some(ref current_expansion) = current_expansion {
+                        if current_expansion.span.lo() == span.hi() {
+                            start_expansion(&mut token_handler.pending_elems, current_expansion);
+                        } else if current_expansion.end_line == line
+                            && span.hi() >= current_expansion.span.hi()
+                        {
+                            need_end = true;
+                        }
+                    }
+                    if need_end {
+                        current_expansion = end_expansion(
+                            &mut token_handler,
+                            expanded_codes,
+                            &expansion_start_tags,
+                            line,
+                            span,
+                        );
+                    }
                 }
             }
             Highlight::EnterSpan { class } => {
@@ -440,6 +604,8 @@ enum Class {
     QuestionMark,
     Decoration(&'static str),
     Backline(u32),
+    /// Macro expansion.
+    Expansion,
 }
 
 impl Class {
@@ -489,6 +655,7 @@ impl Class {
             Class::QuestionMark => "question-mark",
             Class::Decoration(kind) => kind,
             Class::Backline(_) => "",
+            Class::Expansion => "",
         }
     }
 
@@ -513,7 +680,8 @@ impl Class {
             | Self::Lifetime
             | Self::QuestionMark
             | Self::Decoration(_)
-            | Self::Backline(_) => None,
+            | Self::Backline(_)
+            | Self::Expansion => None,
         }
     }
 }
@@ -628,6 +796,13 @@ impl Decorations {
     }
 }
 
+/// Convenient wrapper to create a [`Span`] from a position in the file.
+fn new_span(lo: u32, text: &str, file_span: Span) -> Span {
+    let hi = lo + text.len() as u32;
+    let file_lo = file_span.lo();
+    file_span.with_lo(file_lo + BytePos(lo)).with_hi(file_lo + BytePos(hi))
+}
+
 /// Processes program tokens, classifying strings of text by highlighting
 /// category (`Class`).
 struct Classifier<'src> {
@@ -660,13 +835,6 @@ impl<'src> Classifier<'src> {
         }
     }
 
-    /// Convenient wrapper to create a [`Span`] from a position in the file.
-    fn new_span(&self, lo: u32, text: &str) -> Span {
-        let hi = lo + text.len() as u32;
-        let file_lo = self.file_span.lo();
-        self.file_span.with_lo(file_lo + BytePos(lo)).with_hi(file_lo + BytePos(hi))
-    }
-
     /// Concatenate colons and idents as one when possible.
     fn get_full_ident_path(&mut self) -> Vec<(TokenKind, usize, usize)> {
         let start = self.byte_pos as usize;
@@ -735,18 +903,18 @@ impl<'src> Classifier<'src> {
     /// The general structure for this method is to iterate over each token,
     /// possibly giving it an HTML span with a class specifying what flavor of
     /// token is used.
-    fn highlight(mut self, sink: &mut dyn FnMut(Highlight<'src>)) {
+    fn highlight(mut self, sink: &mut dyn FnMut(Span, Highlight<'src>)) {
         loop {
             if let Some(decs) = self.decorations.as_mut() {
                 let byte_pos = self.byte_pos;
                 let n_starts = decs.starts.iter().filter(|(i, _)| byte_pos >= *i).count();
                 for (_, kind) in decs.starts.drain(0..n_starts) {
-                    sink(Highlight::EnterSpan { class: Class::Decoration(kind) });
+                    sink(DUMMY_SP, Highlight::EnterSpan { class: Class::Decoration(kind) });
                 }
 
                 let n_ends = decs.ends.iter().filter(|i| byte_pos >= **i).count();
                 for _ in decs.ends.drain(0..n_ends) {
-                    sink(Highlight::ExitSpan);
+                    sink(DUMMY_SP, Highlight::ExitSpan);
                 }
             }
 
@@ -784,14 +952,22 @@ impl<'src> Classifier<'src> {
         &mut self,
         token: TokenKind,
         text: &'src str,
-        sink: &mut dyn FnMut(Highlight<'src>),
+        sink: &mut dyn FnMut(Span, Highlight<'src>),
         before: u32,
     ) {
         let lookahead = self.peek();
-        let no_highlight = |sink: &mut dyn FnMut(_)| sink(Highlight::Token { text, class: None });
-        let whitespace = |sink: &mut dyn FnMut(_)| {
+        let file_span = self.file_span;
+        let no_highlight = |sink: &mut dyn FnMut(_, _)| {
+            sink(new_span(before, text, file_span), Highlight::Token { text, class: None })
+        };
+        let whitespace = |sink: &mut dyn FnMut(_, _)| {
+            let mut start = 0u32;
             for part in text.split('\n').intersperse("\n").filter(|s| !s.is_empty()) {
-                sink(Highlight::Token { text: part, class: None });
+                sink(
+                    new_span(before + start, part, file_span),
+                    Highlight::Token { text: part, class: None },
+                );
+                start += part.len() as u32;
             }
         };
         let class = match token {
@@ -807,8 +983,8 @@ impl<'src> Classifier<'src> {
             // leading identifier.
             TokenKind::Bang if self.in_macro => {
                 self.in_macro = false;
-                sink(Highlight::Token { text, class: None });
-                sink(Highlight::ExitSpan);
+                sink(new_span(before, text, file_span), Highlight::Token { text, class: None });
+                sink(DUMMY_SP, Highlight::ExitSpan);
                 return;
             }
 
@@ -819,12 +995,18 @@ impl<'src> Classifier<'src> {
                 Some((TokenKind::Whitespace, _)) => return whitespace(sink),
                 Some((TokenKind::Ident, "mut")) => {
                     self.next();
-                    sink(Highlight::Token { text: "*mut", class: Some(Class::RefKeyWord) });
+                    sink(
+                        DUMMY_SP,
+                        Highlight::Token { text: "*mut", class: Some(Class::RefKeyWord) },
+                    );
                     return;
                 }
                 Some((TokenKind::Ident, "const")) => {
                     self.next();
-                    sink(Highlight::Token { text: "*const", class: Some(Class::RefKeyWord) });
+                    sink(
+                        DUMMY_SP,
+                        Highlight::Token { text: "*const", class: Some(Class::RefKeyWord) },
+                    );
                     return;
                 }
                 _ => Class::RefKeyWord,
@@ -832,18 +1014,21 @@ impl<'src> Classifier<'src> {
             TokenKind::And => match self.tokens.peek() {
                 Some((TokenKind::And, _)) => {
                     self.next();
-                    sink(Highlight::Token { text: "&&", class: None });
+                    sink(DUMMY_SP, Highlight::Token { text: "&&", class: None });
                     return;
                 }
                 Some((TokenKind::Eq, _)) => {
                     self.next();
-                    sink(Highlight::Token { text: "&=", class: None });
+                    sink(DUMMY_SP, Highlight::Token { text: "&=", class: None });
                     return;
                 }
                 Some((TokenKind::Whitespace, _)) => return whitespace(sink),
                 Some((TokenKind::Ident, "mut")) => {
                     self.next();
-                    sink(Highlight::Token { text: "&mut", class: Some(Class::RefKeyWord) });
+                    sink(
+                        DUMMY_SP,
+                        Highlight::Token { text: "&mut", class: Some(Class::RefKeyWord) },
+                    );
                     return;
                 }
                 _ => Class::RefKeyWord,
@@ -853,19 +1038,19 @@ impl<'src> Classifier<'src> {
             TokenKind::Eq => match lookahead {
                 Some(TokenKind::Eq) => {
                     self.next();
-                    sink(Highlight::Token { text: "==", class: None });
+                    sink(DUMMY_SP, Highlight::Token { text: "==", class: None });
                     return;
                 }
                 Some(TokenKind::Gt) => {
                     self.next();
-                    sink(Highlight::Token { text: "=>", class: None });
+                    sink(DUMMY_SP, Highlight::Token { text: "=>", class: None });
                     return;
                 }
                 _ => return no_highlight(sink),
             },
             TokenKind::Minus if lookahead == Some(TokenKind::Gt) => {
                 self.next();
-                sink(Highlight::Token { text: "->", class: None });
+                sink(DUMMY_SP, Highlight::Token { text: "->", class: None });
                 return;
             }
 
@@ -916,16 +1101,22 @@ impl<'src> Classifier<'src> {
                         self.next();
                         if let Some(TokenKind::OpenBracket) = self.peek() {
                             self.in_attribute = true;
-                            sink(Highlight::EnterSpan { class: Class::Attribute });
+                            sink(
+                                new_span(before, text, file_span),
+                                Highlight::EnterSpan { class: Class::Attribute },
+                            );
                         }
-                        sink(Highlight::Token { text: "#", class: None });
-                        sink(Highlight::Token { text: "!", class: None });
+                        sink(DUMMY_SP, Highlight::Token { text: "#", class: None });
+                        sink(DUMMY_SP, Highlight::Token { text: "!", class: None });
                         return;
                     }
                     // Case 2: #[outer_attribute]
                     Some(TokenKind::OpenBracket) => {
                         self.in_attribute = true;
-                        sink(Highlight::EnterSpan { class: Class::Attribute });
+                        sink(
+                            new_span(before, text, file_span),
+                            Highlight::EnterSpan { class: Class::Attribute },
+                        );
                     }
                     _ => (),
                 }
@@ -934,8 +1125,11 @@ impl<'src> Classifier<'src> {
             TokenKind::CloseBracket => {
                 if self.in_attribute {
                     self.in_attribute = false;
-                    sink(Highlight::Token { text: "]", class: None });
-                    sink(Highlight::ExitSpan);
+                    sink(
+                        new_span(before, text, file_span),
+                        Highlight::Token { text: "]", class: None },
+                    );
+                    sink(DUMMY_SP, Highlight::ExitSpan);
                     return;
                 }
                 return no_highlight(sink);
@@ -956,15 +1150,16 @@ impl<'src> Classifier<'src> {
             TokenKind::GuardedStrPrefix => return no_highlight(sink),
             TokenKind::Ident | TokenKind::RawIdent if lookahead == Some(TokenKind::Bang) => {
                 self.in_macro = true;
-                sink(Highlight::EnterSpan { class: Class::Macro(self.new_span(before, text)) });
-                sink(Highlight::Token { text, class: None });
+                let span = new_span(before, text, file_span);
+                sink(DUMMY_SP, Highlight::EnterSpan { class: Class::Macro(span) });
+                sink(span, Highlight::Token { text, class: None });
                 return;
             }
             TokenKind::Ident => match get_real_ident_class(text, false) {
                 None => match text {
-                    "Option" | "Result" => Class::PreludeTy(self.new_span(before, text)),
+                    "Option" | "Result" => Class::PreludeTy(new_span(before, text, file_span)),
                     "Some" | "None" | "Ok" | "Err" => {
-                        Class::PreludeVal(self.new_span(before, text))
+                        Class::PreludeVal(new_span(before, text, file_span))
                     }
                     // "union" is a weak keyword and is only considered as a keyword when declaring
                     // a union type.
@@ -973,13 +1168,13 @@ impl<'src> Classifier<'src> {
                         self.in_macro_nonterminal = false;
                         Class::MacroNonTerminal
                     }
-                    "self" | "Self" => Class::Self_(self.new_span(before, text)),
-                    _ => Class::Ident(self.new_span(before, text)),
+                    "self" | "Self" => Class::Self_(new_span(before, text, file_span)),
+                    _ => Class::Ident(new_span(before, text, file_span)),
                 },
                 Some(c) => c,
             },
             TokenKind::RawIdent | TokenKind::UnknownPrefix | TokenKind::InvalidIdent => {
-                Class::Ident(self.new_span(before, text))
+                Class::Ident(new_span(before, text, file_span))
             }
             TokenKind::Lifetime { .. }
             | TokenKind::RawLifetime
@@ -988,8 +1183,13 @@ impl<'src> Classifier<'src> {
         };
         // Anything that didn't return above is the simple case where we the
         // class just spans a single token, so we can use the `string` method.
+        let mut start = 0u32;
         for part in text.split('\n').intersperse("\n").filter(|s| !s.is_empty()) {
-            sink(Highlight::Token { text: part, class: Some(class) });
+            sink(
+                new_span(before + start, part, file_span),
+                Highlight::Token { text: part, class: Some(class) },
+            );
+            start += part.len() as u32;
         }
     }
 
@@ -1042,9 +1242,9 @@ fn exit_span(out: &mut impl Write, closing_tag: &str) {
 /// Note that if `context` is not `None` and that the given `klass` contains a `Span`, the function
 /// will then try to find this `span` in the `span_correspondence_map`. If found, it'll then
 /// generate a link for this element (which corresponds to where its definition is located).
-fn string<T: Display, W: Write>(
+fn string<W: Write>(
     out: &mut W,
-    text: T,
+    text: EscapeBodyText<'_>,
     klass: Option<Class>,
     href_context: &Option<HrefContext<'_, '_>>,
     open_tag: bool,
@@ -1052,6 +1252,9 @@ fn string<T: Display, W: Write>(
 ) {
     if let Some(Class::Backline(line)) = klass {
         write_line_number_callback(out, line, "\n");
+    } else if let Some(Class::Expansion) = klass {
+        // This has already been escaped so we get the text to write it directly.
+        out.write_str(text.0).unwrap();
     } else if let Some(closing_tag) =
         string_without_closing_tag(out, text, klass, href_context, open_tag)
     {
diff --git a/src/librustdoc/html/macro_expansion.rs b/src/librustdoc/html/macro_expansion.rs
new file mode 100644
index 00000000000..9098e92a5cd
--- /dev/null
+++ b/src/librustdoc/html/macro_expansion.rs
@@ -0,0 +1,156 @@
+use rustc_ast::visit::{Visitor, walk_crate, walk_expr, walk_item, walk_pat, walk_stmt};
+use rustc_ast::{Crate, Expr, Item, Pat, Stmt};
+use rustc_data_structures::fx::FxHashMap;
+use rustc_span::source_map::SourceMap;
+use rustc_span::{BytePos, Span};
+
+use crate::config::{OutputFormat, RenderOptions};
+
+/// It returns the expanded macros correspondence map.
+pub(crate) fn source_macro_expansion(
+    krate: &Crate,
+    render_options: &RenderOptions,
+    output_format: OutputFormat,
+    source_map: &SourceMap,
+) -> FxHashMap<BytePos, Vec<ExpandedCode>> {
+    if output_format == OutputFormat::Html
+        && !render_options.html_no_source
+        && render_options.generate_macro_expansion
+    {
+        let mut expanded_visitor = ExpandedCodeVisitor { expanded_codes: Vec::new(), source_map };
+        walk_crate(&mut expanded_visitor, krate);
+        expanded_visitor.compute_expanded()
+    } else {
+        Default::default()
+    }
+}
+
+/// Contains information about macro expansion in the source code pages.
+#[derive(Debug)]
+pub(crate) struct ExpandedCode {
+    /// The line where the macro expansion starts.
+    pub(crate) start_line: u32,
+    /// The line where the macro expansion ends.
+    pub(crate) end_line: u32,
+    /// The source code of the expanded macro.
+    pub(crate) code: String,
+    /// The span of macro callsite.
+    pub(crate) span: Span,
+}
+
+/// Contains temporary information of macro expanded code.
+///
+/// As we go through the HIR visitor, if any span overlaps with another, they will
+/// both be merged.
+struct ExpandedCodeInfo {
+    /// Callsite of the macro.
+    span: Span,
+    /// Expanded macro source code (HTML escaped).
+    code: String,
+    /// Span of macro-generated code.
+    expanded_span: Span,
+}
+
+/// HIR visitor which retrieves expanded macro.
+///
+/// Once done, the `expanded_codes` will be transformed into a vec of [`ExpandedCode`]
+/// which contains the information needed when running the source code highlighter.
+pub(crate) struct ExpandedCodeVisitor<'ast> {
+    expanded_codes: Vec<ExpandedCodeInfo>,
+    source_map: &'ast SourceMap,
+}
+
+impl<'ast> ExpandedCodeVisitor<'ast> {
+    fn handle_new_span<F: Fn() -> String>(&mut self, new_span: Span, f: F) {
+        if new_span.is_dummy() || !new_span.from_expansion() {
+            return;
+        }
+        let callsite_span = new_span.source_callsite();
+        if let Some(index) =
+            self.expanded_codes.iter().position(|info| info.span.overlaps(callsite_span))
+        {
+            let info = &mut self.expanded_codes[index];
+            if new_span.contains(info.expanded_span) {
+                // New macro expansion recursively contains the old one, so replace it.
+                info.span = callsite_span;
+                info.expanded_span = new_span;
+                info.code = f();
+            } else {
+                // We push the new item after the existing one.
+                let expanded_code = &mut self.expanded_codes[index];
+                expanded_code.code.push('\n');
+                expanded_code.code.push_str(&f());
+                let lo = BytePos(expanded_code.expanded_span.lo().0.min(new_span.lo().0));
+                let hi = BytePos(expanded_code.expanded_span.hi().0.min(new_span.hi().0));
+                expanded_code.expanded_span = expanded_code.expanded_span.with_lo(lo).with_hi(hi);
+            }
+        } else {
+            // We add a new item.
+            self.expanded_codes.push(ExpandedCodeInfo {
+                span: callsite_span,
+                code: f(),
+                expanded_span: new_span,
+            });
+        }
+    }
+
+    fn compute_expanded(mut self) -> FxHashMap<BytePos, Vec<ExpandedCode>> {
+        self.expanded_codes.sort_unstable_by(|item1, item2| item1.span.cmp(&item2.span));
+        let mut expanded: FxHashMap<BytePos, Vec<ExpandedCode>> = FxHashMap::default();
+        for ExpandedCodeInfo { span, code, .. } in self.expanded_codes {
+            if let Ok(lines) = self.source_map.span_to_lines(span)
+                && !lines.lines.is_empty()
+            {
+                let mut out = String::new();
+                super::highlight::write_code(&mut out, &code, None, None, None);
+                let first = lines.lines.first().unwrap();
+                let end = lines.lines.last().unwrap();
+                expanded.entry(lines.file.start_pos).or_default().push(ExpandedCode {
+                    start_line: first.line_index as u32 + 1,
+                    end_line: end.line_index as u32 + 1,
+                    code: out,
+                    span,
+                });
+            }
+        }
+        expanded
+    }
+}
+
+// We need to use the AST pretty printing because:
+//
+// 1. HIR pretty printing doesn't display accurately the code (like `impl Trait`).
+// 2. `SourceMap::snippet_opt` might fail if the source is not available.
+impl<'ast> Visitor<'ast> for ExpandedCodeVisitor<'ast> {
+    fn visit_expr(&mut self, expr: &'ast Expr) {
+        if expr.span.from_expansion() {
+            self.handle_new_span(expr.span, || rustc_ast_pretty::pprust::expr_to_string(expr));
+        } else {
+            walk_expr(self, expr);
+        }
+    }
+
+    fn visit_item(&mut self, item: &'ast Item) {
+        if item.span.from_expansion() {
+            self.handle_new_span(item.span, || rustc_ast_pretty::pprust::item_to_string(item));
+        } else {
+            walk_item(self, item);
+        }
+    }
+
+    fn visit_stmt(&mut self, stmt: &'ast Stmt) {
+        if stmt.span.from_expansion() {
+            self.handle_new_span(stmt.span, || rustc_ast_pretty::pprust::stmt_to_string(stmt));
+        } else {
+            walk_stmt(self, stmt);
+        }
+    }
+
+    fn visit_pat(&mut self, pat: &'ast Pat) {
+        if pat.span.from_expansion() {
+            self.handle_new_span(pat.span, || rustc_ast_pretty::pprust::pat_to_string(pat));
+        } else {
+            walk_pat(self, pat);
+        }
+    }
+}
diff --git a/src/librustdoc/html/mod.rs b/src/librustdoc/html/mod.rs
index 481ed16c05f..d42f4782845 100644
--- a/src/librustdoc/html/mod.rs
+++ b/src/librustdoc/html/mod.rs
@@ -3,6 +3,7 @@ pub(crate) mod format;
 pub(crate) mod highlight;
 pub(crate) mod layout;
 mod length_limit;
+pub(crate) mod macro_expansion;
 // used by the error-index generator, so it needs to be public
 pub mod markdown;
 pub(crate) mod render;
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index e4fca09d64f..faaecaf0cbb 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -12,7 +12,7 @@ use rustc_hir::def_id::{DefIdMap, LOCAL_CRATE};
 use rustc_middle::ty::TyCtxt;
 use rustc_session::Session;
 use rustc_span::edition::Edition;
-use rustc_span::{FileName, Symbol, sym};
+use rustc_span::{BytePos, FileName, Symbol, sym};
 use tracing::info;
 
 use super::print_item::{full_path, print_item, print_item_path};
@@ -28,6 +28,7 @@ use crate::formats::FormatRenderer;
 use crate::formats::cache::Cache;
 use crate::formats::item_type::ItemType;
 use crate::html::escape::Escape;
+use crate::html::macro_expansion::ExpandedCode;
 use crate::html::markdown::{self, ErrorCodes, IdMap, plain_text_summary};
 use crate::html::render::write_shared::write_shared;
 use crate::html::url_parts_builder::UrlPartsBuilder;
@@ -139,6 +140,7 @@ pub(crate) struct SharedContext<'tcx> {
     /// Correspondence map used to link types used in the source code pages to allow to click on
     /// links to jump to the type's definition.
     pub(crate) span_correspondence_map: FxHashMap<rustc_span::Span, LinkFromSrc>,
+    pub(crate) expanded_codes: FxHashMap<BytePos, Vec<ExpandedCode>>,
     /// The [`Cache`] used during rendering.
     pub(crate) cache: Cache,
     pub(crate) call_locations: AllCallLocations,
@@ -458,20 +460,13 @@ impl<'tcx> Context<'tcx> {
     }
 }
 
-/// Generates the documentation for `crate` into the directory `dst`
-impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
-    fn descr() -> &'static str {
-        "html"
-    }
-
-    const RUN_ON_MODULE: bool = true;
-    type ModuleData = ContextInfo;
-
-    fn init(
+impl<'tcx> Context<'tcx> {
+    pub(crate) fn init(
         krate: clean::Crate,
         options: RenderOptions,
         cache: Cache,
         tcx: TyCtxt<'tcx>,
+        expanded_codes: FxHashMap<BytePos, Vec<ExpandedCode>>,
     ) -> Result<(Self, clean::Crate), Error> {
         // need to save a copy of the options for rendering the index page
         let md_opts = options.clone();
@@ -579,6 +574,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             cache,
             call_locations,
             should_merge: options.should_merge,
+            expanded_codes,
         };
 
         let dst = output;
@@ -604,6 +600,16 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
 
         Ok((cx, krate))
     }
+}
+
+/// Generates the documentation for `crate` into the directory `dst`
+impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
+    fn descr() -> &'static str {
+        "html"
+    }
+
+    const RUN_ON_MODULE: bool = true;
+    type ModuleData = ContextInfo;
 
     fn save_module_data(&mut self) -> Self::ModuleData {
         self.deref_id_map.borrow_mut().clear();
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 8d7f0577506..673947ad308 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -1029,6 +1029,7 @@ fn assoc_const(
 ) -> impl fmt::Display {
     let tcx = cx.tcx();
     fmt::from_fn(move |w| {
+        render_attributes_in_code(w, it, &" ".repeat(indent), cx);
         write!(
             w,
             "{indent}{vis}const <a{href} class=\"constant\">{name}</a>{generics}: {ty}",
@@ -1136,10 +1137,10 @@ fn assoc_method(
         let (indent, indent_str, end_newline) = if parent == ItemType::Trait {
             header_len += 4;
             let indent_str = "    ";
-            write!(w, "{}", render_attributes_in_pre(meth, indent_str, cx))?;
+            render_attributes_in_code(w, meth, indent_str, cx);
             (4, indent_str, Ending::NoNewline)
         } else {
-            render_attributes_in_code(w, meth, cx);
+            render_attributes_in_code(w, meth, "", cx);
             (0, "", Ending::Newline)
         };
         write!(
@@ -1309,28 +1310,28 @@ fn render_assoc_item(
     })
 }
 
-// When an attribute is rendered inside a `<pre>` tag, it is formatted using
-// a whitespace prefix and newline.
-fn render_attributes_in_pre(it: &clean::Item, prefix: &str, cx: &Context<'_>) -> impl fmt::Display {
-    fmt::from_fn(move |f| {
-        for a in it.attributes(cx.tcx(), cx.cache()) {
-            writeln!(f, "{prefix}{a}")?;
-        }
-        Ok(())
-    })
-}
-
 struct CodeAttribute(String);
 
-fn render_code_attribute(code_attr: CodeAttribute, w: &mut impl fmt::Write) {
-    write!(w, "<div class=\"code-attribute\">{}</div>", code_attr.0).unwrap();
+fn render_code_attribute(prefix: &str, code_attr: CodeAttribute, w: &mut impl fmt::Write) {
+    write!(
+        w,
+        "<div class=\"code-attribute\">{prefix}{attr}</div>",
+        prefix = prefix,
+        attr = code_attr.0
+    )
+    .unwrap();
 }
 
 // When an attribute is rendered inside a <code> tag, it is formatted using
 // a div to produce a newline after it.
-fn render_attributes_in_code(w: &mut impl fmt::Write, it: &clean::Item, cx: &Context<'_>) {
+fn render_attributes_in_code(
+    w: &mut impl fmt::Write,
+    it: &clean::Item,
+    prefix: &str,
+    cx: &Context<'_>,
+) {
     for attr in it.attributes(cx.tcx(), cx.cache()) {
-        render_code_attribute(CodeAttribute(attr), w);
+        render_code_attribute(prefix, CodeAttribute(attr), w);
     }
 }
 
@@ -1342,7 +1343,7 @@ fn render_repr_attributes_in_code(
     item_type: ItemType,
 ) {
     if let Some(repr) = clean::repr_attributes(cx.tcx(), cx.cache(), def_id, item_type) {
-        render_code_attribute(CodeAttribute(repr), w);
+        render_code_attribute("", CodeAttribute(repr), w);
     }
 }
 
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 407238d66b8..b86a2c94697 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -20,8 +20,8 @@ use super::{
     AssocItemLink, AssocItemRender, Context, ImplRenderingParameters, RenderMode,
     collect_paths_for_type, document, ensure_trailing_slash, get_filtered_impls_for_reference,
     item_ty_to_section, notable_traits_button, notable_traits_json, render_all_impls,
-    render_assoc_item, render_assoc_items, render_attributes_in_code, render_attributes_in_pre,
-    render_impl, render_repr_attributes_in_code, render_rightside, render_stability_since_raw,
+    render_assoc_item, render_assoc_items, render_attributes_in_code, render_impl,
+    render_repr_attributes_in_code, render_rightside, render_stability_since_raw,
     render_stability_since_raw_with_extra, write_section_heading,
 };
 use crate::clean;
@@ -107,13 +107,6 @@ macro_rules! item_template_methods {
         }
         item_template_methods!($($rest)*);
     };
-    (render_attributes_in_pre $($rest:tt)*) => {
-        fn render_attributes_in_pre(&self) -> impl fmt::Display {
-            let (item, cx) = self.item_and_cx();
-            render_attributes_in_pre(item, "", cx)
-        }
-        item_template_methods!($($rest)*);
-    };
     (render_assoc_items $($rest:tt)*) => {
         fn render_assoc_items(&self) -> impl fmt::Display {
             let (item, cx) = self.item_and_cx();
@@ -457,7 +450,12 @@ fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> i
                     write!(
                         w,
                         "<dt{id}>\
-                            <code>{vis}{imp}</code>{stab_tags}\
+                            <code>"
+                    )?;
+                    render_attributes_in_code(w, myitem, "", cx);
+                    write!(
+                        w,
+                        "{vis}{imp}</code>{stab_tags}\
                         </dt>",
                         vis = visibility_print_with_space(myitem, cx),
                         imp = import.print(cx)
@@ -625,11 +623,11 @@ fn item_function(cx: &Context<'_>, it: &clean::Item, f: &clean::Function) -> imp
         let notable_traits = notable_traits_button(&f.decl.output, cx).maybe_display();
 
         wrap_item(w, |w| {
+            render_attributes_in_code(w, it, "", cx);
             write!(
                 w,
-                "{attrs}{vis}{constness}{asyncness}{safety}{abi}fn \
+                "{vis}{constness}{asyncness}{safety}{abi}fn \
                 {name}{generics}{decl}{notable_traits}{where_clause}",
-                attrs = render_attributes_in_pre(it, "", cx),
                 vis = visibility,
                 constness = constness,
                 asyncness = asyncness,
@@ -666,10 +664,10 @@ fn item_trait(cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) -> impl fmt:
 
         // Output the trait definition
         wrap_item(w, |mut w| {
+            render_attributes_in_code(&mut w, it, "", cx);
             write!(
                 w,
-                "{attrs}{vis}{safety}{is_auto}trait {name}{generics}{bounds}",
-                attrs = render_attributes_in_pre(it, "", cx),
+                "{vis}{safety}{is_auto}trait {name}{generics}{bounds}",
                 vis = visibility_print_with_space(it, cx),
                 safety = t.safety(tcx).print_with_space(),
                 is_auto = if t.is_auto(tcx) { "auto " } else { "" },
@@ -1240,10 +1238,10 @@ fn item_trait_alias(
 ) -> impl fmt::Display {
     fmt::from_fn(|w| {
         wrap_item(w, |w| {
+            render_attributes_in_code(w, it, "", cx);
             write!(
                 w,
-                "{attrs}trait {name}{generics} = {bounds}{where_clause};",
-                attrs = render_attributes_in_pre(it, "", cx),
+                "trait {name}{generics} = {bounds}{where_clause};",
                 name = it.name.unwrap(),
                 generics = t.generics.print(cx),
                 bounds = print_bounds(&t.bounds, true, cx),
@@ -1268,10 +1266,10 @@ fn item_trait_alias(
 fn item_type_alias(cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) -> impl fmt::Display {
     fmt::from_fn(|w| {
         wrap_item(w, |w| {
+            render_attributes_in_code(w, it, "", cx);
             write!(
                 w,
-                "{attrs}{vis}type {name}{generics}{where_clause} = {type_};",
-                attrs = render_attributes_in_pre(it, "", cx),
+                "{vis}type {name}{generics}{where_clause} = {type_};",
                 vis = visibility_print_with_space(it, cx),
                 name = it.name.unwrap(),
                 generics = t.generics.print(cx),
@@ -1452,7 +1450,21 @@ item_template!(
 
 impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> {
     fn render_union(&self) -> impl Display {
-        render_union(self.it, Some(self.generics), self.fields, self.cx)
+        render_union(
+            self.it,
+            Some(self.generics),
+            self.fields,
+            self.def_id,
+            self.is_type_alias,
+            self.cx,
+        )
+    }
+
+    fn print_field_attrs(&self, field: &'a clean::Item) -> impl Display {
+        fmt::from_fn(move |w| {
+            render_attributes_in_code(w, field, "", self.cx);
+            Ok(())
+        })
     }
 
     fn document_field(&self, field: &'a clean::Item) -> impl Display {
@@ -1479,27 +1491,6 @@ impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> {
             _ => None,
         })
     }
-
-    fn render_attributes_in_pre(&self) -> impl fmt::Display {
-        fmt::from_fn(move |f| {
-            if self.is_type_alias {
-                // For now the only attributes we render for type aliases are `repr` attributes.
-                if let Some(repr) = clean::repr_attributes(
-                    self.cx.tcx(),
-                    self.cx.cache(),
-                    self.def_id,
-                    ItemType::Union,
-                ) {
-                    writeln!(f, "{repr}")?;
-                };
-            } else {
-                for a in self.it.attributes(self.cx.tcx(), self.cx.cache()) {
-                    writeln!(f, "{a}")?;
-                }
-            }
-            Ok(())
-        })
-    }
 }
 
 fn item_union(cx: &Context<'_>, it: &clean::Item, s: &clean::Union) -> impl fmt::Display {
@@ -1563,7 +1554,7 @@ impl<'clean> DisplayEnum<'clean> {
                 // For now the only attributes we render for type aliases are `repr` attributes.
                 render_repr_attributes_in_code(w, cx, self.def_id, ItemType::Enum);
             } else {
-                render_attributes_in_code(w, it, cx);
+                render_attributes_in_code(w, it, "", cx);
             }
             write!(
                 w,
@@ -1702,7 +1693,7 @@ fn render_enum_fields(
                 if v.is_stripped() {
                     continue;
                 }
-                write!(w, "{}", render_attributes_in_pre(v, TAB, cx))?;
+                render_attributes_in_code(w, v, TAB, cx);
                 w.write_str(TAB)?;
                 match v.kind {
                     clean::VariantItem(ref var) => match var.kind {
@@ -1786,6 +1777,7 @@ fn item_variants(
                 )
                 .maybe_display()
             )?;
+            render_attributes_in_code(w, variant, "", cx);
             if let clean::VariantItem(ref var) = variant.kind
                 && let clean::VariantKind::CLike = var.kind
             {
@@ -1859,7 +1851,12 @@ fn item_variants(
                                 "<div class=\"sub-variant-field\">\
                                     <span id=\"{id}\" class=\"section-header\">\
                                         <a href=\"#{id}\" class=\"anchor field\">§</a>\
-                                        <code>{f}: {t}</code>\
+                                        <code>"
+                            )?;
+                            render_attributes_in_code(w, field, "", cx);
+                            write!(
+                                w,
+                                "{f}: {t}</code>\
                                     </span>\
                                     {doc}\
                                 </div>",
@@ -1882,6 +1879,7 @@ fn item_macro(cx: &Context<'_>, it: &clean::Item, t: &clean::Macro) -> impl fmt:
     fmt::from_fn(|w| {
         wrap_item(w, |w| {
             // FIXME: Also print `#[doc(hidden)]` for `macro_rules!` if it `is_doc_hidden`.
+            render_attributes_in_code(w, it, "", cx);
             if !t.macro_rules {
                 write!(w, "{}", visibility_print_with_space(it, cx))?;
             }
@@ -1950,7 +1948,7 @@ fn item_constant(
     fmt::from_fn(|w| {
         wrap_item(w, |w| {
             let tcx = cx.tcx();
-            render_attributes_in_code(w, it, cx);
+            render_attributes_in_code(w, it, "", cx);
 
             write!(
                 w,
@@ -2018,7 +2016,7 @@ impl<'a> DisplayStruct<'a> {
                 // For now the only attributes we render for type aliases are `repr` attributes.
                 render_repr_attributes_in_code(w, cx, self.def_id, ItemType::Struct);
             } else {
-                render_attributes_in_code(w, it, cx);
+                render_attributes_in_code(w, it, "", cx);
             }
             write!(
                 w,
@@ -2094,10 +2092,15 @@ fn item_fields(
                     w,
                     "<span id=\"{id}\" class=\"{item_type} section-header\">\
                         <a href=\"#{id}\" class=\"anchor field\">§</a>\
-                        <code>{field_name}: {ty}</code>\
+                        <code>",
+                    item_type = ItemType::StructField,
+                )?;
+                render_attributes_in_code(w, field, "", cx);
+                write!(
+                    w,
+                    "{field_name}: {ty}</code>\
                     </span>\
                     {doc}",
-                    item_type = ItemType::StructField,
                     ty = ty.print(cx),
                     doc = document(cx, field, Some(it), HeadingOffset::H3),
                 )?;
@@ -2115,7 +2118,7 @@ fn item_static(
 ) -> impl fmt::Display {
     fmt::from_fn(move |w| {
         wrap_item(w, |w| {
-            render_attributes_in_code(w, it, cx);
+            render_attributes_in_code(w, it, "", cx);
             write!(
                 w,
                 "{vis}{safe}static {mutability}{name}: {typ}",
@@ -2135,7 +2138,7 @@ fn item_foreign_type(cx: &Context<'_>, it: &clean::Item) -> impl fmt::Display {
     fmt::from_fn(|w| {
         wrap_item(w, |w| {
             w.write_str("extern {\n")?;
-            render_attributes_in_code(w, it, cx);
+            render_attributes_in_code(w, it, "", cx);
             write!(w, "    {}type {};\n}}", visibility_print_with_space(it, cx), it.name.unwrap(),)
         })?;
 
@@ -2358,9 +2361,17 @@ fn render_union(
     it: &clean::Item,
     g: Option<&clean::Generics>,
     fields: &[clean::Item],
+    def_id: DefId,
+    is_type_alias: bool,
     cx: &Context<'_>,
 ) -> impl Display {
     fmt::from_fn(move |mut f| {
+        if is_type_alias {
+            // For now the only attributes we render for type aliases are `repr` attributes.
+            render_repr_attributes_in_code(f, cx, def_id, ItemType::Union);
+        } else {
+            render_attributes_in_code(f, it, "", cx);
+        }
         write!(f, "{}union {}", visibility_print_with_space(it, cx), it.name.unwrap(),)?;
 
         let where_displayed = if let Some(generics) = g {
@@ -2390,6 +2401,7 @@ fn render_union(
 
         for field in fields {
             if let clean::StructFieldItem(ref ty) = field.kind {
+                render_attributes_in_code(&mut f, field, "    ", cx);
                 writeln!(
                     f,
                     "    {}{}: {},",
@@ -2481,11 +2493,15 @@ fn render_struct_fields(
                 if toggle {
                     toggle_open(&mut *w, format_args!("{count_fields} fields"));
                 }
+                if has_visible_fields {
+                    writeln!(w)?;
+                }
                 for field in fields {
                     if let clean::StructFieldItem(ref ty) = field.kind {
-                        write!(
+                        render_attributes_in_code(w, field, &format!("{tab}    "), cx);
+                        writeln!(
                             w,
-                            "\n{tab}    {vis}{name}: {ty},",
+                            "{tab}    {vis}{name}: {ty},",
                             vis = visibility_print_with_space(field, cx),
                             name = field.name.unwrap(),
                             ty = ty.print(cx)
@@ -2495,12 +2511,12 @@ fn render_struct_fields(
 
                 if has_visible_fields {
                     if has_stripped_entries {
-                        write!(
+                        writeln!(
                             w,
-                            "\n{tab}    <span class=\"comment\">/* private fields */</span>"
+                            "{tab}    <span class=\"comment\">/* private fields */</span>"
                         )?;
                     }
-                    write!(w, "\n{tab}")?;
+                    write!(w, "{tab}")?;
                 } else if has_stripped_entries {
                     write!(w, " <span class=\"comment\">/* private fields */</span> ")?;
                 }
diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs
index 846d3ad310c..8bc2e0bd957 100644
--- a/src/librustdoc/html/render/span_map.rs
+++ b/src/librustdoc/html/render/span_map.rs
@@ -35,7 +35,7 @@ pub(crate) enum LinkFromSrc {
 /// 1. Generate a `span` correspondence map which links an item `span` to its definition `span`.
 /// 2. Collect the source code files.
 ///
-/// It returns the `krate`, the source code files and the `span` correspondence map.
+/// It returns the source code files and the `span` correspondence map.
 ///
 /// Note about the `span` correspondence map: the keys are actually `(lo, hi)` of `span`s. We don't
 /// need the `span` context later on, only their position, so instead of keeping a whole `Span`, we
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index dc27d7943d9..86f1a42bc01 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -956,6 +956,40 @@ rustdoc-topbar {
 .example-wrap.digits-8 { --example-wrap-digits-count: 8ch; }
 .example-wrap.digits-9 { --example-wrap-digits-count: 9ch; }
 
+.example-wrap .expansion {
+	position: relative;
+	display: inline;
+}
+.example-wrap .expansion > input {
+	display: block;
+	position: absolute;
+	appearance: none;
+	content: '↕';
+	left: -20px;
+	top: 0;
+	border: 1px solid var(--border-color);
+	border-radius: 4px;
+	cursor: pointer;
+	color: var(--main-color);
+	padding: 0 2px;
+	line-height: 20px;
+}
+.example-wrap .expansion > input::after {
+	content: "↕";
+}
+.example-wrap .expansion .expanded {
+	display: none;
+	color: var(--main-color);
+}
+.example-wrap .expansion > input:checked ~ .expanded,
+.example-wrap .expansion > input:checked ~ * .expanded {
+	display: inherit;
+}
+.example-wrap .expansion > input:checked ~ .original,
+.example-wrap .expansion > input:checked ~ * .original {
+	display: none;
+}
+
 .example-wrap [data-nosnippet] {
 	width: calc(var(--example-wrap-digits-count) + var(--line-number-padding) * 2);
 }
@@ -964,6 +998,17 @@ rustdoc-topbar {
 		var(--example-wrap-digits-count) + var(--line-number-padding) * 2
 		+ var(--line-number-right-margin));
 }
+.src .example-wrap .expansion [data-nosnippet] {
+	/* FIXME: Once <https://bugzilla.mozilla.org/show_bug.cgi?id=1949948> is solved, uncomment
+	   next line and remove the two other rules. */
+	/*left: calc((
+		var(--example-wrap-digits-count) + var(--line-number-padding) * 2
+		+ var(--line-number-right-margin)) * -1);*/
+	position: initial;
+	margin-left: calc((
+		var(--example-wrap-digits-count) + var(--line-number-padding) * 2
+		+ var(--line-number-right-margin)) * -1);
+}
 
 .example-wrap [data-nosnippet] {
 	color: var(--src-line-numbers-span-color);
@@ -978,9 +1023,6 @@ rustdoc-topbar {
 	position: absolute;
 	left: 0;
 }
-.example-wrap .line-highlighted[data-nosnippet] {
-	background-color: var(--src-line-number-highlighted-background-color);
-}
 .example-wrap pre > code {
 	position: relative;
 	display: block;
@@ -995,6 +1037,9 @@ rustdoc-topbar {
 .example-wrap [data-nosnippet]:target {
 	border-right: none;
 }
+.example-wrap .line-highlighted[data-nosnippet] {
+	background-color: var(--src-line-number-highlighted-background-color);
+}
 .example-wrap.hide-lines [data-nosnippet] {
 	display: none;
 }
diff --git a/src/librustdoc/html/static/images/favicon-32x32.png b/src/librustdoc/html/static/images/favicon-32x32.png
index 69b8613ce15..0670c4dabb0 100644
--- a/src/librustdoc/html/static/images/favicon-32x32.png
+++ b/src/librustdoc/html/static/images/favicon-32x32.png
Binary files differdiff --git a/src/librustdoc/html/templates/item_union.html b/src/librustdoc/html/templates/item_union.html
index b5d3367a6a1..171e079ed13 100644
--- a/src/librustdoc/html/templates/item_union.html
+++ b/src/librustdoc/html/templates/item_union.html
@@ -1,5 +1,4 @@
 <pre class="rust item-decl"><code>
-    {{ self.render_attributes_in_pre()|safe }}
     {{ self.render_union()|safe }}
 </code></pre>
 {% if !self.is_type_alias %}
@@ -13,7 +12,7 @@
         {% let name = field.name.expect("union field name") %}
         <span id="structfield.{{ name }}" class="{{ ItemType::StructField +}} section-header"> {# #}
             <a href="#structfield.{{ name }}" class="anchor field">§</a> {# #}
-            <code>{{ name }}: {{+ self.print_ty(ty)|safe }}</code> {# #}
+            <code>{{+ self.print_field_attrs(field)|safe }}{{ name }}: {{+ self.print_ty(ty)|safe }}</code> {# #}
         </span>
         {% if let Some(stability_class) = self.stability_field(field) %}
             <span class="stab {{ stability_class }}"></span>
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index 760e48baffa..b724d7e866a 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -175,15 +175,8 @@ fn target(sess: &rustc_session::Session) -> types::Target {
     }
 }
 
-impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
-    fn descr() -> &'static str {
-        "json"
-    }
-
-    const RUN_ON_MODULE: bool = false;
-    type ModuleData = ();
-
-    fn init(
+impl<'tcx> JsonRenderer<'tcx> {
+    pub(crate) fn init(
         krate: clean::Crate,
         options: RenderOptions,
         cache: Cache,
@@ -205,6 +198,15 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
             krate,
         ))
     }
+}
+
+impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
+    fn descr() -> &'static str {
+        "json"
+    }
+
+    const RUN_ON_MODULE: bool = false;
+    type ModuleData = ();
 
     fn save_module_data(&mut self) -> Self::ModuleData {
         unreachable!("RUN_ON_MODULE = false, should never call save_module_data")
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 28dbd8ba7d3..e2682045ab4 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -11,6 +11,7 @@
 #![feature(file_buffered)]
 #![feature(format_args_nl)]
 #![feature(if_let_guard)]
+#![feature(iter_advance_by)]
 #![feature(iter_intersperse)]
 #![feature(round_char_boundary)]
 #![feature(rustc_private)]
@@ -80,6 +81,8 @@ use rustc_session::{EarlyDiagCtxt, getopts};
 use tracing::info;
 
 use crate::clean::utils::DOC_RUST_LANG_ORG_VERSION;
+use crate::error::Error;
+use crate::formats::cache::Cache;
 
 /// A macro to create a FxHashMap.
 ///
@@ -663,6 +666,14 @@ fn opts() -> Vec<RustcOptGroup> {
             "disable the minification of CSS/JS files (perma-unstable, do not use with cached files)",
             "",
         ),
+        opt(
+            Unstable,
+            Flag,
+            "",
+            "generate-macro-expansion",
+            "Add possibility to expand macros in the HTML source code pages",
+            "",
+        ),
         // deprecated / removed options
         opt(
             Stable,
@@ -726,13 +737,23 @@ pub(crate) fn wrap_return(dcx: DiagCtxtHandle<'_>, res: Result<(), String>) {
     }
 }
 
-fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>(
+fn run_renderer<
+    'tcx,
+    T: formats::FormatRenderer<'tcx>,
+    F: FnOnce(
+        clean::Crate,
+        config::RenderOptions,
+        Cache,
+        TyCtxt<'tcx>,
+    ) -> Result<(T, clean::Crate), Error>,
+>(
     krate: clean::Crate,
     renderopts: config::RenderOptions,
     cache: formats::cache::Cache,
     tcx: TyCtxt<'tcx>,
+    init: F,
 ) {
-    match formats::run_format::<T>(krate, renderopts, cache, tcx) {
+    match formats::run_format::<T, F>(krate, renderopts, cache, tcx, init) {
         Ok(_) => tcx.dcx().abort_if_errors(),
         Err(e) => {
             let mut msg =
@@ -862,6 +883,7 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) {
     let scrape_examples_options = options.scrape_examples_options.clone();
     let bin_crate = options.bin_crate;
 
+    let output_format = options.output_format;
     let config = core::create_config(input, options, &render_options);
 
     let registered_lints = config.register_lints.is_some();
@@ -886,9 +908,10 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) {
                 sess.dcx().fatal("Compilation failed, aborting rustdoc");
             }
 
-            let (krate, render_opts, mut cache) = sess.time("run_global_ctxt", || {
-                core::run_global_ctxt(tcx, show_coverage, render_options, output_format)
-            });
+            let (krate, render_opts, mut cache, expanded_macros) = sess
+                .time("run_global_ctxt", || {
+                    core::run_global_ctxt(tcx, show_coverage, render_options, output_format)
+                });
             info!("finished with rustc");
 
             if let Some(options) = scrape_examples_options {
@@ -919,10 +942,24 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) {
             info!("going to format");
             match output_format {
                 config::OutputFormat::Html => sess.time("render_html", || {
-                    run_renderer::<html::render::Context<'_>>(krate, render_opts, cache, tcx)
+                    run_renderer(
+                        krate,
+                        render_opts,
+                        cache,
+                        tcx,
+                        |krate, render_opts, cache, tcx| {
+                            html::render::Context::init(
+                                krate,
+                                render_opts,
+                                cache,
+                                tcx,
+                                expanded_macros,
+                            )
+                        },
+                    )
                 }),
                 config::OutputFormat::Json => sess.time("render_json", || {
-                    run_renderer::<json::JsonRenderer<'_>>(krate, render_opts, cache, tcx)
+                    run_renderer(krate, render_opts, cache, tcx, json::JsonRenderer::init)
                 }),
                 // Already handled above with doctest runners.
                 config::OutputFormat::Doctest => unreachable!(),
diff --git a/src/librustdoc/passes/lint/html_tags.rs b/src/librustdoc/passes/lint/html_tags.rs
index 19cf15d40a3..da09117b1bb 100644
--- a/src/librustdoc/passes/lint/html_tags.rs
+++ b/src/librustdoc/passes/lint/html_tags.rs
@@ -1,9 +1,11 @@
 //! Detects invalid HTML (like an unclosed `<span>`) in doc comments.
 
+use std::borrow::Cow;
 use std::iter::Peekable;
 use std::ops::Range;
 use std::str::CharIndices;
 
+use itertools::Itertools as _;
 use pulldown_cmark::{BrokenLink, Event, LinkType, Parser, Tag, TagEnd};
 use rustc_hir::HirId;
 use rustc_resolve::rustdoc::source_span_for_markdown_range;
@@ -101,7 +103,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &
         });
     };
 
-    let mut tags = Vec::new();
+    let mut tagp = TagParser::new();
     let mut is_in_comment = None;
     let mut in_code_block = false;
 
@@ -126,70 +128,65 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: &
     };
 
     let p = Parser::new_with_broken_link_callback(dox, main_body_opts(), Some(&mut replacer))
-        .into_offset_iter();
+        .into_offset_iter()
+        .coalesce(|a, b| {
+            // for some reason, pulldown-cmark splits html blocks into separate events for each line.
+            // we undo this, in order to handle multi-line tags.
+            match (a, b) {
+                ((Event::Html(_), ra), (Event::Html(_), rb)) if ra.end == rb.start => {
+                    let merged = ra.start..rb.end;
+                    Ok((Event::Html(Cow::Borrowed(&dox[merged.clone()]).into()), merged))
+                }
+                x => Err(x),
+            }
+        });
 
     for (event, range) in p {
         match event {
             Event::Start(Tag::CodeBlock(_)) => in_code_block = true,
             Event::Html(text) | Event::InlineHtml(text) if !in_code_block => {
-                extract_tags(&mut tags, &text, range, &mut is_in_comment, &report_diag)
+                tagp.extract_tags(&text, range, &mut is_in_comment, &report_diag)
             }
             Event::End(TagEnd::CodeBlock) => in_code_block = false,
             _ => {}
         }
     }
 
-    for (tag, range) in tags.iter().filter(|(t, _)| {
-        let t = t.to_lowercase();
-        !ALLOWED_UNCLOSED.contains(&t.as_str())
-    }) {
-        report_diag(format!("unclosed HTML tag `{tag}`"), range, true);
-    }
-
     if let Some(range) = is_in_comment {
         report_diag("Unclosed HTML comment".to_string(), &range, false);
+    } else if let &Some(quote_pos) = &tagp.quote_pos {
+        let qr = Range { start: quote_pos, end: quote_pos };
+        report_diag(
+            format!("unclosed quoted HTML attribute on tag `{}`", &tagp.tag_name),
+            &qr,
+            false,
+        );
+    } else {
+        if !tagp.tag_name.is_empty() {
+            report_diag(
+                format!("incomplete HTML tag `{}`", &tagp.tag_name),
+                &(tagp.tag_start_pos..dox.len()),
+                false,
+            );
+        }
+        for (tag, range) in tagp.tags.iter().filter(|(t, _)| {
+            let t = t.to_lowercase();
+            !is_implicitly_self_closing(&t)
+        }) {
+            report_diag(format!("unclosed HTML tag `{tag}`"), range, true);
+        }
     }
 }
 
+/// These tags are interpreted as self-closing if they lack an explicit closing tag.
 const ALLOWED_UNCLOSED: &[&str] = &[
     "area", "base", "br", "col", "embed", "hr", "img", "input", "keygen", "link", "meta", "param",
     "source", "track", "wbr",
 ];
 
-fn drop_tag(
-    tags: &mut Vec<(String, Range<usize>)>,
-    tag_name: String,
-    range: Range<usize>,
-    f: &impl Fn(String, &Range<usize>, bool),
-) {
-    let tag_name_low = tag_name.to_lowercase();
-    if let Some(pos) = tags.iter().rposition(|(t, _)| t.to_lowercase() == tag_name_low) {
-        // If the tag is nested inside a "<script>" or a "<style>" tag, no warning should
-        // be emitted.
-        let should_not_warn = tags.iter().take(pos + 1).any(|(at, _)| {
-            let at = at.to_lowercase();
-            at == "script" || at == "style"
-        });
-        for (last_tag_name, last_tag_span) in tags.drain(pos + 1..) {
-            if should_not_warn {
-                continue;
-            }
-            let last_tag_name_low = last_tag_name.to_lowercase();
-            if ALLOWED_UNCLOSED.contains(&last_tag_name_low.as_str()) {
-                continue;
-            }
-            // `tags` is used as a queue, meaning that everything after `pos` is included inside it.
-            // So `<h2><h3></h2>` will look like `["h2", "h3"]`. So when closing `h2`, we will still
-            // have `h3`, meaning the tag wasn't closed as it should have.
-            f(format!("unclosed HTML tag `{last_tag_name}`"), &last_tag_span, true);
-        }
-        // Remove the `tag_name` that was originally closed
-        tags.pop();
-    } else {
-        // It can happen for example in this case: `<h2></script></h2>` (the `h2` tag isn't required
-        // but it helps for the visualization).
-        f(format!("unopened HTML tag `{tag_name}`"), &range, false);
-    }
+/// Allows constructs like `<img>`, but not `<img`.
+fn is_implicitly_self_closing(tag_name: &str) -> bool {
+    ALLOWED_UNCLOSED.contains(&tag_name)
 }
 
 fn extract_path_backwards(text: &str, end_pos: usize) -> Option<usize> {
@@ -252,151 +249,292 @@ fn is_valid_for_html_tag_name(c: char, is_empty: bool) -> bool {
     c.is_ascii_alphabetic() || !is_empty && (c == '-' || c.is_ascii_digit())
 }
 
-fn extract_html_tag(
-    tags: &mut Vec<(String, Range<usize>)>,
-    text: &str,
-    range: &Range<usize>,
-    start_pos: usize,
-    iter: &mut Peekable<CharIndices<'_>>,
-    f: &impl Fn(String, &Range<usize>, bool),
-) {
-    let mut tag_name = String::new();
-    let mut is_closing = false;
-    let mut prev_pos = start_pos;
+/// Parse html tags to ensure they are well-formed
+#[derive(Debug, Clone)]
+struct TagParser {
+    tags: Vec<(String, Range<usize>)>,
+    /// Name of the tag that is being parsed, if we are within a tag.
+    ///
+    /// Since the `<` and name of a tag must appear on the same line with no whitespace,
+    /// if this is the empty string, we are not in a tag.
+    tag_name: String,
+    tag_start_pos: usize,
+    is_closing: bool,
+    /// `true` if we are within a tag, but not within its name.
+    in_attrs: bool,
+    /// If we are in a quoted attribute, what quote char does it use?
+    ///
+    /// This needs to be stored in the struct since HTML5 allows newlines in quoted attrs.
+    quote: Option<char>,
+    quote_pos: Option<usize>,
+    after_eq: bool,
+}
 
-    loop {
-        let (pos, c) = match iter.peek() {
-            Some((pos, c)) => (*pos, *c),
-            // In case we reached the of the doc comment, we want to check that it's an
-            // unclosed HTML tag. For example "/// <h3".
-            None => (prev_pos, '\0'),
-        };
-        prev_pos = pos;
-        // Checking if this is a closing tag (like `</a>` for `<a>`).
-        if c == '/' && tag_name.is_empty() {
-            is_closing = true;
-        } else if is_valid_for_html_tag_name(c, tag_name.is_empty()) {
-            tag_name.push(c);
-        } else {
-            if !tag_name.is_empty() {
-                let mut r = Range { start: range.start + start_pos, end: range.start + pos };
-                if c == '>' {
-                    // In case we have a tag without attribute, we can consider the span to
-                    // refer to it fully.
-                    r.end += 1;
+impl TagParser {
+    fn new() -> Self {
+        Self {
+            tags: Vec::new(),
+            tag_name: String::with_capacity(8),
+            tag_start_pos: 0,
+            is_closing: false,
+            in_attrs: false,
+            quote: None,
+            quote_pos: None,
+            after_eq: false,
+        }
+    }
+
+    fn drop_tag(&mut self, range: Range<usize>, f: &impl Fn(String, &Range<usize>, bool)) {
+        let tag_name_low = self.tag_name.to_lowercase();
+        if let Some(pos) = self.tags.iter().rposition(|(t, _)| t.to_lowercase() == tag_name_low) {
+            // If the tag is nested inside a "<script>" or a "<style>" tag, no warning should
+            // be emitted.
+            let should_not_warn = self.tags.iter().take(pos + 1).any(|(at, _)| {
+                let at = at.to_lowercase();
+                at == "script" || at == "style"
+            });
+            for (last_tag_name, last_tag_span) in self.tags.drain(pos + 1..) {
+                if should_not_warn {
+                    continue;
                 }
-                if is_closing {
-                    // In case we have "</div >" or even "</div         >".
-                    if c != '>' {
-                        if !c.is_whitespace() {
-                            // It seems like it's not a valid HTML tag.
-                            break;
-                        }
-                        let mut found = false;
-                        for (new_pos, c) in text[pos..].char_indices() {
+                let last_tag_name_low = last_tag_name.to_lowercase();
+                if is_implicitly_self_closing(&last_tag_name_low) {
+                    continue;
+                }
+                // `tags` is used as a queue, meaning that everything after `pos` is included inside it.
+                // So `<h2><h3></h2>` will look like `["h2", "h3"]`. So when closing `h2`, we will still
+                // have `h3`, meaning the tag wasn't closed as it should have.
+                f(format!("unclosed HTML tag `{last_tag_name}`"), &last_tag_span, true);
+            }
+            // Remove the `tag_name` that was originally closed
+            self.tags.pop();
+        } else {
+            // It can happen for example in this case: `<h2></script></h2>` (the `h2` tag isn't required
+            // but it helps for the visualization).
+            f(format!("unopened HTML tag `{}`", &self.tag_name), &range, false);
+        }
+    }
+
+    /// Handle a `<` that appeared while parsing a tag.
+    fn handle_lt_in_tag(
+        &mut self,
+        range: Range<usize>,
+        lt_pos: usize,
+        f: &impl Fn(String, &Range<usize>, bool),
+    ) {
+        let global_pos = range.start + lt_pos;
+        // is this check needed?
+        if global_pos == self.tag_start_pos {
+            // `<` is in the tag because it is the start.
+            return;
+        }
+        // tried to start a new tag while in a tag
+        f(
+            format!("incomplete HTML tag `{}`", &self.tag_name),
+            &(self.tag_start_pos..global_pos),
+            false,
+        );
+        self.tag_parsed();
+    }
+
+    fn extract_html_tag(
+        &mut self,
+        text: &str,
+        range: &Range<usize>,
+        start_pos: usize,
+        iter: &mut Peekable<CharIndices<'_>>,
+        f: &impl Fn(String, &Range<usize>, bool),
+    ) {
+        let mut prev_pos = start_pos;
+
+        'outer_loop: loop {
+            let (pos, c) = match iter.peek() {
+                Some((pos, c)) => (*pos, *c),
+                // In case we reached the of the doc comment, we want to check that it's an
+                // unclosed HTML tag. For example "/// <h3".
+                None if self.tag_name.is_empty() => (prev_pos, '\0'),
+                None => break,
+            };
+            prev_pos = pos;
+            if c == '/' && self.tag_name.is_empty() {
+                // Checking if this is a closing tag (like `</a>` for `<a>`).
+                self.is_closing = true;
+            } else if !self.in_attrs && is_valid_for_html_tag_name(c, self.tag_name.is_empty()) {
+                self.tag_name.push(c);
+            } else {
+                if !self.tag_name.is_empty() {
+                    self.in_attrs = true;
+                    let mut r = Range { start: range.start + start_pos, end: range.start + pos };
+                    if c == '>' {
+                        // In case we have a tag without attribute, we can consider the span to
+                        // refer to it fully.
+                        r.end += 1;
+                    }
+                    if self.is_closing {
+                        // In case we have "</div >" or even "</div         >".
+                        if c != '>' {
                             if !c.is_whitespace() {
-                                if c == '>' {
-                                    r.end = range.start + new_pos + 1;
-                                    found = true;
-                                }
+                                // It seems like it's not a valid HTML tag.
                                 break;
                             }
-                        }
-                        if !found {
-                            break;
-                        }
-                    }
-                    drop_tag(tags, tag_name, r, f);
-                } else {
-                    let mut is_self_closing = false;
-                    let mut quote_pos = None;
-                    if c != '>' {
-                        let mut quote = None;
-                        let mut after_eq = false;
-                        for (i, c) in text[pos..].char_indices() {
-                            if !c.is_whitespace() {
-                                if let Some(q) = quote {
-                                    if c == q {
-                                        quote = None;
-                                        quote_pos = None;
-                                        after_eq = false;
+                            let mut found = false;
+                            for (new_pos, c) in text[pos..].char_indices() {
+                                if !c.is_whitespace() {
+                                    if c == '>' {
+                                        r.end = range.start + new_pos + 1;
+                                        found = true;
+                                    } else if c == '<' {
+                                        self.handle_lt_in_tag(range.clone(), pos + new_pos, f);
                                     }
-                                } else if c == '>' {
                                     break;
-                                } else if c == '/' && !after_eq {
-                                    is_self_closing = true;
-                                } else {
-                                    if is_self_closing {
-                                        is_self_closing = false;
-                                    }
-                                    if (c == '"' || c == '\'') && after_eq {
-                                        quote = Some(c);
-                                        quote_pos = Some(pos + i);
-                                    } else if c == '=' {
-                                        after_eq = true;
-                                    }
                                 }
-                            } else if quote.is_none() {
-                                after_eq = false;
+                            }
+                            if !found {
+                                break 'outer_loop;
                             }
                         }
-                    }
-                    if let Some(quote_pos) = quote_pos {
-                        let qr = Range { start: quote_pos, end: quote_pos };
-                        f(
-                            format!("unclosed quoted HTML attribute on tag `{tag_name}`"),
-                            &qr,
-                            false,
-                        );
-                    }
-                    if is_self_closing {
-                        // https://html.spec.whatwg.org/#parse-error-non-void-html-element-start-tag-with-trailing-solidus
-                        let valid = ALLOWED_UNCLOSED.contains(&&tag_name[..])
-                            || tags.iter().take(pos + 1).any(|(at, _)| {
-                                let at = at.to_lowercase();
-                                at == "svg" || at == "math"
-                            });
-                        if !valid {
-                            f(format!("invalid self-closing HTML tag `{tag_name}`"), &r, false);
-                        }
+                        self.drop_tag(r, f);
+                        self.tag_parsed();
                     } else {
-                        tags.push((tag_name, r));
+                        self.extract_opening_tag(text, range, r, pos, c, iter, f)
                     }
                 }
+                break;
             }
-            break;
+            iter.next();
         }
-        iter.next();
     }
-}
-
-fn extract_tags(
-    tags: &mut Vec<(String, Range<usize>)>,
-    text: &str,
-    range: Range<usize>,
-    is_in_comment: &mut Option<Range<usize>>,
-    f: &impl Fn(String, &Range<usize>, bool),
-) {
-    let mut iter = text.char_indices().peekable();
 
-    while let Some((start_pos, c)) = iter.next() {
-        if is_in_comment.is_some() {
-            if text[start_pos..].starts_with("-->") {
-                *is_in_comment = None;
+    fn extract_opening_tag(
+        &mut self,
+        text: &str,
+        range: &Range<usize>,
+        r: Range<usize>,
+        pos: usize,
+        c: char,
+        iter: &mut Peekable<CharIndices<'_>>,
+        f: &impl Fn(String, &Range<usize>, bool),
+    ) {
+        // we can store this as a local, since html5 does require the `/` and `>`
+        // to not be separated by whitespace.
+        let mut is_self_closing = false;
+        if c != '>' {
+            'parse_til_gt: {
+                for (i, c) in text[pos..].char_indices() {
+                    if !c.is_whitespace() {
+                        debug_assert_eq!(self.quote_pos.is_some(), self.quote.is_some());
+                        if let Some(q) = self.quote {
+                            if c == q {
+                                self.quote = None;
+                                self.quote_pos = None;
+                                self.after_eq = false;
+                            }
+                        } else if c == '>' {
+                            break 'parse_til_gt;
+                        } else if c == '<' {
+                            self.handle_lt_in_tag(range.clone(), pos + i, f);
+                        } else if c == '/' && !self.after_eq {
+                            is_self_closing = true;
+                        } else {
+                            if is_self_closing {
+                                is_self_closing = false;
+                            }
+                            if (c == '"' || c == '\'') && self.after_eq {
+                                self.quote = Some(c);
+                                self.quote_pos = Some(pos + i);
+                            } else if c == '=' {
+                                self.after_eq = true;
+                            }
+                        }
+                    } else if self.quote.is_none() {
+                        self.after_eq = false;
+                    }
+                    if !is_self_closing && !self.tag_name.is_empty() {
+                        iter.next();
+                    }
+                }
+                // if we've run out of text but still haven't found a `>`,
+                // return early without calling `tag_parsed` or emitting lints.
+                // this allows us to either find the `>` in a later event
+                // or emit a lint about it being missing.
+                return;
             }
-        } else if c == '<' {
-            if text[start_pos..].starts_with("<!--") {
-                // We skip the "!--" part. (Once `advance_by` is stable, might be nice to use it!)
-                iter.next();
-                iter.next();
-                iter.next();
-                *is_in_comment = Some(Range {
-                    start: range.start + start_pos,
-                    end: range.start + start_pos + 3,
+        }
+        if is_self_closing {
+            // https://html.spec.whatwg.org/#parse-error-non-void-html-element-start-tag-with-trailing-solidus
+            let valid = ALLOWED_UNCLOSED.contains(&&self.tag_name[..])
+                || self.tags.iter().take(pos + 1).any(|(at, _)| {
+                    let at = at.to_lowercase();
+                    at == "svg" || at == "math"
                 });
-            } else {
-                extract_html_tag(tags, text, &range, start_pos, &mut iter, f);
+            if !valid {
+                f(format!("invalid self-closing HTML tag `{}`", self.tag_name), &r, false);
+            }
+        } else if !self.tag_name.is_empty() {
+            self.tags.push((std::mem::take(&mut self.tag_name), r));
+        }
+        self.tag_parsed();
+    }
+    /// Finished parsing a tag, reset related data.
+    fn tag_parsed(&mut self) {
+        self.tag_name.clear();
+        self.is_closing = false;
+        self.in_attrs = false;
+    }
+
+    fn extract_tags(
+        &mut self,
+        text: &str,
+        range: Range<usize>,
+        is_in_comment: &mut Option<Range<usize>>,
+        f: &impl Fn(String, &Range<usize>, bool),
+    ) {
+        let mut iter = text.char_indices().peekable();
+        let mut prev_pos = 0;
+        loop {
+            if self.quote.is_some() {
+                debug_assert!(self.in_attrs && self.quote_pos.is_some());
+            }
+            if self.in_attrs
+                && let Some(&(start_pos, _)) = iter.peek()
+            {
+                self.extract_html_tag(text, &range, start_pos, &mut iter, f);
+                // if no progress is being made, move forward forcefully.
+                if prev_pos == start_pos {
+                    iter.next();
+                }
+                prev_pos = start_pos;
+                continue;
+            }
+            let Some((start_pos, c)) = iter.next() else { break };
+            if is_in_comment.is_some() {
+                if text[start_pos..].starts_with("-->") {
+                    *is_in_comment = None;
+                }
+            } else if c == '<' {
+                // "<!--" is a valid attribute name under html5, so don't treat it as a comment if we're in a tag.
+                if self.tag_name.is_empty() && text[start_pos..].starts_with("<!--") {
+                    // We skip the "!--" part. (Once `advance_by` is stable, might be nice to use it!)
+                    iter.next();
+                    iter.next();
+                    iter.next();
+                    *is_in_comment = Some(Range {
+                        start: range.start + start_pos,
+                        end: range.start + start_pos + 4,
+                    });
+                } else {
+                    if self.tag_name.is_empty() {
+                        self.tag_start_pos = range.start + start_pos;
+                    }
+                    self.extract_html_tag(text, &range, start_pos, &mut iter, f);
+                }
+            } else if !self.tag_name.is_empty() {
+                // partially inside html tag that spans across events
+                self.extract_html_tag(text, &range, start_pos, &mut iter, f);
             }
         }
     }
 }
+
+#[cfg(test)]
+mod tests;
diff --git a/src/librustdoc/passes/lint/html_tags/tests.rs b/src/librustdoc/passes/lint/html_tags/tests.rs
new file mode 100644
index 00000000000..81c1d21a55d
--- /dev/null
+++ b/src/librustdoc/passes/lint/html_tags/tests.rs
@@ -0,0 +1,73 @@
+use std::cell::RefCell;
+
+use super::*;
+
+#[test]
+fn test_extract_tags_nested_unclosed() {
+    let mut tagp = TagParser::new();
+    let diags = RefCell::new(Vec::new());
+    let dox = "<div>\n<br</div>";
+    tagp.extract_tags(dox, 0..dox.len(), &mut None, &|s, r, b| {
+        diags.borrow_mut().push((s, r.clone(), b));
+    });
+    assert_eq!(diags.borrow().len(), 1, "did not get expected diagnostics: {diags:?}");
+    assert_eq!(diags.borrow()[0].1, 6..9)
+}
+
+#[test]
+fn test_extract_tags_taglike_in_attr() {
+    let mut tagp = TagParser::new();
+    let diags = RefCell::new(Vec::new());
+    let dox = "<img src='<div>'>";
+    tagp.extract_tags(dox, 0..dox.len(), &mut None, &|s, r, b| {
+        diags.borrow_mut().push((s, r.clone(), b));
+    });
+    assert_eq!(diags.borrow().len(), 0, "unexpected diagnostics: {diags:?}");
+}
+
+#[test]
+fn test_extract_tags_taglike_in_multiline_attr() {
+    let mut tagp = TagParser::new();
+    let diags = RefCell::new(Vec::new());
+    let dox = "<img src=\"\nasd\n<div>\n\">";
+    tagp.extract_tags(dox, 0..dox.len(), &mut None, &|s, r, b| {
+        diags.borrow_mut().push((s, r.clone(), b));
+    });
+    assert_eq!(diags.borrow().len(), 0, "unexpected diagnostics: {diags:?}");
+}
+
+#[test]
+fn test_extract_tags_taglike_in_multievent_attr() {
+    let mut tagp = TagParser::new();
+    let diags = RefCell::new(Vec::new());
+    let dox = "<img src='<div>'>";
+    let split_point = 10;
+    let mut p = |range: Range<usize>| {
+        tagp.extract_tags(&dox[range.clone()], range, &mut None, &|s, r, b| {
+            diags.borrow_mut().push((s, r.clone(), b));
+        })
+    };
+    p(0..split_point);
+    p(split_point..dox.len());
+    assert_eq!(diags.borrow().len(), 0, "unexpected diagnostics: {diags:?}");
+}
+
+#[test]
+fn test_extract_tags_taglike_in_multiline_multievent_attr() {
+    let mut tagp = TagParser::new();
+    let diags = RefCell::new(Vec::new());
+    let dox = "<img src='\n foo:\n </div>\n <p/>\n <div>\n'>";
+    let mut p = |range: Range<usize>| {
+        tagp.extract_tags(&dox[range.clone()], range, &mut None, &|s, r, b| {
+            diags.borrow_mut().push((s, r.clone(), b));
+        })
+    };
+    let mut offset = 0;
+    for ln in dox.split_inclusive('\n') {
+        let new_offset = offset + ln.len();
+        p(offset..new_offset);
+        offset = new_offset;
+    }
+    assert_eq!(diags.borrow().len(), 0, "unexpected diagnostics: {diags:?}");
+    assert_eq!(tagp.tags.len(), 1);
+}
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index 9f71d6ae789..16034c11827 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -18,7 +18,6 @@ use rustc_span::edition::Edition;
 use rustc_span::{BytePos, FileName, SourceFile};
 use tracing::{debug, trace, warn};
 
-use crate::formats::renderer::FormatRenderer;
 use crate::html::render::Context;
 use crate::{clean, config, formats};
 
@@ -276,7 +275,8 @@ pub(crate) fn run(
     let inner = move || -> Result<(), String> {
         // Generates source files for examples
         renderopts.no_emit_shared = true;
-        let (cx, _) = Context::init(krate, renderopts, cache, tcx).map_err(|e| e.to_string())?;
+        let (cx, _) = Context::init(krate, renderopts, cache, tcx, Default::default())
+            .map_err(|e| e.to_string())?;
 
         // Collect CrateIds corresponding to provided target crates
         // If two different versions of the crate in the dependency tree, then examples will be
diff --git a/src/llvm-project b/src/llvm-project
-Subproject 9a1f898064f52269bc94675dcbd620b46d45d17
+Subproject 19f0a49c5c3f4ba88b5e7ac620b9a0d8574c09c
diff --git a/src/tools/build-manifest/Cargo.toml b/src/tools/build-manifest/Cargo.toml
index 7e0c4bee2b3..efa99f181b3 100644
--- a/src/tools/build-manifest/Cargo.toml
+++ b/src/tools/build-manifest/Cargo.toml
@@ -4,7 +4,7 @@ version = "0.1.0"
 edition = "2021"
 
 [dependencies]
-toml = "0.5"
+toml = "0.7"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
 anyhow = "1.0.32"
diff --git a/src/tools/bump-stage0/Cargo.toml b/src/tools/bump-stage0/Cargo.toml
index 6ee7a831839..b7f3625da91 100644
--- a/src/tools/bump-stage0/Cargo.toml
+++ b/src/tools/bump-stage0/Cargo.toml
@@ -11,4 +11,4 @@ build_helper = { path = "../../build_helper" }
 curl = "0.4.38"
 indexmap = { version = "2.0.0", features = ["serde"] }
 serde = { version = "1.0.125", features = ["derive"] }
-toml = "0.5.7"
+toml = "0.7"
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 623d536836b4cde09ce38609232a024d5b25da8
+Subproject a6c58d43051d01d83f55a3e61ef5f5b2b0dd6bd
diff --git a/src/tools/clippy/Cargo.toml b/src/tools/clippy/Cargo.toml
index 2add525b7e8..b3618932ded 100644
--- a/src/tools/clippy/Cargo.toml
+++ b/src/tools/clippy/Cargo.toml
@@ -65,13 +65,6 @@ harness = false
 name = "dogfood"
 harness = false
 
-# quine-mc_cluskey makes up a significant part of the runtime in dogfood
-# due to the number of conditions in the clippy_lints crate
-# and enabling optimizations for that specific dependency helps a bit
-# without increasing total build times.
-[profile.dev.package.quine-mc_cluskey]
-opt-level = 3
-
 [lints.rust.unexpected_cfgs]
 level = "warn"
 check-cfg = ['cfg(bootstrap)']
diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs
index b16924babd1..d02952eb487 100644
--- a/src/tools/clippy/clippy_lints/src/missing_inline.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs
@@ -190,5 +190,5 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
 /// and a rustc warning would be triggered, see #15301
 fn fn_is_externally_exported(cx: &LateContext<'_>, def_id: DefId) -> bool {
     let attrs = cx.tcx.codegen_fn_attrs(def_id);
-    attrs.contains_extern_indicator(cx.tcx, def_id)
+    attrs.contains_extern_indicator()
 }
diff --git a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
index ec5fb2793f9..b898920baef 100644
--- a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
+++ b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs
@@ -49,17 +49,7 @@ pub(super) fn check<'tcx>(
             true
         },
         (ty::Int(_) | ty::Uint(_), ty::RawPtr(_, _)) => {
-            span_lint_and_then(
-                cx,
-                USELESS_TRANSMUTE,
-                e.span,
-                "transmute from an integer to a pointer",
-                |diag| {
-                    if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) {
-                        diag.span_suggestion(e.span, "try", arg.as_ty(to_ty.to_string()), Applicability::Unspecified);
-                    }
-                },
-            );
+            // Handled by the upstream rustc `integer_to_ptr_transmutes` lint
             true
         },
         _ => false,
diff --git a/src/tools/clippy/tests/ui/ptr_arg.stderr b/src/tools/clippy/tests/ui/ptr_arg.stderr
index 87235057349..f32e83d8b81 100644
--- a/src/tools/clippy/tests/ui/ptr_arg.stderr
+++ b/src/tools/clippy/tests/ui/ptr_arg.stderr
@@ -268,10 +268,10 @@ LL |     fn barbar(_x: &mut Vec<u32>, y: &mut String) {
    |                                     ^^^^^^^^^^^ help: change this to: `&mut str`
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> tests/ui/ptr_arg.rs:314:36
+  --> tests/ui/ptr_arg.rs:314:56
    |
 LL |     fn cow_good_ret_ty<'a>(input: &'a Cow<'a, str>) -> &str {
-   |                                    ^^     ^^           ---- the same lifetime is elided here
+   |                                    --     --           ^^^^ the same lifetime is elided here
    |                                    |      |
    |                                    |      the lifetime is named here
    |                                    the lifetime is named here
diff --git a/src/tools/clippy/tests/ui/transmute.rs b/src/tools/clippy/tests/ui/transmute.rs
index e968e7a5924..e7099104f94 100644
--- a/src/tools/clippy/tests/ui/transmute.rs
+++ b/src/tools/clippy/tests/ui/transmute.rs
@@ -4,6 +4,7 @@
     dead_code,
     clippy::borrow_as_ptr,
     unnecessary_transmutes,
+    integer_to_ptr_transmutes,
     clippy::needless_lifetimes,
     clippy::missing_transmute_annotations
 )]
@@ -60,12 +61,10 @@ fn useless() {
         //~^ useless_transmute
 
         let _: *const usize = std::mem::transmute(5_isize);
-        //~^ useless_transmute
 
         let _ = std::ptr::dangling::<usize>();
 
         let _: *const usize = std::mem::transmute(1 + 1usize);
-        //~^ useless_transmute
 
         let _ = (1 + 1_usize) as *const usize;
     }
diff --git a/src/tools/clippy/tests/ui/transmute.stderr b/src/tools/clippy/tests/ui/transmute.stderr
index 79528ec06f1..9478db09481 100644
--- a/src/tools/clippy/tests/ui/transmute.stderr
+++ b/src/tools/clippy/tests/ui/transmute.stderr
@@ -1,5 +1,5 @@
 error: transmute from a reference to a pointer
-  --> tests/ui/transmute.rs:33:27
+  --> tests/ui/transmute.rs:34:27
    |
 LL |         let _: *const T = core::mem::transmute(t);
    |                           ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T`
@@ -8,61 +8,49 @@ LL |         let _: *const T = core::mem::transmute(t);
    = help: to override `-D warnings` add `#[allow(clippy::useless_transmute)]`
 
 error: transmute from a reference to a pointer
-  --> tests/ui/transmute.rs:36:25
+  --> tests/ui/transmute.rs:37:25
    |
 LL |         let _: *mut T = core::mem::transmute(t);
    |                         ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *mut T`
 
 error: transmute from a reference to a pointer
-  --> tests/ui/transmute.rs:39:27
+  --> tests/ui/transmute.rs:40:27
    |
 LL |         let _: *const U = core::mem::transmute(t);
    |                           ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *const U`
 
 error: transmute from a type (`std::vec::Vec<i32>`) to itself
-  --> tests/ui/transmute.rs:47:27
+  --> tests/ui/transmute.rs:48:27
    |
 LL |         let _: Vec<i32> = core::mem::transmute(my_vec());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`std::vec::Vec<i32>`) to itself
-  --> tests/ui/transmute.rs:50:27
+  --> tests/ui/transmute.rs:51:27
    |
 LL |         let _: Vec<i32> = core::mem::transmute(my_vec());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`std::vec::Vec<i32>`) to itself
-  --> tests/ui/transmute.rs:53:27
+  --> tests/ui/transmute.rs:54:27
    |
 LL |         let _: Vec<i32> = std::mem::transmute(my_vec());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`std::vec::Vec<i32>`) to itself
-  --> tests/ui/transmute.rs:56:27
+  --> tests/ui/transmute.rs:57:27
    |
 LL |         let _: Vec<i32> = std::mem::transmute(my_vec());
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`std::vec::Vec<i32>`) to itself
-  --> tests/ui/transmute.rs:59:27
+  --> tests/ui/transmute.rs:60:27
    |
 LL |         let _: Vec<i32> = my_transmute(my_vec());
    |                           ^^^^^^^^^^^^^^^^^^^^^^
 
-error: transmute from an integer to a pointer
-  --> tests/ui/transmute.rs:62:31
-   |
-LL |         let _: *const usize = std::mem::transmute(5_isize);
-   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `5_isize as *const usize`
-
-error: transmute from an integer to a pointer
-  --> tests/ui/transmute.rs:67:31
-   |
-LL |         let _: *const usize = std::mem::transmute(1 + 1usize);
-   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(1 + 1usize) as *const usize`
-
 error: transmute from a type (`*const Usize`) to the type that it points to (`Usize`)
-  --> tests/ui/transmute.rs:99:24
+  --> tests/ui/transmute.rs:98:24
    |
 LL |         let _: Usize = core::mem::transmute(int_const_ptr);
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -71,25 +59,25 @@ LL |         let _: Usize = core::mem::transmute(int_const_ptr);
    = help: to override `-D warnings` add `#[allow(clippy::crosspointer_transmute)]`
 
 error: transmute from a type (`*mut Usize`) to the type that it points to (`Usize`)
-  --> tests/ui/transmute.rs:102:24
+  --> tests/ui/transmute.rs:101:24
    |
 LL |         let _: Usize = core::mem::transmute(int_mut_ptr);
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`Usize`) to a pointer to that type (`*const Usize`)
-  --> tests/ui/transmute.rs:105:31
+  --> tests/ui/transmute.rs:104:31
    |
 LL |         let _: *const Usize = core::mem::transmute(my_int());
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a type (`Usize`) to a pointer to that type (`*mut Usize`)
-  --> tests/ui/transmute.rs:108:29
+  --> tests/ui/transmute.rs:107:29
    |
 LL |         let _: *mut Usize = core::mem::transmute(my_int());
    |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: transmute from a `u8` to a `bool`
-  --> tests/ui/transmute.rs:115:28
+  --> tests/ui/transmute.rs:114:28
    |
 LL |     let _: bool = unsafe { std::mem::transmute(0_u8) };
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0`
@@ -98,7 +86,7 @@ LL |     let _: bool = unsafe { std::mem::transmute(0_u8) };
    = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_bool)]`
 
 error: transmute from a `&[u8]` to a `&str`
-  --> tests/ui/transmute.rs:122:28
+  --> tests/ui/transmute.rs:121:28
    |
 LL |     let _: &str = unsafe { std::mem::transmute(B) };
    |                            ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(B).unwrap()`
@@ -107,16 +95,16 @@ LL |     let _: &str = unsafe { std::mem::transmute(B) };
    = help: to override `-D warnings` add `#[allow(clippy::transmute_bytes_to_str)]`
 
 error: transmute from a `&mut [u8]` to a `&mut str`
-  --> tests/ui/transmute.rs:125:32
+  --> tests/ui/transmute.rs:124:32
    |
 LL |     let _: &mut str = unsafe { std::mem::transmute(mb) };
    |                                ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()`
 
 error: transmute from a `&[u8]` to a `&str`
-  --> tests/ui/transmute.rs:128:30
+  --> tests/ui/transmute.rs:127:30
    |
 LL |     const _: &str = unsafe { std::mem::transmute(B) };
    |                              ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_unchecked(B)`
 
-error: aborting due to 18 previous errors
+error: aborting due to 16 previous errors
 
diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed
index e7ad2a1cbbc..02f67f79e2b 100644
--- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed
+++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed
@@ -13,9 +13,6 @@ fn main() {
     // We should see an error message for each transmute, and no error messages for
     // the casts, since the casts are the recommended fixes.
 
-    // e is an integer and U is *U_0, while U_0: Sized; addr-ptr-cast
-    let _ptr_i32_transmute = unsafe { usize::MAX as *const i32 };
-    //~^ useless_transmute
     let ptr_i32 = usize::MAX as *const i32;
 
     // e has type *T, U is *U_0, and either U_0: Sized ...
diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs
index 42a81777a82..c5e156405eb 100644
--- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs
+++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs
@@ -13,9 +13,6 @@ fn main() {
     // We should see an error message for each transmute, and no error messages for
     // the casts, since the casts are the recommended fixes.
 
-    // e is an integer and U is *U_0, while U_0: Sized; addr-ptr-cast
-    let _ptr_i32_transmute = unsafe { transmute::<usize, *const i32>(usize::MAX) };
-    //~^ useless_transmute
     let ptr_i32 = usize::MAX as *const i32;
 
     // e has type *T, U is *U_0, and either U_0: Sized ...
diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr
index 7746f087cc7..f39a64d57eb 100644
--- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr
+++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr
@@ -1,14 +1,5 @@
-error: transmute from an integer to a pointer
-  --> tests/ui/transmutes_expressible_as_ptr_casts.rs:17:39
-   |
-LL |     let _ptr_i32_transmute = unsafe { transmute::<usize, *const i32>(usize::MAX) };
-   |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `usize::MAX as *const i32`
-   |
-   = note: `-D clippy::useless-transmute` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::useless_transmute)]`
-
 error: transmute from a pointer to a pointer
-  --> tests/ui/transmutes_expressible_as_ptr_casts.rs:22:38
+  --> tests/ui/transmutes_expressible_as_ptr_casts.rs:19:38
    |
 LL |     let _ptr_i8_transmute = unsafe { transmute::<*const i32, *const i8>(ptr_i32) };
    |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -22,7 +13,7 @@ LL +     let _ptr_i8_transmute = unsafe { ptr_i32.cast::<i8>() };
    |
 
 error: transmute from a pointer to a pointer
-  --> tests/ui/transmutes_expressible_as_ptr_casts.rs:29:46
+  --> tests/ui/transmutes_expressible_as_ptr_casts.rs:26:46
    |
 LL |     let _ptr_to_unsized_transmute = unsafe { transmute::<*const [i32], *const [u32]>(slice_ptr) };
    |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -34,7 +25,7 @@ LL +     let _ptr_to_unsized_transmute = unsafe { slice_ptr as *const [u32] };
    |
 
 error: transmute from `*const i32` to `usize` which could be expressed as a pointer cast instead
-  --> tests/ui/transmutes_expressible_as_ptr_casts.rs:36:50
+  --> tests/ui/transmutes_expressible_as_ptr_casts.rs:33:50
    |
 LL |     let _usize_from_int_ptr_transmute = unsafe { transmute::<*const i32, usize>(ptr_i32) };
    |                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr_i32 as usize`
@@ -43,40 +34,43 @@ LL |     let _usize_from_int_ptr_transmute = unsafe { transmute::<*const i32, us
    = help: to override `-D warnings` add `#[allow(clippy::transmutes_expressible_as_ptr_casts)]`
 
 error: transmute from a reference to a pointer
-  --> tests/ui/transmutes_expressible_as_ptr_casts.rs:43:41
+  --> tests/ui/transmutes_expressible_as_ptr_casts.rs:40:41
    |
 LL |     let _array_ptr_transmute = unsafe { transmute::<&[i32; 4], *const [i32; 4]>(array_ref) };
    |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `array_ref as *const [i32; 4]`
+   |
+   = note: `-D clippy::useless-transmute` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::useless_transmute)]`
 
 error: transmute from `fn(usize) -> u8` to `*const usize` which could be expressed as a pointer cast instead
-  --> tests/ui/transmutes_expressible_as_ptr_casts.rs:52:41
+  --> tests/ui/transmutes_expressible_as_ptr_casts.rs:49:41
    |
 LL |     let _usize_ptr_transmute = unsafe { transmute::<fn(usize) -> u8, *const usize>(foo) };
    |                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `foo as *const usize`
 
 error: transmute from `fn(usize) -> u8` to `usize` which could be expressed as a pointer cast instead
-  --> tests/ui/transmutes_expressible_as_ptr_casts.rs:57:49
+  --> tests/ui/transmutes_expressible_as_ptr_casts.rs:54:49
    |
 LL |     let _usize_from_fn_ptr_transmute = unsafe { transmute::<fn(usize) -> u8, usize>(foo) };
    |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `foo as usize`
 
 error: transmute from `*const u32` to `usize` which could be expressed as a pointer cast instead
-  --> tests/ui/transmutes_expressible_as_ptr_casts.rs:61:36
+  --> tests/ui/transmutes_expressible_as_ptr_casts.rs:58:36
    |
 LL |     let _usize_from_ref = unsafe { transmute::<*const u32, usize>(&1u32) };
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&1u32 as *const u32 as usize`
 
 error: transmute from a reference to a pointer
-  --> tests/ui/transmutes_expressible_as_ptr_casts.rs:73:14
+  --> tests/ui/transmutes_expressible_as_ptr_casts.rs:70:14
    |
 LL |     unsafe { transmute::<&[i32; 1], *const u8>(in_param) }
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `in_param as *const [i32; 1] as *const u8`
 
 error: transmute from `fn()` to `*const u8` which could be expressed as a pointer cast instead
-  --> tests/ui/transmutes_expressible_as_ptr_casts.rs:92:28
+  --> tests/ui/transmutes_expressible_as_ptr_casts.rs:89:28
    |
 LL |     let _x: u8 = unsafe { *std::mem::transmute::<fn(), *const u8>(f) };
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(f as *const u8)`
 
-error: aborting due to 10 previous errors
+error: aborting due to 9 previous errors
 
diff --git a/src/tools/compiletest/Cargo.toml b/src/tools/compiletest/Cargo.toml
index cdada5a2230..220c29cec49 100644
--- a/src/tools/compiletest/Cargo.toml
+++ b/src/tools/compiletest/Cargo.toml
@@ -28,8 +28,8 @@ rustfix = "0.8.1"
 semver = { version = "1.0.23", features = ["serde"] }
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
-tracing = "0.1"
 tracing-subscriber = { version = "0.3.3", default-features = false, features = ["ansi", "env-filter", "fmt", "parking_lot", "smallvec"] }
+tracing.workspace = true
 unified-diff = "0.2.1"
 walkdir = "2"
 # tidy-alphabetical-end
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 7fc80c1edb1..b72c0b7ed20 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -8,7 +8,7 @@ use camino::{Utf8Path, Utf8PathBuf};
 use semver::Version;
 use serde::de::{Deserialize, Deserializer, Error as _};
 
-use crate::executor::{ColorConfig, OutputFormat};
+use crate::executor::ColorConfig;
 use crate::fatal;
 use crate::util::{Utf8PathBufExt, add_dylib_path, string_enum};
 
@@ -565,13 +565,6 @@ pub struct Config {
     /// FIXME: this is *way* too coarse; the user can't select *which* info to verbosely dump.
     pub verbose: bool,
 
-    /// (Useless) Adjust libtest output format.
-    ///
-    /// FIXME: the hand-rolled executor does not support non-JSON output, because `compiletest` need
-    /// to package test outcome as `libtest`-esque JSON that `bootstrap` can intercept *anyway*.
-    /// However, now that we don't use the `libtest` executor, this is useless.
-    pub format: OutputFormat,
-
     /// Whether to use colors in test output.
     ///
     /// Note: the exact control mechanism is delegated to [`colored`].
@@ -768,7 +761,6 @@ impl Config {
             adb_device_status: Default::default(),
             lldb_python_dir: Default::default(),
             verbose: Default::default(),
-            format: Default::default(),
             color: Default::default(),
             remote_test_client: Default::default(),
             compare_mode: Default::default(),
diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs
index 00007aa1d66..f2ad049d526 100644
--- a/src/tools/compiletest/src/directives.rs
+++ b/src/tools/compiletest/src/directives.rs
@@ -205,6 +205,8 @@ pub struct TestProps {
     pub dont_require_annotations: HashSet<ErrorKind>,
     /// Whether pretty printers should be disabled in gdb.
     pub disable_gdb_pretty_printers: bool,
+    /// Compare the output by lines, rather than as a single string.
+    pub compare_output_by_lines: bool,
 }
 
 mod directives {
@@ -254,6 +256,7 @@ mod directives {
     // This isn't a real directive, just one that is probably mistyped often
     pub const INCORRECT_COMPILER_FLAGS: &'static str = "compiler-flags";
     pub const DISABLE_GDB_PRETTY_PRINTERS: &'static str = "disable-gdb-pretty-printers";
+    pub const COMPARE_OUTPUT_BY_LINES: &'static str = "compare-output-by-lines";
 }
 
 impl TestProps {
@@ -310,6 +313,7 @@ impl TestProps {
             add_core_stubs: false,
             dont_require_annotations: Default::default(),
             disable_gdb_pretty_printers: false,
+            compare_output_by_lines: false,
         }
     }
 
@@ -664,6 +668,11 @@ impl TestProps {
                         DISABLE_GDB_PRETTY_PRINTERS,
                         &mut self.disable_gdb_pretty_printers,
                     );
+                    config.set_name_directive(
+                        ln,
+                        COMPARE_OUTPUT_BY_LINES,
+                        &mut self.compare_output_by_lines,
+                    );
                 },
             );
 
diff --git a/src/tools/compiletest/src/directives/directive_names.rs b/src/tools/compiletest/src/directives/directive_names.rs
index 59690ff2602..0ef84fb4594 100644
--- a/src/tools/compiletest/src/directives/directive_names.rs
+++ b/src/tools/compiletest/src/directives/directive_names.rs
@@ -17,6 +17,7 @@ pub(crate) const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "check-run-results",
     "check-stdout",
     "check-test-line-numbers-match",
+    "compare-output-by-lines",
     "compile-flags",
     "disable-gdb-pretty-printers",
     "doc-flags",
diff --git a/src/tools/compiletest/src/executor.rs b/src/tools/compiletest/src/executor.rs
index df64f12784f..fdd7155c21f 100644
--- a/src/tools/compiletest/src/executor.rs
+++ b/src/tools/compiletest/src/executor.rs
@@ -1,5 +1,9 @@
 //! This module contains a reimplementation of the subset of libtest
 //! functionality needed by compiletest.
+//!
+//! FIXME(Zalathar): Much of this code was originally designed to mimic libtest
+//! as closely as possible, for ease of migration. Now that libtest is no longer
+//! used, we can potentially redesign things to be a better fit for compiletest.
 
 use std::borrow::Cow;
 use std::collections::HashMap;
@@ -207,7 +211,7 @@ impl TestOutcome {
 ///
 /// Adapted from `filter_tests` in libtest.
 ///
-/// FIXME(#139660): After the libtest dependency is removed, redesign the whole filtering system to
+/// FIXME(#139660): Now that libtest has been removed, redesign the whole filtering system to
 /// do a better job of understanding and filtering _paths_, instead of being tied to libtest's
 /// substring/exact matching behaviour.
 fn filter_tests(opts: &Config, tests: Vec<CollectedTest>) -> Vec<CollectedTest> {
@@ -249,7 +253,7 @@ fn get_concurrency() -> usize {
     }
 }
 
-/// Information needed to create a `test::TestDescAndFn`.
+/// Information that was historically needed to create a libtest `TestDescAndFn`.
 pub(crate) struct CollectedTest {
     pub(crate) desc: CollectedTestDesc,
     pub(crate) config: Arc<Config>,
@@ -257,7 +261,7 @@ pub(crate) struct CollectedTest {
     pub(crate) revision: Option<String>,
 }
 
-/// Information needed to create a `test::TestDesc`.
+/// Information that was historically needed to create a libtest `TestDesc`.
 pub(crate) struct CollectedTestDesc {
     pub(crate) name: String,
     pub(crate) ignore: bool,
@@ -274,18 +278,6 @@ pub enum ColorConfig {
     NeverColor,
 }
 
-/// Format of the test results output.
-#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
-pub enum OutputFormat {
-    /// Verbose output
-    Pretty,
-    /// Quiet output
-    #[default]
-    Terse,
-    /// JSON output
-    Json,
-}
-
 /// Whether test is expected to panic or not.
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 pub(crate) enum ShouldPanic {
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index 469dd68207e..58f7c6b5071 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -43,7 +43,7 @@ use crate::common::{
     expected_output_path, output_base_dir, output_relative_path,
 };
 use crate::directives::DirectivesCache;
-use crate::executor::{CollectedTest, ColorConfig, OutputFormat};
+use crate::executor::{CollectedTest, ColorConfig};
 use crate::util::logv;
 
 /// Creates the `Config` instance for this invocation of compiletest.
@@ -137,9 +137,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
             "overwrite stderr/stdout files instead of complaining about a mismatch",
         )
         .optflag("", "fail-fast", "stop as soon as possible after any test fails")
-        .optflag("", "quiet", "print one character per test instead of one line")
         .optopt("", "color", "coloring: auto, always, never", "WHEN")
-        .optflag("", "json", "emit json output instead of plaintext output")
         .optopt("", "target", "the target to build for", "TARGET")
         .optopt("", "host", "the host to build for", "HOST")
         .optopt("", "cdb", "path to CDB to use for CDB debuginfo tests", "PATH")
@@ -203,7 +201,6 @@ pub fn parse_config(args: Vec<String>) -> Config {
             "COMMAND",
         )
         .reqopt("", "minicore-path", "path to minicore aux library", "PATH")
-        .optflag("N", "no-new-executor", "disables the new test executor, and uses libtest instead")
         .optopt(
             "",
             "debugger",
@@ -436,12 +433,6 @@ pub fn parse_config(args: Vec<String>) -> Config {
             && !opt_str2(matches.opt_str("adb-test-dir")).is_empty(),
         lldb_python_dir: matches.opt_str("lldb-python-dir"),
         verbose: matches.opt_present("verbose"),
-        format: match (matches.opt_present("quiet"), matches.opt_present("json")) {
-            (true, true) => panic!("--quiet and --json are incompatible"),
-            (true, false) => OutputFormat::Terse,
-            (false, true) => OutputFormat::Json,
-            (false, false) => OutputFormat::Pretty,
-        },
         only_modified: matches.opt_present("only-modified"),
         color,
         remote_test_client: matches.opt_str("remote-test-client").map(Utf8PathBuf::from),
@@ -527,7 +518,6 @@ pub fn log_config(config: &Config) {
     logv(c, format!("target-linker: {:?}", config.target_linker));
     logv(c, format!("host-linker: {:?}", config.host_linker));
     logv(c, format!("verbose: {}", config.verbose));
-    logv(c, format!("format: {:?}", config.format));
     logv(c, format!("minicore_path: {}", config.minicore_path));
     logv(c, "\n".to_string());
 }
@@ -601,7 +591,7 @@ pub fn run_tests(config: Arc<Config>) {
         configs.push(config.clone());
     };
 
-    // Discover all of the tests in the test suite directory, and build a libtest
+    // Discover all of the tests in the test suite directory, and build a `CollectedTest`
     // structure for each test (or each revision of a multi-revision test).
     let mut tests = Vec::new();
     for c in configs {
@@ -613,50 +603,35 @@ pub fn run_tests(config: Arc<Config>) {
     // Delegate to the executor to filter and run the big list of test structures
     // created during test discovery. When the executor decides to run a test,
     // it will return control to the rest of compiletest by calling `runtest::run`.
-    // FIXME(Zalathar): Once we're confident that we won't need to revert the
-    // removal of the libtest-based executor, remove this Result and other
-    // remnants of the old executor.
-    let res: io::Result<bool> = Ok(executor::run_tests(&config, tests));
-
-    // Check the outcome reported by libtest.
-    match res {
-        Ok(true) => {}
-        Ok(false) => {
-            // We want to report that the tests failed, but we also want to give
-            // some indication of just what tests we were running. Especially on
-            // CI, where there can be cross-compiled tests for a lot of
-            // architectures, without this critical information it can be quite
-            // easy to miss which tests failed, and as such fail to reproduce
-            // the failure locally.
-
-            let mut msg = String::from("Some tests failed in compiletest");
-            write!(msg, " suite={}", config.suite).unwrap();
-
-            if let Some(compare_mode) = config.compare_mode.as_ref() {
-                write!(msg, " compare_mode={}", compare_mode).unwrap();
-            }
+    let ok = executor::run_tests(&config, tests);
+
+    // Check the outcome reported by the executor.
+    if !ok {
+        // We want to report that the tests failed, but we also want to give
+        // some indication of just what tests we were running. Especially on
+        // CI, where there can be cross-compiled tests for a lot of
+        // architectures, without this critical information it can be quite
+        // easy to miss which tests failed, and as such fail to reproduce
+        // the failure locally.
+
+        let mut msg = String::from("Some tests failed in compiletest");
+        write!(msg, " suite={}", config.suite).unwrap();
+
+        if let Some(compare_mode) = config.compare_mode.as_ref() {
+            write!(msg, " compare_mode={}", compare_mode).unwrap();
+        }
 
-            if let Some(pass_mode) = config.force_pass_mode.as_ref() {
-                write!(msg, " pass_mode={}", pass_mode).unwrap();
-            }
+        if let Some(pass_mode) = config.force_pass_mode.as_ref() {
+            write!(msg, " pass_mode={}", pass_mode).unwrap();
+        }
 
-            write!(msg, " mode={}", config.mode).unwrap();
-            write!(msg, " host={}", config.host).unwrap();
-            write!(msg, " target={}", config.target).unwrap();
+        write!(msg, " mode={}", config.mode).unwrap();
+        write!(msg, " host={}", config.host).unwrap();
+        write!(msg, " target={}", config.target).unwrap();
 
-            println!("{msg}");
+        println!("{msg}");
 
-            std::process::exit(1);
-        }
-        Err(e) => {
-            // We don't know if tests passed or not, but if there was an error
-            // during testing we don't want to just succeed (we may not have
-            // tested something), so fail.
-            //
-            // This should realistically "never" happen, so don't try to make
-            // this a pretty error message.
-            panic!("I/O failure during tests: {:?}", e);
-        }
+        std::process::exit(1);
     }
 }
 
@@ -691,7 +666,11 @@ impl TestCollector {
 ///
 /// This always inspects _all_ test files in the suite (e.g. all 17k+ ui tests),
 /// regardless of whether any filters/tests were specified on the command-line,
-/// because filtering is handled later by libtest.
+/// because filtering is handled later by code that was copied from libtest.
+///
+/// FIXME(Zalathar): Now that we no longer rely on libtest, try to overhaul
+/// test discovery to take into account the filters/tests specified on the
+/// command-line, instead of having to enumerate everything.
 pub(crate) fn collect_and_make_tests(config: Arc<Config>) -> Vec<CollectedTest> {
     debug!("making tests from {}", config.src_test_suite_root);
     let common_inputs_stamp = common_inputs_stamp(&config);
@@ -805,7 +784,7 @@ fn modified_tests(config: &Config, dir: &Utf8Path) -> Result<Vec<Utf8PathBuf>, S
 }
 
 /// Recursively scans a directory to find test files and create test structures
-/// that will be handed over to libtest.
+/// that will be handed over to the executor.
 fn collect_tests_from_dir(
     cx: &TestCollectorCx,
     dir: &Utf8Path,
@@ -871,7 +850,7 @@ fn collect_tests_from_dir(
             if is_test(file_name)
                 && (!cx.config.only_modified || cx.modified_tests.contains(&file_path))
             {
-                // We found a test file, so create the corresponding libtest structures.
+                // We found a test file, so create the corresponding test structures.
                 debug!(%file_path, "found test file");
 
                 // Record the stem of the test file, to check for overlaps later.
@@ -915,7 +894,7 @@ pub fn is_test(file_name: &str) -> bool {
 }
 
 /// For a single test file, creates one or more test structures (one per revision) that can be
-/// handed over to libtest to run, possibly in parallel.
+/// handed over to the executor to run, possibly in parallel.
 fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &TestPaths) {
     // For run-make tests, each "test file" is actually a _directory_ containing an `rmake.rs`. But
     // for the purposes of directive parsing, we want to look at that recipe file, not the directory
@@ -929,7 +908,7 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te
     // Scan the test file to discover its revisions, if any.
     let early_props = EarlyProps::from_file(&cx.config, &test_path);
 
-    // Normally we create one libtest structure per revision, with two exceptions:
+    // Normally we create one structure per revision, with two exceptions:
     // - If a test doesn't use revisions, create a dummy revision (None) so that
     //   the test can still run.
     // - Incremental tests inherently can't run their revisions in parallel, so
@@ -944,12 +923,12 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te
     // For each revision (or the sole dummy revision), create and append a
     // `CollectedTest` that can be handed over to the test executor.
     collector.tests.extend(revisions.into_iter().map(|revision| {
-        // Create a test name and description to hand over to libtest.
+        // Create a test name and description to hand over to the executor.
         let src_file = fs::File::open(&test_path).expect("open test file to parse ignores");
         let test_name = make_test_name(&cx.config, testpaths, revision);
-        // Create a libtest description for the test/revision.
+        // Create a description struct for the test/revision.
         // This is where `ignore-*`/`only-*`/`needs-*` directives are handled,
-        // because they need to set the libtest ignored flag.
+        // because they historically needed to set the libtest ignored flag.
         let mut desc = make_test_description(
             &cx.config,
             &cx.cache,
@@ -961,10 +940,12 @@ fn make_test(cx: &TestCollectorCx, collector: &mut TestCollector, testpaths: &Te
         );
 
         // If a test's inputs haven't changed since the last time it ran,
-        // mark it as ignored so that libtest will skip it.
+        // mark it as ignored so that the executor will skip it.
         if !cx.config.force_rerun && is_up_to_date(cx, testpaths, &early_props, revision) {
             desc.ignore = true;
             // Keep this in sync with the "up-to-date" message detected by bootstrap.
+            // FIXME(Zalathar): Now that we are no longer tied to libtest, we could
+            // find a less fragile way to communicate this status to bootstrap.
             desc.ignore_message = Some("up-to-date".into());
         }
 
@@ -1104,7 +1085,7 @@ impl Stamp {
     }
 }
 
-/// Creates a name for this test/revision that can be handed over to libtest.
+/// Creates a name for this test/revision that can be handed over to the executor.
 fn make_test_name(config: &Config, testpaths: &TestPaths, revision: Option<&str>) -> String {
     // Print the name of the file, relative to the sources root.
     let path = testpaths.file.strip_prefix(&config.src_root).unwrap();
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 2402ed9a950..3a05b242519 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -412,7 +412,7 @@ impl<'test> TestCx<'test> {
             cmdline: format!("{cmd:?}"),
         };
         self.dump_output(
-            self.config.verbose,
+            self.config.verbose || !proc_res.status.success(),
             &cmd.get_program().to_string_lossy(),
             &proc_res.stdout,
             &proc_res.stderr,
@@ -1486,7 +1486,7 @@ impl<'test> TestCx<'test> {
         };
 
         self.dump_output(
-            self.config.verbose,
+            self.config.verbose || (!result.status.success() && self.config.mode != TestMode::Ui),
             &command.get_program().to_string_lossy(),
             &result.stdout,
             &result.stderr,
@@ -2222,7 +2222,7 @@ impl<'test> TestCx<'test> {
                 .env("PAGER", "")
                 .stdin(File::open(&diff_filename).unwrap())
                 // Capture output and print it explicitly so it will in turn be
-                // captured by libtest.
+                // captured by output-capture.
                 .output()
                 .unwrap();
             assert!(output.status.success());
@@ -2754,7 +2754,11 @@ impl<'test> TestCx<'test> {
         // Wrapper tools set by `runner` might provide extra output on failure,
         // for example a WebAssembly runtime might print the stack trace of an
         // `unreachable` instruction by default.
-        let compare_output_by_lines = self.config.runner.is_some();
+        //
+        // Also, some tests like `ui/parallel-rustc` have non-deterministic
+        // orders of output, so we need to compare by lines.
+        let compare_output_by_lines =
+            self.props.compare_output_by_lines || self.config.runner.is_some();
 
         let tmp;
         let (expected, actual): (&str, &str) = if compare_output_by_lines {
@@ -2983,6 +2987,7 @@ struct ProcArgs {
     args: Vec<OsString>,
 }
 
+#[derive(Debug)]
 pub struct ProcRes {
     status: ExitStatus,
     stdout: String,
diff --git a/src/tools/compiletest/src/runtest/debuginfo.rs b/src/tools/compiletest/src/runtest/debuginfo.rs
index 6114afdc9df..24fdbab3aec 100644
--- a/src/tools/compiletest/src/runtest/debuginfo.rs
+++ b/src/tools/compiletest/src/runtest/debuginfo.rs
@@ -395,6 +395,35 @@ impl TestCx<'_> {
         // 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");
 
+        // macOS has a system for restricting access to files and peripherals
+        // called Transparency, Consent, and Control (TCC), which can be
+        // configured using the "Security & Privacy" tab in your settings.
+        //
+        // This system is provenance-based: if Terminal.app is given access to
+        // your Desktop, and you launch a binary within Terminal.app, the new
+        // binary also has access to the files on your Desktop.
+        //
+        // By default though, LLDB launches binaries in very isolated
+        // contexts. This includes resetting any TCC grants that might
+        // otherwise have been inherited.
+        //
+        // In effect, this means that if the developer has placed the rust
+        // repository under one of the system-protected folders, they will get
+        // a pop-up _for each binary_ asking for permissions to access the
+        // folder - quite annoying.
+        //
+        // To avoid this, we tell LLDB to spawn processes with TCC grants
+        // inherited from the parent process.
+        //
+        // Setting this also avoids unnecessary overhead from XprotectService
+        // when running with the Developer Tool grant.
+        //
+        // TIP: If you want to allow launching `lldb ~/Desktop/my_binary`
+        // without being prompted, you can put this in your `~/.lldbinit` too.
+        if self.config.host.contains("darwin") {
+            script_str.push_str("settings set target.inherit-tcc true\n");
+        }
+
         // Make LLDB emit its version, so we have it documented in the test output
         script_str.push_str("version\n");
 
diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs
index c8d5190c039..8a0e45cf8ca 100644
--- a/src/tools/compiletest/src/runtest/run_make.rs
+++ b/src/tools/compiletest/src/runtest/run_make.rs
@@ -308,7 +308,7 @@ impl TestCx<'_> {
         let stdout = String::from_utf8_lossy(&stdout).into_owned();
         let stderr = String::from_utf8_lossy(&stderr).into_owned();
         // This conditions on `status.success()` so we don't print output twice on error.
-        // NOTE: this code is called from a libtest thread, so it's hidden by default unless --nocapture is passed.
+        // NOTE: this code is called from an executor thread, so it's hidden by default unless --no-capture is passed.
         self.dump_output(status.success(), &cmd.get_program().to_string_lossy(), &stdout, &stderr);
         if !status.success() {
             let res = ProcRes { status, stdout, stderr, truncated, cmdline: format!("{:?}", cmd) };
diff --git a/src/tools/coverage-dump/Cargo.toml b/src/tools/coverage-dump/Cargo.toml
index 36a66f16030..2f703537b59 100644
--- a/src/tools/coverage-dump/Cargo.toml
+++ b/src/tools/coverage-dump/Cargo.toml
@@ -7,7 +7,7 @@ edition = "2021"
 
 [dependencies]
 anyhow = "1.0.71"
-itertools = "0.12"
+itertools.workspace = true
 leb128 = "0.2.5"
 md5 = { package = "md-5" , version = "0.10.5" }
 miniz_oxide = "0.8.8"
diff --git a/src/tools/llvm-bitcode-linker/Cargo.toml b/src/tools/llvm-bitcode-linker/Cargo.toml
index a9210b562f3..f78f8b618d3 100644
--- a/src/tools/llvm-bitcode-linker/Cargo.toml
+++ b/src/tools/llvm-bitcode-linker/Cargo.toml
@@ -8,7 +8,7 @@ publish = false
 
 [dependencies]
 anyhow = "1.0"
-tracing = "0.1"
-tracing-subscriber = {version = "0.3.0", features = ["std"] }
+tracing.workspace = true
+tracing-subscriber = { version = "0.3.0", features = ["std"] }
 clap = { version = "4.3", features = ["derive"] }
 thiserror = "1.0.24"
diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs
index d9e374c414c..ae1b25f8857 100644
--- a/src/tools/miri/src/bin/miri.rs
+++ b/src/tools/miri/src/bin/miri.rs
@@ -279,7 +279,7 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls {
                                 return None;
                             }
                             let codegen_fn_attrs = tcx.codegen_fn_attrs(local_def_id);
-                            if codegen_fn_attrs.contains_extern_indicator(tcx, local_def_id.into())
+                            if codegen_fn_attrs.contains_extern_indicator()
                                 || codegen_fn_attrs
                                     .flags
                                     .contains(CodegenFnAttrFlags::USED_COMPILER)
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index 1b5d9d50996..e0c077e9931 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -134,8 +134,7 @@ pub fn iter_exported_symbols<'tcx>(
     for def_id in crate_items.definitions() {
         let exported = tcx.def_kind(def_id).has_codegen_attrs() && {
             let codegen_attrs = tcx.codegen_fn_attrs(def_id);
-            codegen_attrs.contains_extern_indicator(tcx, def_id.into())
-                || codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
+            codegen_attrs.contains_extern_indicator()
                 || codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER)
                 || codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
         };
diff --git a/src/tools/miri/src/shims/native_lib/mod.rs b/src/tools/miri/src/shims/native_lib/mod.rs
index e2a0bdbd9b4..74b9b704fea 100644
--- a/src/tools/miri/src/shims/native_lib/mod.rs
+++ b/src/tools/miri/src/shims/native_lib/mod.rs
@@ -242,14 +242,9 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
 
                 match evt {
                     AccessEvent::Read(_) => {
-                        // FIXME: ProvenanceMap should have something like get_range().
-                        let p_map = alloc.provenance();
-                        for idx in overlap {
-                            // If a provenance was read by the foreign code, expose it.
-                            if let Some((prov, _idx)) = p_map.get_byte(Size::from_bytes(idx), this)
-                            {
-                                this.expose_provenance(prov)?;
-                            }
+                        // If a provenance was read by the foreign code, expose it.
+                        for prov in alloc.provenance().get_range(this, overlap.into()) {
+                            this.expose_provenance(prov)?;
                         }
                     }
                     AccessEvent::Write(_, certain) => {
diff --git a/src/tools/miri/tests/fail/branchless-select-i128-pointer.rs b/src/tools/miri/tests/fail/branchless-select-i128-pointer.rs
index 2b861e5447b..7147813c4b6 100644
--- a/src/tools/miri/tests/fail/branchless-select-i128-pointer.rs
+++ b/src/tools/miri/tests/fail/branchless-select-i128-pointer.rs
@@ -1,3 +1,5 @@
+#![allow(integer_to_ptr_transmutes)]
+
 use std::mem::transmute;
 
 #[cfg(target_pointer_width = "32")]
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.rs
index b91a41d7650..744d64b9b1e 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.rs
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias.rs
@@ -1,3 +1,5 @@
+//! Ensure we detect aliasing of two in-place arguments for the tricky case where they do not
+//! live in memory.
 //@revisions: stack tree
 //@[tree]compile-flags: -Zmiri-tree-borrows
 // Validation forces more things into memory, which we can't have here.
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.rs
new file mode 100644
index 00000000000..dff724f8d96
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.rs
@@ -0,0 +1,34 @@
+//! Ensure we detect aliasing of a in-place argument with the return place for the tricky case where
+//! they do not live in memory.
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
+// Validation forces more things into memory, which we can't have here.
+//@compile-flags: -Zmiri-disable-validation
+#![feature(custom_mir, core_intrinsics)]
+use std::intrinsics::mir::*;
+
+#[allow(unused)]
+pub struct S(i32);
+
+#[custom_mir(dialect = "runtime", phase = "optimized")]
+fn main() {
+    mir! {
+        let _unit: ();
+        {
+            let staging = S(42); // This forces `staging` into memory...
+            let _non_copy = staging; // ... so we move it to a non-inmemory local here.
+            // This specifically uses a type with scalar representation to tempt Miri to use the
+            // efficient way of storing local variables (outside adressable memory).
+            Call(_non_copy = callee(Move(_non_copy)), ReturnTo(after_call), UnwindContinue())
+            //~[stack]^ ERROR: not granting access
+            //~[tree]| ERROR: /reborrow .* forbidden/
+        }
+        after_call = {
+            Return()
+        }
+    }
+}
+
+pub fn callee(x: S) -> S {
+    x
+}
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.stack.stderr
new file mode 100644
index 00000000000..fcd5b8752e7
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.stack.stderr
@@ -0,0 +1,25 @@
+error: Undefined Behavior: not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected
+  --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
+   |
+LL |             Call(_non_copy = callee(Move(_non_copy)), ReturnTo(after_call), UnwindContinue())
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
+   |
+   = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
+   = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
+help: <TAG> was created here, as the root tag for ALLOC
+  --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
+   |
+LL |             Call(_non_copy = callee(Move(_non_copy)), ReturnTo(after_call), UnwindContinue())
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: <TAG> is this argument
+  --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
+   |
+LL |     x
+   |     ^
+   = note: BACKTRACE (of the first span):
+   = note: inside `main` at tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.tree.stderr
new file mode 100644
index 00000000000..b7f514de0af
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_locals_alias_ret.tree.stderr
@@ -0,0 +1,34 @@
+error: Undefined Behavior: reborrow through <TAG> (root of the allocation) at ALLOC[0x0] is forbidden
+  --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
+   |
+LL |             Call(_non_copy = callee(Move(_non_copy)), ReturnTo(after_call), UnwindContinue())
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
+   |
+   = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
+   = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information
+   = help: the accessed tag <TAG> (root of the allocation) is foreign to the protected tag <TAG> (i.e., it is not a child)
+   = help: this reborrow (acting as a foreign read access) would cause the protected tag <TAG> (currently Active) to become Disabled
+   = help: protected tags must never be Disabled
+help: the accessed tag <TAG> was created here
+  --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
+   |
+LL |             Call(_non_copy = callee(Move(_non_copy)), ReturnTo(after_call), UnwindContinue())
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: the protected tag <TAG> was created here, in the initial state Reserved
+  --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
+   |
+LL |     x
+   |     ^
+help: the protected tag <TAG> later transitioned to Active due to a child write access at offsets [0x0..0x4]
+  --> tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
+   |
+LL |     x
+   |     ^
+   = help: this transition corresponds to the first write to a 2-phase borrowed mutable reference
+   = note: BACKTRACE (of the first span):
+   = note: inside `main` at tests/fail/function_calls/arg_inplace_locals_alias_ret.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/fail/provenance/provenance_transmute.rs b/src/tools/miri/tests/fail/provenance/provenance_transmute.rs
index d72f10530d7..60cb9a7f6bf 100644
--- a/src/tools/miri/tests/fail/provenance/provenance_transmute.rs
+++ b/src/tools/miri/tests/fail/provenance/provenance_transmute.rs
@@ -1,5 +1,7 @@
 //@compile-flags: -Zmiri-permissive-provenance
 
+#![allow(integer_to_ptr_transmutes)]
+
 use std::mem;
 
 // This is the example from
diff --git a/src/tools/miri/tests/fail/validity/dangling_ref1.rs b/src/tools/miri/tests/fail/validity/dangling_ref1.rs
index fc3a9f34463..57ba1117e76 100644
--- a/src/tools/miri/tests/fail/validity/dangling_ref1.rs
+++ b/src/tools/miri/tests/fail/validity/dangling_ref1.rs
@@ -1,5 +1,8 @@
 // Make sure we catch this even without Stacked Borrows
 //@compile-flags: -Zmiri-disable-stacked-borrows
+
+#![allow(integer_to_ptr_transmutes)]
+
 use std::mem;
 
 fn main() {
diff --git a/src/tools/miri/tests/panic/transmute_fat2.rs b/src/tools/miri/tests/panic/transmute_fat2.rs
index e695ff2d57b..7441f25d03e 100644
--- a/src/tools/miri/tests/panic/transmute_fat2.rs
+++ b/src/tools/miri/tests/panic/transmute_fat2.rs
@@ -1,3 +1,5 @@
+#![allow(integer_to_ptr_transmutes)]
+
 fn main() {
     #[cfg(all(target_endian = "little", target_pointer_width = "64"))]
     let bad = unsafe { std::mem::transmute::<u128, &[u8]>(42) };
diff --git a/src/tools/miri/tests/pass/binops.rs b/src/tools/miri/tests/pass/binops.rs
index 0aff7acb29d..fcbe6c85b7b 100644
--- a/src/tools/miri/tests/pass/binops.rs
+++ b/src/tools/miri/tests/pass/binops.rs
@@ -32,6 +32,7 @@ fn test_bool() {
     assert_eq!(true ^ true, false);
 }
 
+#[allow(integer_to_ptr_transmutes)]
 fn test_ptr() {
     unsafe {
         let p1: *const u8 = ::std::mem::transmute(0_usize);
diff --git a/src/tools/miri/tests/pass/too-large-primval-write-problem.rs b/src/tools/miri/tests/pass/too-large-primval-write-problem.rs
index f4c418bd78a..00882b7ecca 100644
--- a/src/tools/miri/tests/pass/too-large-primval-write-problem.rs
+++ b/src/tools/miri/tests/pass/too-large-primval-write-problem.rs
@@ -7,6 +7,8 @@
 //
 // This is just intended as a regression test to make sure we don't reintroduce this problem.
 
+#![allow(integer_to_ptr_transmutes)]
+
 #[cfg(target_pointer_width = "32")]
 fn main() {
     use std::mem::transmute;
diff --git a/src/tools/opt-dist/src/exec.rs b/src/tools/opt-dist/src/exec.rs
index a8d4c93d160..a3935f98359 100644
--- a/src/tools/opt-dist/src/exec.rs
+++ b/src/tools/opt-dist/src/exec.rs
@@ -189,6 +189,12 @@ impl Bootstrap {
         self
     }
 
+    /// Rebuild rustc in case of statically linked LLVM
+    pub fn rustc_rebuild(mut self) -> Self {
+        self.cmd = self.cmd.arg("--keep-stage").arg("0");
+        self
+    }
+
     pub fn run(self, timer: &mut TimerSection) -> anyhow::Result<()> {
         self.cmd.run()?;
         let metrics = load_metrics(&self.metrics_path)?;
diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs
index 19706b4a4f0..339c25552ad 100644
--- a/src/tools/opt-dist/src/main.rs
+++ b/src/tools/opt-dist/src/main.rs
@@ -375,8 +375,14 @@ fn execute_pipeline(
 
     let mut dist = Bootstrap::dist(env, &dist_args)
         .llvm_pgo_optimize(llvm_pgo_profile.as_ref())
-        .rustc_pgo_optimize(&rustc_pgo_profile)
-        .avoid_rustc_rebuild();
+        .rustc_pgo_optimize(&rustc_pgo_profile);
+
+    // if LLVM is not built we'll have PGO optimized rustc
+    dist = if env.supports_shared_llvm() || !env.build_llvm() {
+        dist.avoid_rustc_rebuild()
+    } else {
+        dist.rustc_rebuild()
+    };
 
     for bolt_profile in bolt_profiles {
         dist = dist.with_bolt_profile(bolt_profile);
diff --git a/src/tools/rustfmt/Cargo.toml b/src/tools/rustfmt/Cargo.toml
index e497b792342..6392ffbe409 100644
--- a/src/tools/rustfmt/Cargo.toml
+++ b/src/tools/rustfmt/Cargo.toml
@@ -40,7 +40,7 @@ cargo_metadata = "0.18"
 clap = { version = "4.4.2", features = ["derive"] }
 clap-cargo = "0.12.0"
 diff = "0.1"
-dirs = "5.0"
+dirs = "6.0"
 getopts = "0.2"
 ignore = "0.4"
 itertools = "0.12"
diff --git a/src/tools/rustfmt/tests/source/frontmatter_compact.rs b/src/tools/rustfmt/tests/source/frontmatter_compact.rs
new file mode 100644
index 00000000000..21d4c6f4b61
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/frontmatter_compact.rs
@@ -0,0 +1,8 @@
+#!/usr/bin/env cargo
+---identifier
+[dependencies]
+regex = "1"
+---
+#![feature(frontmatter)]
+
+fn main() {}
diff --git a/src/tools/rustfmt/tests/source/frontmatter_escaped.rs b/src/tools/rustfmt/tests/source/frontmatter_escaped.rs
new file mode 100644
index 00000000000..0d026377566
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/frontmatter_escaped.rs
@@ -0,0 +1,13 @@
+#!/usr/bin/env cargo
+------------
+package.description = """
+Header
+-----
+
+Body
+"""
+------------
+
+#![feature(frontmatter)]
+
+fn main() {}
diff --git a/src/tools/rustfmt/tests/source/frontmatter_spaced.rs b/src/tools/rustfmt/tests/source/frontmatter_spaced.rs
new file mode 100644
index 00000000000..ee0bb81705c
--- /dev/null
+++ b/src/tools/rustfmt/tests/source/frontmatter_spaced.rs
@@ -0,0 +1,16 @@
+#!/usr/bin/env cargo
+
+
+---   identifier
+[dependencies]
+regex = "1"
+
+---
+
+
+
+
+
+#![feature(frontmatter)]
+
+fn main() {}
diff --git a/src/tools/rustfmt/tests/target/frontmatter_compact.rs b/src/tools/rustfmt/tests/target/frontmatter_compact.rs
new file mode 100644
index 00000000000..21d4c6f4b61
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/frontmatter_compact.rs
@@ -0,0 +1,8 @@
+#!/usr/bin/env cargo
+---identifier
+[dependencies]
+regex = "1"
+---
+#![feature(frontmatter)]
+
+fn main() {}
diff --git a/src/tools/rustfmt/tests/target/frontmatter_escaped.rs b/src/tools/rustfmt/tests/target/frontmatter_escaped.rs
new file mode 100644
index 00000000000..0d026377566
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/frontmatter_escaped.rs
@@ -0,0 +1,13 @@
+#!/usr/bin/env cargo
+------------
+package.description = """
+Header
+-----
+
+Body
+"""
+------------
+
+#![feature(frontmatter)]
+
+fn main() {}
diff --git a/src/tools/rustfmt/tests/target/frontmatter_spaced.rs b/src/tools/rustfmt/tests/target/frontmatter_spaced.rs
new file mode 100644
index 00000000000..ee0bb81705c
--- /dev/null
+++ b/src/tools/rustfmt/tests/target/frontmatter_spaced.rs
@@ -0,0 +1,16 @@
+#!/usr/bin/env cargo
+
+
+---   identifier
+[dependencies]
+regex = "1"
+
+---
+
+
+
+
+
+#![feature(frontmatter)]
+
+fn main() {}
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 80b6d54ce1c..6974ede624a 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -287,14 +287,12 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "gimli",
     "gsgdt",
     "hashbrown",
+    "icu_collections",
     "icu_list",
-    "icu_list_data",
-    "icu_locid",
-    "icu_locid_transform",
-    "icu_locid_transform_data",
+    "icu_locale",
+    "icu_locale_core",
+    "icu_locale_data",
     "icu_provider",
-    "icu_provider_adapters",
-    "icu_provider_macros",
     "ident_case",
     "indexmap",
     "intl-memoizer",
@@ -332,6 +330,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "polonius-engine",
     "portable-atomic", // dependency for platforms doesn't support `AtomicU64` in std
     "portable-atomic-util",
+    "potential_utf",
     "ppv-lite86",
     "proc-macro-hack",
     "proc-macro2",
@@ -361,7 +360,6 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "scoped-tls",
     "scopeguard",
     "self_cell",
-    "semver",
     "serde",
     "serde_derive",
     "serde_json",
@@ -448,6 +446,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "zerocopy-derive",
     "zerofrom",
     "zerofrom-derive",
+    "zerotrie",
     "zerovec",
     "zerovec-derive",
     // tidy-alphabetical-end
diff --git a/src/tools/tidy/src/gcc_submodule.rs b/src/tools/tidy/src/gcc_submodule.rs
index 5d726c3ea48..217eaf1758c 100644
--- a/src/tools/tidy/src/gcc_submodule.rs
+++ b/src/tools/tidy/src/gcc_submodule.rs
@@ -24,6 +24,12 @@ pub fn check(root_path: &Path, compiler_path: &Path, bad: &mut bool) {
         .output()
         .expect("Cannot determine git SHA of the src/gcc checkout");
 
+    // Git is not available or we are in a tarball
+    if !git_output.status.success() {
+        eprintln!("Cannot figure out the SHA of the GCC submodule");
+        return;
+    }
+
     // This can return e.g.
     // -e607be166673a8de9fc07f6f02c60426e556c5f2 src/gcc
     //  e607be166673a8de9fc07f6f02c60426e556c5f2 src/gcc (master-e607be166673a8de9fc07f6f02c60426e556c5f2.e607be)
diff --git a/src/tools/tidy/src/unit_tests.rs b/src/tools/tidy/src/unit_tests.rs
index 3d14a467319..7396310ed37 100644
--- a/src/tools/tidy/src/unit_tests.rs
+++ b/src/tools/tidy/src/unit_tests.rs
@@ -61,6 +61,7 @@ pub fn check(root_path: &Path, stdlib: bool, bad: &mut bool) {
                 || path.ends_with("library/alloc/src/collections/linked_list/tests.rs")
                 || path.ends_with("library/alloc/src/collections/vec_deque/tests.rs")
                 || path.ends_with("library/alloc/src/raw_vec/tests.rs")
+                || path.ends_with("library/alloc/src/wtf8/tests.rs")
         }
     };
 
diff --git a/src/tools/wasm-component-ld/Cargo.toml b/src/tools/wasm-component-ld/Cargo.toml
index ce718902b29..23dc86998e8 100644
--- a/src/tools/wasm-component-ld/Cargo.toml
+++ b/src/tools/wasm-component-ld/Cargo.toml
@@ -10,4 +10,4 @@ name = "wasm-component-ld"
 path = "src/main.rs"
 
 [dependencies]
-wasm-component-ld = "0.5.14"
+wasm-component-ld = "0.5.16"
diff --git a/tests/assembly-llvm/reg-struct-return.rs b/tests/assembly-llvm/reg-struct-return.rs
new file mode 100644
index 00000000000..b251d791d51
--- /dev/null
+++ b/tests/assembly-llvm/reg-struct-return.rs
@@ -0,0 +1,143 @@
+//! Tests that -Zreg-struct-return changes ABI for small struct returns
+//! from hidden-pointer convention to register-return on x86_32.
+//! This test covers:
+//! * Callee side, verifying that the structs are correctly loaded into registers when
+//!   `-Zreg-struct-return` is activated
+//! * Caller side, verifying callers do receive returned structs in registers when
+//!   `-Zreg-struct-return` is activated
+//@ add-core-stubs
+//@ assembly-output: emit-asm
+//@ compile-flags: -O --target=i686-unknown-linux-gnu -Crelocation-model=static
+//@ revisions: WITH WITHOUT
+//@[WITH] compile-flags: -Zreg-struct-return
+//@ needs-llvm-components: x86
+
+#![feature(no_core)]
+#![no_std]
+#![no_core]
+#![crate_type = "lib"]
+
+extern crate minicore;
+use minicore::*;
+
+// Verifies ABI changes for small structs, where both fields fit into one register.
+// WITH is expected to use register return, WITHOUT should use hidden pointer.
+mod Small {
+    struct SmallStruct {
+        a: i8,
+        b: i8,
+    }
+
+    unsafe extern "C" {
+        fn small() -> SmallStruct;
+    }
+
+    #[unsafe(no_mangle)]
+    pub unsafe extern "C" fn small_callee() -> SmallStruct {
+        // (42 << 8) | 42 = 10794
+
+        // WITH-LABEL: small_callee
+        // WITH: movw $10794, %ax
+        // WITH: retl
+
+        // WITHOUT-LABEL: small_callee
+        // WITHOUT: movl 4(%esp), %e{{.*}}
+        // WITHOUT: movw $10794, (%e{{.*}})
+        // WITHOUT: retl $4
+        SmallStruct { a: 42, b: 42 }
+    }
+
+    #[unsafe(no_mangle)]
+    pub unsafe extern "C" fn small_caller(dst: &mut SmallStruct) {
+        // WITH-LABEL: small_caller
+        // WITH: calll small
+        // WITH: movw %ax, (%e{{.*}})
+
+        // WITHOUT-LABEL: small_caller
+        // WITHOUT: calll small
+        // WITHOUT: movzwl {{.*}}(%esp), %e[[TMP:..]]
+        // WITHOUT: movw %[[TMP]], (%e{{..}})
+        *dst = small();
+    }
+}
+
+// Verifies ABI changes for a struct of size 8, which is the maximum size
+// for reg-struct-return.
+// WITH is expected to still use register return, WITHOUT should use hidden
+// pointer.
+mod Pivot {
+    struct PivotStruct {
+        a: i32,
+        b: i32,
+    }
+
+    unsafe extern "C" {
+        fn pivot() -> PivotStruct;
+    }
+
+    #[unsafe(no_mangle)]
+    pub unsafe extern "C" fn pivot_callee() -> PivotStruct {
+        // WITH-LABEL: pivot_callee
+        // WITH: movl $42, %e{{.*}}
+        // WITH: movl $42, %e{{.*}}
+        // WITH: retl
+
+        // WITHOUT-LABEL: pivot_callee
+        // WITHOUT: movl 4(%esp), %e{{.*}}
+        // WITHOUT-DAG: movl $42, (%e{{.*}})
+        // WITHOUT-DAG: movl $42, 4(%e{{.*}})
+        // WITHOUT: retl $4
+        PivotStruct { a: 42, b: 42 }
+    }
+
+    #[unsafe(no_mangle)]
+    pub unsafe extern "C" fn pivot_caller(dst: &mut PivotStruct) {
+        // WITH-LABEL: pivot_caller
+        // WITH: calll pivot
+        // WITH-DAG: movl %e{{.*}}, 4(%e{{.*}})
+        // WITH-DAG: movl %e{{.*}}, (%e{{.*}})
+
+        // WITHOUT-LABEL: pivot_caller
+        // WITHOUT: calll pivot
+        // WITHOUT: movsd {{.*}}(%esp), %[[TMP:xmm.]]
+        // WITHOUT: movsd %[[TMP]], (%e{{..}})
+        *dst = pivot();
+    }
+}
+
+// Verifies ABI changes for a struct of size 12, which is larger than the
+// maximum size for reg-struct-return (8 bytes).
+// Here, the hidden pointer convention should be used even when `-Zreg-struct-return` is set.
+mod Large {
+    struct LargeStruct {
+        a: i32,
+        b: i32,
+        c: i32,
+    }
+
+    unsafe extern "C" {
+        fn large() -> LargeStruct;
+    }
+
+    #[unsafe(no_mangle)]
+    pub unsafe extern "C" fn large_callee() -> LargeStruct {
+        // CHECK-LABEL: large_callee
+        // CHECK: movl 4(%esp), %e{{.*}}
+        // CHECK-DAG: movl $42, (%e{{.*}})
+        // CHECK-DAG: movl $42, 4(%e{{.*}})
+        // CHECK-DAG: movl $42, 8(%e{{.*}})
+        // CHECK: retl $4
+        LargeStruct { a: 42, b: 42, c: 42 }
+    }
+
+    #[unsafe(no_mangle)]
+    pub unsafe extern "C" fn large_caller(dst: &mut LargeStruct) {
+        // CHECK-LABEL: large_caller
+        // CHECK: calll large
+        // CHECK-DAG: movl   {{.*}}(%esp), %[[TMP1:e..]]
+        // CHECK-DAG: movl  %[[TMP1]], {{.*}}(%e{{..}})
+        // CHECK-DAG: movsd  {{.*}}(%esp), %[[TMP2:xmm.]]
+        // CHECK-DAG: movsd  %[[TMP2]], {{.*}}(%e{{..}})
+        *dst = large();
+    }
+}
diff --git a/tests/assembly-llvm/targets/targets-elf.rs b/tests/assembly-llvm/targets/targets-elf.rs
index 79347d0bbf6..c935a75a690 100644
--- a/tests/assembly-llvm/targets/targets-elf.rs
+++ b/tests/assembly-llvm/targets/targets-elf.rs
@@ -10,6 +10,9 @@
 //@ revisions: aarch64_be_unknown_linux_gnu_ilp32
 //@ [aarch64_be_unknown_linux_gnu_ilp32] compile-flags: --target aarch64_be-unknown-linux-gnu_ilp32
 //@ [aarch64_be_unknown_linux_gnu_ilp32] needs-llvm-components: aarch64
+//@ revisions: aarch64_be_unknown_linux_musl
+//@ [aarch64_be_unknown_linux_musl] compile-flags: --target aarch64_be-unknown-linux-musl
+//@ [aarch64_be_unknown_linux_musl] needs-llvm-components: aarch64
 //@ revisions: aarch64_be_unknown_netbsd
 //@ [aarch64_be_unknown_netbsd] compile-flags: --target aarch64_be-unknown-netbsd
 //@ [aarch64_be_unknown_netbsd] needs-llvm-components: aarch64
@@ -481,6 +484,9 @@
 //@ revisions: riscv64gc_unknown_linux_gnu
 //@ [riscv64gc_unknown_linux_gnu] compile-flags: --target riscv64gc-unknown-linux-gnu
 //@ [riscv64gc_unknown_linux_gnu] needs-llvm-components: riscv
+//@ revisions: riscv64a23_unknown_linux_gnu
+//@ [riscv64a23_unknown_linux_gnu] compile-flags: --target riscv64a23-unknown-linux-gnu
+//@ [riscv64a23_unknown_linux_gnu] needs-llvm-components: riscv
 //@ revisions: riscv64gc_unknown_linux_musl
 //@ [riscv64gc_unknown_linux_musl] compile-flags: --target riscv64gc-unknown-linux-musl
 //@ [riscv64gc_unknown_linux_musl] needs-llvm-components: riscv
diff --git a/tests/codegen-llvm/addr-of-mutate.rs b/tests/codegen-llvm/addr-of-mutate.rs
index 71669065289..36d6bf555d1 100644
--- a/tests/codegen-llvm/addr-of-mutate.rs
+++ b/tests/codegen-llvm/addr-of-mutate.rs
@@ -5,7 +5,7 @@
 // Test for the absence of `readonly` on the argument when it is mutated via `&raw const`.
 // See <https://github.com/rust-lang/rust/issues/111502>.
 
-// CHECK: i8 @foo(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef align 1{{( captures\(none\))?}} dereferenceable(128) %x)
+// CHECK: i8 @foo(ptr{{( dead_on_return)?}} noalias noundef align 1{{( captures\(address\))?}} dereferenceable(128) %x)
 #[no_mangle]
 pub fn foo(x: [u8; 128]) -> u8 {
     let ptr = core::ptr::addr_of!(x).cast_mut();
@@ -15,7 +15,7 @@ pub fn foo(x: [u8; 128]) -> u8 {
     x[0]
 }
 
-// CHECK: i1 @second(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef align {{[0-9]+}}{{( captures\(none\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
+// CHECK: i1 @second(ptr{{( dead_on_return)?}} noalias noundef align {{[0-9]+}}{{( captures\(address\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
 #[no_mangle]
 pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
     let b_bool_ptr = core::ptr::addr_of!(a_ptr_and_b.1.1).cast_mut();
@@ -24,7 +24,7 @@ pub unsafe fn second(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
 }
 
 // If going through a deref (and there are no other mutating accesses), then `readonly` is fine.
-// CHECK: i1 @third(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef readonly align {{[0-9]+}}{{( captures\(none\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
+// CHECK: i1 @third(ptr{{( dead_on_return)?}} noalias noundef readonly align {{[0-9]+}}{{( captures\(address\))?}} dereferenceable({{[0-9]+}}) %a_ptr_and_b)
 #[no_mangle]
 pub unsafe fn third(a_ptr_and_b: (*mut (i32, bool), (i64, bool))) -> bool {
     let b_bool_ptr = core::ptr::addr_of!((*a_ptr_and_b.0).1).cast_mut();
diff --git a/tests/codegen-llvm/function-arguments.rs b/tests/codegen-llvm/function-arguments.rs
index db508682862..a0744e44c61 100644
--- a/tests/codegen-llvm/function-arguments.rs
+++ b/tests/codegen-llvm/function-arguments.rs
@@ -134,7 +134,7 @@ pub fn mutable_notunpin_borrow(_: &mut NotUnpin) {}
 #[no_mangle]
 pub fn notunpin_borrow(_: &NotUnpin) {}
 
-// CHECK: @indirect_struct(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef readonly align 4{{( captures\(none\))?}} dereferenceable(32) %_1)
+// CHECK: @indirect_struct(ptr{{( dead_on_return)?}} noalias noundef readonly align 4{{( captures\(address\))?}} dereferenceable(32) %_1)
 #[no_mangle]
 pub fn indirect_struct(_: S) {}
 
@@ -197,7 +197,7 @@ pub fn notunpin_box(x: Box<NotUnpin>) -> Box<NotUnpin> {
     x
 }
 
-// CHECK: @struct_return(ptr{{( dead_on_unwind)?}} noalias{{( nocapture)?}} noundef{{( writable)?}} sret([32 x i8]) align 4{{( captures\(none\))?}} dereferenceable(32){{( %_0)?}})
+// CHECK: @struct_return(ptr{{( dead_on_unwind)?}} noalias noundef{{( writable)?}} sret([32 x i8]) align 4{{( captures\(address\))?}} dereferenceable(32){{( %_0)?}})
 #[no_mangle]
 pub fn struct_return() -> S {
     S { _field: [0, 0, 0, 0, 0, 0, 0, 0] }
diff --git a/tests/codegen-llvm/loongarch-abi/loongarch64-lp64d-abi.rs b/tests/codegen-llvm/loongarch-abi/loongarch64-lp64d-abi.rs
index 4666342a16a..7ea08a1a8f7 100644
--- a/tests/codegen-llvm/loongarch-abi/loongarch64-lp64d-abi.rs
+++ b/tests/codegen-llvm/loongarch-abi/loongarch64-lp64d-abi.rs
@@ -256,11 +256,11 @@ pub struct IntDoubleInt {
     c: i32,
 }
 
-// CHECK: define void @f_int_double_int_s_arg(ptr{{( dead_on_return)?}} noalias{{( nocapture)?}} noundef align 8{{( captures\(none\))?}} dereferenceable(24) %a)
+// CHECK: define void @f_int_double_int_s_arg(ptr{{( dead_on_return)?}} noalias noundef align 8{{( captures\(address\))?}} dereferenceable(24) %a)
 #[no_mangle]
 pub extern "C" fn f_int_double_int_s_arg(a: IntDoubleInt) {}
 
-// CHECK: define void @f_ret_int_double_int_s(ptr{{( dead_on_unwind)?}} noalias{{( nocapture)?}} noundef{{( writable)?}} sret([24 x i8]) align 8{{( captures\(none\))?}} dereferenceable(24) %_0)
+// CHECK: define void @f_ret_int_double_int_s(ptr{{( dead_on_unwind)?}} noalias noundef{{( writable)?}} sret([24 x i8]) align 8{{( captures\(address\))?}} dereferenceable(24) %_0)
 #[no_mangle]
 pub extern "C" fn f_ret_int_double_int_s() -> IntDoubleInt {
     IntDoubleInt { a: 1, b: 2., c: 3 }
diff --git a/tests/crashes/120175.rs b/tests/crashes/120175.rs
index c6e7203ff98..e441454bed2 100644
--- a/tests/crashes/120175.rs
+++ b/tests/crashes/120175.rs
@@ -2,8 +2,9 @@
 //@ needs-rustc-debug-assertions
 
 #![feature(extern_types)]
+#![feature(raw_dylib_elf)]
 
-#[link(name = "bar", import_name_type = "decorated", kind = "raw-dylib")]
+#[link(name = "bar", kind = "raw-dylib")]
 extern "C" {
     pub type CrossCrate;
 }
diff --git a/tests/crashes/124352.rs b/tests/crashes/124352.rs
deleted file mode 100644
index e9eb4419e6a..00000000000
--- a/tests/crashes/124352.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-//@ known-bug: #124352
-#![rustc_never_type_options(: Unsize<U> = "hi")]
-
-fn main() {}
diff --git a/tests/crashes/137580.rs b/tests/crashes/137580.rs
deleted file mode 100644
index 246c80ef556..00000000000
--- a/tests/crashes/137580.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-//@ known-bug: #137580
-fn main() {
-    println!("%65536$", 1);
-}
diff --git a/tests/mir-opt/building/async_await.rs b/tests/mir-opt/building/async_await.rs
index 6c44570d109..2d14a1fb0c6 100644
--- a/tests/mir-opt/building/async_await.rs
+++ b/tests/mir-opt/building/async_await.rs
@@ -4,7 +4,7 @@
 // related to `yield` are `&mut Context`, and its return type is `Poll`.
 
 //@ edition:2018
-//@ compile-flags: -C panic=abort
+//@ compile-flags: -Zmir-opt-level=0 -C panic=abort
 
 #![crate_type = "lib"]
 
diff --git a/tests/mir-opt/building/dump_mir_cycle.rs b/tests/mir-opt/building/dump_mir_cycle.rs
index 8e13420aed7..ab0f2ea6db8 100644
--- a/tests/mir-opt/building/dump_mir_cycle.rs
+++ b/tests/mir-opt/building/dump_mir_cycle.rs
@@ -1,3 +1,5 @@
+//@ compile-flags: -Zmir-opt-level=0
+
 #[derive(Debug)]
 pub struct Thing {
     pub next: &'static Thing,
diff --git a/tests/mir-opt/building/enum_cast.rs b/tests/mir-opt/building/enum_cast.rs
index eaf5537e0ab..07025f572ab 100644
--- a/tests/mir-opt/building/enum_cast.rs
+++ b/tests/mir-opt/building/enum_cast.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zmir-opt-level=0
 // skip-filecheck
 // EMIT_MIR enum_cast.foo.built.after.mir
 // EMIT_MIR enum_cast.bar.built.after.mir
diff --git a/tests/mir-opt/building/eq_never_type.rs b/tests/mir-opt/building/eq_never_type.rs
index 90e2e697535..486e2f9fb8d 100644
--- a/tests/mir-opt/building/eq_never_type.rs
+++ b/tests/mir-opt/building/eq_never_type.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zmir-opt-level=0
 // skip-filecheck
 #![feature(never_type)]
 #![allow(unreachable_code)]
diff --git a/tests/mir-opt/building/index_array_and_slice.rs b/tests/mir-opt/building/index_array_and_slice.rs
index 42ede66d92b..47d8255ef57 100644
--- a/tests/mir-opt/building/index_array_and_slice.rs
+++ b/tests/mir-opt/building/index_array_and_slice.rs
@@ -1,36 +1,42 @@
-//@ compile-flags: -C opt-level=0
+//@ compile-flags: -Zmir-opt-level=0 -C opt-level=0
 
 // EMIT_MIR index_array_and_slice.index_array.built.after.mir
 fn index_array(array: &[i32; 7], index: usize) -> &i32 {
     // CHECK: bb0:
-    // CHECK: [[LT:_.+]] = Lt(copy _2, const 7_usize);
-    // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", const 7_usize, copy _2) -> [success: bb1, unwind
+    // CHECK: _3 = copy _2;
+    // CHECK: [[LT:_.+]] = Lt(copy _3, const 7_usize);
+    // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", const 7_usize, copy _3) -> [success: bb1, unwind
 
     // CHECK: bb1:
-    // CHECK: _0 = &(*_1)[_2];
+    // CHECK: _5 = &(*_1)[_3];
+    // CHECK: _0 = &(*_5);
     &array[index]
 }
 
 // EMIT_MIR index_array_and_slice.index_const_generic_array.built.after.mir
 fn index_const_generic_array<const N: usize>(array: &[i32; N], index: usize) -> &i32 {
     // CHECK: bb0:
-    // CHECK: [[LT:_.+]] = Lt(copy _2, const N);
-    // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", const N, copy _2) -> [success: bb1, unwind
+    // CHECK: _3 = copy _2;
+    // CHECK: [[LT:_.+]] = Lt(copy _3, const N);
+    // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", const N, copy _3) -> [success: bb1, unwind
 
     // CHECK: bb1:
-    // CHECK: _0 = &(*_1)[_2];
+    // CHECK: _5 = &(*_1)[_3];
+    // CHECK: _0 = &(*_5);
     &array[index]
 }
 
 // EMIT_MIR index_array_and_slice.index_slice.built.after.mir
 fn index_slice(slice: &[i32], index: usize) -> &i32 {
     // CHECK: bb0:
+    // CHECK: _3 = copy _2;
     // CHECK: [[LEN:_.+]] = PtrMetadata(copy _1);
-    // CHECK: [[LT:_.+]] = Lt(copy _2, copy [[LEN]]);
-    // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", move [[LEN]], copy _2) -> [success: bb1,
+    // CHECK: [[LT:_.+]] = Lt(copy _3, copy [[LEN]]);
+    // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", move [[LEN]], copy _3) -> [success: bb1,
 
     // CHECK: bb1:
-    // CHECK: _0 = &(*_1)[_2];
+    // CHECK: _6 = &(*_1)[_3];
+    // CHECK: _0 = &(*_6);
     &slice[index]
 }
 
@@ -40,12 +46,15 @@ fn index_mut_slice(slice: &mut [i32], index: usize) -> &i32 {
     // This cannot `copy _1` in the *built* MIR, only in the *runtime* MIR.
 
     // CHECK: bb0:
-    // CHECK: [[LEN:_.+]] = PtrMetadata(copy _1);
-    // CHECK: [[LT:_.+]] = Lt(copy _2, copy [[LEN]]);
-    // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", move [[LEN]], copy _2) -> [success: bb1,
+    // CHECK: _3 = copy _2;
+    // CHECK: _4 = &raw const (fake) (*_1);
+    // CHECK: [[LEN:_.+]] = PtrMetadata(move _4);
+    // CHECK: [[LT:_.+]] = Lt(copy _3, copy [[LEN]]);
+    // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", move [[LEN]], copy _3) -> [success: bb1,
 
     // CHECK: bb1:
-    // CHECK: _0 = &(*_1)[_2];
+    // CHECK: _7 = &(*_1)[_3];
+    // CHECK: _0 = &(*_7);
     &slice[index]
 }
 
@@ -54,13 +63,15 @@ struct WithSliceTail(f64, [i32]);
 // EMIT_MIR index_array_and_slice.index_custom.built.after.mir
 fn index_custom(custom: &WithSliceTail, index: usize) -> &i32 {
     // CHECK: bb0:
+    // CHECK: _3 = copy _2;
     // CHECK: [[PTR:_.+]] = &raw const (fake) ((*_1).1: [i32]);
-    // CHECK: [[LEN:_.+]] = PtrMetadata(copy [[PTR]]);
-    // CHECK: [[LT:_.+]] = Lt(copy _2, copy [[LEN]]);
-    // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", move [[LEN]], copy _2) -> [success: bb1,
+    // CHECK: [[LEN:_.+]] = PtrMetadata(move [[PTR]]);
+    // CHECK: [[LT:_.+]] = Lt(copy _3, copy [[LEN]]);
+    // CHECK: assert(move [[LT]], "index out of bounds{{.+}}", move [[LEN]], copy _3) -> [success: bb1,
 
     // CHECK: bb1:
-    // CHECK: _0 = &((*_1).1: [i32])[_2];
+    // CHECK: _7 = &((*_1).1: [i32])[_3];
+    // CHECK: _0 = &(*_7);
     &custom.1[index]
 }
 
diff --git a/tests/mir-opt/building/issue_101867.main.built.after.mir b/tests/mir-opt/building/issue_101867.main.built.after.mir
index 8a36c901eed..fa35658a16d 100644
--- a/tests/mir-opt/building/issue_101867.main.built.after.mir
+++ b/tests/mir-opt/building/issue_101867.main.built.after.mir
@@ -1,8 +1,8 @@
 // MIR for `main` after built
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: Ty(std::option::Option<u8>), max_universe: U0, variables: [] }, span: $DIR/issue_101867.rs:4:12: 4:22, inferred_ty: std::option::Option<u8>
-| 1: user_ty: Canonical { value: Ty(std::option::Option<u8>), max_universe: U0, variables: [] }, span: $DIR/issue_101867.rs:4:12: 4:22, inferred_ty: std::option::Option<u8>
+| 0: user_ty: Canonical { value: Ty(std::option::Option<u8>), max_universe: U0, variables: [] }, span: $DIR/issue_101867.rs:5:12: 5:22, inferred_ty: std::option::Option<u8>
+| 1: user_ty: Canonical { value: Ty(std::option::Option<u8>), max_universe: U0, variables: [] }, span: $DIR/issue_101867.rs:5:12: 5:22, inferred_ty: std::option::Option<u8>
 |
 fn main() -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/building/issue_101867.rs b/tests/mir-opt/building/issue_101867.rs
index f8a531e8982..a00bc13b3fe 100644
--- a/tests/mir-opt/building/issue_101867.rs
+++ b/tests/mir-opt/building/issue_101867.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zmir-opt-level=0
 // skip-filecheck
 // EMIT_MIR issue_101867.main.built.after.mir
 fn main() {
diff --git a/tests/mir-opt/building/issue_110508.rs b/tests/mir-opt/building/issue_110508.rs
index e597cd5d06b..aa8a7b1d08f 100644
--- a/tests/mir-opt/building/issue_110508.rs
+++ b/tests/mir-opt/building/issue_110508.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zmir-opt-level=0
 // skip-filecheck
 // EMIT_MIR issue_110508.{impl#0}-BAR.built.after.mir
 // EMIT_MIR issue_110508.{impl#0}-SELF_BAR.built.after.mir
diff --git a/tests/mir-opt/building/issue_110508.{impl#0}-BAR.built.after.mir b/tests/mir-opt/building/issue_110508.{impl#0}-BAR.built.after.mir
index c3d28fae518..0cefb9c8fd1 100644
--- a/tests/mir-opt/building/issue_110508.{impl#0}-BAR.built.after.mir
+++ b/tests/mir-opt/building/issue_110508.{impl#0}-BAR.built.after.mir
@@ -1,6 +1,6 @@
-// MIR for `<impl at $DIR/issue_110508.rs:9:1: 9:9>::BAR` after built
+// MIR for `<impl at $DIR/issue_110508.rs:10:1: 10:9>::BAR` after built
 
-const <impl at $DIR/issue_110508.rs:9:1: 9:9>::BAR: Foo = {
+const <impl at $DIR/issue_110508.rs:10:1: 10:9>::BAR: Foo = {
     let mut _0: Foo;
     let mut _1: ();
 
diff --git a/tests/mir-opt/building/issue_110508.{impl#0}-SELF_BAR.built.after.mir b/tests/mir-opt/building/issue_110508.{impl#0}-SELF_BAR.built.after.mir
index 177518c30af..0e0e9149385 100644
--- a/tests/mir-opt/building/issue_110508.{impl#0}-SELF_BAR.built.after.mir
+++ b/tests/mir-opt/building/issue_110508.{impl#0}-SELF_BAR.built.after.mir
@@ -1,6 +1,6 @@
-// MIR for `<impl at $DIR/issue_110508.rs:9:1: 9:9>::SELF_BAR` after built
+// MIR for `<impl at $DIR/issue_110508.rs:10:1: 10:9>::SELF_BAR` after built
 
-const <impl at $DIR/issue_110508.rs:9:1: 9:9>::SELF_BAR: Foo = {
+const <impl at $DIR/issue_110508.rs:10:1: 10:9>::SELF_BAR: Foo = {
     let mut _0: Foo;
     let mut _1: ();
 
diff --git a/tests/mir-opt/building/issue_49232.rs b/tests/mir-opt/building/issue_49232.rs
index ac06e02778f..f17e3e955a4 100644
--- a/tests/mir-opt/building/issue_49232.rs
+++ b/tests/mir-opt/building/issue_49232.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zmir-opt-level=0
 // skip-filecheck
 // We must mark a variable whose initialization fails due to an
 // abort statement as StorageDead.
diff --git a/tests/mir-opt/building/logical_or_in_conditional.rs b/tests/mir-opt/building/logical_or_in_conditional.rs
index 249ccf72804..d1c1ea2896a 100644
--- a/tests/mir-opt/building/logical_or_in_conditional.rs
+++ b/tests/mir-opt/building/logical_or_in_conditional.rs
@@ -1,5 +1,5 @@
 // skip-filecheck
-//@ compile-flags: -Z validate-mir
+//@ compile-flags: -Zmir-opt-level=0 -Z validate-mir
 //@ edition: 2024
 struct Droppy(u8);
 impl Drop for Droppy {
diff --git a/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir b/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir
index 744553c7cd2..5cf182c21c3 100644
--- a/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir
+++ b/tests/mir-opt/building/receiver_ptr_mutability.main.built.after.mir
@@ -1,10 +1,10 @@
 // MIR for `main` after built
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [] }, span: $DIR/receiver_ptr_mutability.rs:15:14: 15:23, inferred_ty: *mut Test
-| 1: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [] }, span: $DIR/receiver_ptr_mutability.rs:15:14: 15:23, inferred_ty: *mut Test
-| 2: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [Region(U0), Region(U0), Region(U0), Region(U0)] }, span: $DIR/receiver_ptr_mutability.rs:19:18: 19:31, inferred_ty: &&&&*mut Test
-| 3: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [Region(U0), Region(U0), Region(U0), Region(U0)] }, span: $DIR/receiver_ptr_mutability.rs:19:18: 19:31, inferred_ty: &&&&*mut Test
+| 0: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [] }, span: $DIR/receiver_ptr_mutability.rs:16:14: 16:23, inferred_ty: *mut Test
+| 1: user_ty: Canonical { value: Ty(*mut Test), max_universe: U0, variables: [] }, span: $DIR/receiver_ptr_mutability.rs:16:14: 16:23, inferred_ty: *mut Test
+| 2: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [Region(U0), Region(U0), Region(U0), Region(U0)] }, span: $DIR/receiver_ptr_mutability.rs:20:18: 20:31, inferred_ty: &&&&*mut Test
+| 3: user_ty: Canonical { value: Ty(&&&&*mut Test), max_universe: U0, variables: [Region(U0), Region(U0), Region(U0), Region(U0)] }, span: $DIR/receiver_ptr_mutability.rs:20:18: 20:31, inferred_ty: &&&&*mut Test
 |
 fn main() -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/building/receiver_ptr_mutability.rs b/tests/mir-opt/building/receiver_ptr_mutability.rs
index 1ddb8b71a5a..37b142f1d8a 100644
--- a/tests/mir-opt/building/receiver_ptr_mutability.rs
+++ b/tests/mir-opt/building/receiver_ptr_mutability.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zmir-opt-level=0
 // skip-filecheck
 // EMIT_MIR receiver_ptr_mutability.main.built.after.mir
 
diff --git a/tests/mir-opt/building/shifts.rs b/tests/mir-opt/building/shifts.rs
index d7747bb2f78..165b388bc18 100644
--- a/tests/mir-opt/building/shifts.rs
+++ b/tests/mir-opt/building/shifts.rs
@@ -1,5 +1,5 @@
 // skip-filecheck
-//@ compile-flags: -C debug-assertions=yes
+//@ compile-flags: -Zmir-opt-level=0 -C debug-assertions=yes
 
 // EMIT_MIR shifts.shift_signed.built.after.mir
 fn shift_signed(small: i8, big: u128, a: i8, b: i32, c: i128) -> ([i8; 3], [u128; 3]) {
diff --git a/tests/mir-opt/building/storage_live_dead_in_statics.rs b/tests/mir-opt/building/storage_live_dead_in_statics.rs
index 7cb74acbf06..868f4a8f559 100644
--- a/tests/mir-opt/building/storage_live_dead_in_statics.rs
+++ b/tests/mir-opt/building/storage_live_dead_in_statics.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zmir-opt-level=0
 // skip-filecheck
 // Check that when we compile the static `XXX` into MIR, we do not
 // generate `StorageStart` or `StorageEnd` statements.
diff --git a/tests/mir-opt/building/uniform_array_move_out.rs b/tests/mir-opt/building/uniform_array_move_out.rs
index aff5996d0b6..36245273fe1 100644
--- a/tests/mir-opt/building/uniform_array_move_out.rs
+++ b/tests/mir-opt/building/uniform_array_move_out.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zmir-opt-level=0
 // skip-filecheck
 #![feature(liballoc_internals, rustc_attrs)]
 
diff --git a/tests/mir-opt/building/user_type_annotations.let_else.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_else.built.after.mir
index 3d26fe24ac9..bbf504d311f 100644
--- a/tests/mir-opt/building/user_type_annotations.let_else.built.after.mir
+++ b/tests/mir-opt/building/user_type_annotations.let_else.built.after.mir
@@ -1,8 +1,8 @@
 // MIR for `let_else` after built
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:35:20: 35:45, inferred_ty: (u32, u64, &char)
-| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:35:20: 35:45, inferred_ty: (u32, u64, &char)
+| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:36:20: 36:45, inferred_ty: (u32, u64, &char)
+| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:36:20: 36:45, inferred_ty: (u32, u64, &char)
 |
 fn let_else() -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/building/user_type_annotations.let_else_bindless.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_else_bindless.built.after.mir
index b2a06ae53a8..7bf2551e99f 100644
--- a/tests/mir-opt/building/user_type_annotations.let_else_bindless.built.after.mir
+++ b/tests/mir-opt/building/user_type_annotations.let_else_bindless.built.after.mir
@@ -1,8 +1,8 @@
 // MIR for `let_else_bindless` after built
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:40:20: 40:45, inferred_ty: (u32, u64, &char)
-| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:40:20: 40:45, inferred_ty: (u32, u64, &char)
+| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:41:20: 41:45, inferred_ty: (u32, u64, &char)
+| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:41:20: 41:45, inferred_ty: (u32, u64, &char)
 |
 fn let_else_bindless() -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/building/user_type_annotations.let_init.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_init.built.after.mir
index d1b8f823e9b..0cf681d8ab2 100644
--- a/tests/mir-opt/building/user_type_annotations.let_init.built.after.mir
+++ b/tests/mir-opt/building/user_type_annotations.let_init.built.after.mir
@@ -1,8 +1,8 @@
 // MIR for `let_init` after built
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:25:20: 25:45, inferred_ty: (u32, u64, &char)
-| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:25:20: 25:45, inferred_ty: (u32, u64, &char)
+| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:26:20: 26:45, inferred_ty: (u32, u64, &char)
+| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:26:20: 26:45, inferred_ty: (u32, u64, &char)
 |
 fn let_init() -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/building/user_type_annotations.let_init_bindless.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_init_bindless.built.after.mir
index 6702f930060..968813c826e 100644
--- a/tests/mir-opt/building/user_type_annotations.let_init_bindless.built.after.mir
+++ b/tests/mir-opt/building/user_type_annotations.let_init_bindless.built.after.mir
@@ -1,8 +1,8 @@
 // MIR for `let_init_bindless` after built
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:30:20: 30:45, inferred_ty: (u32, u64, &char)
-| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:30:20: 30:45, inferred_ty: (u32, u64, &char)
+| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:31:20: 31:45, inferred_ty: (u32, u64, &char)
+| 1: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:31:20: 31:45, inferred_ty: (u32, u64, &char)
 |
 fn let_init_bindless() -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/building/user_type_annotations.let_uninit.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_uninit.built.after.mir
index 76b5938b87d..b6fdc4ff46d 100644
--- a/tests/mir-opt/building/user_type_annotations.let_uninit.built.after.mir
+++ b/tests/mir-opt/building/user_type_annotations.let_uninit.built.after.mir
@@ -1,7 +1,7 @@
 // MIR for `let_uninit` after built
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:15:20: 15:45, inferred_ty: (u32, u64, &char)
+| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:16:20: 16:45, inferred_ty: (u32, u64, &char)
 |
 fn let_uninit() -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/building/user_type_annotations.let_uninit_bindless.built.after.mir b/tests/mir-opt/building/user_type_annotations.let_uninit_bindless.built.after.mir
index 0cd12558771..472dbfb6304 100644
--- a/tests/mir-opt/building/user_type_annotations.let_uninit_bindless.built.after.mir
+++ b/tests/mir-opt/building/user_type_annotations.let_uninit_bindless.built.after.mir
@@ -1,7 +1,7 @@
 // MIR for `let_uninit_bindless` after built
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:20:20: 20:45, inferred_ty: (u32, u64, &char)
+| 0: user_ty: Canonical { value: Ty((u32, u64, &'static char)), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:21:20: 21:45, inferred_ty: (u32, u64, &char)
 |
 fn let_uninit_bindless() -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/building/user_type_annotations.match_assoc_const.built.after.mir b/tests/mir-opt/building/user_type_annotations.match_assoc_const.built.after.mir
index c0ce6f1d06b..ff4b0bf7600 100644
--- a/tests/mir-opt/building/user_type_annotations.match_assoc_const.built.after.mir
+++ b/tests/mir-opt/building/user_type_annotations.match_assoc_const.built.after.mir
@@ -1,8 +1,8 @@
 // MIR for `match_assoc_const` after built
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:54:9: 54:44, inferred_ty: u32
-| 1: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:54:9: 54:44, inferred_ty: u32
+| 0: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:55:9: 55:44, inferred_ty: u32
+| 1: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:55:9: 55:44, inferred_ty: u32
 |
 fn match_assoc_const() -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/building/user_type_annotations.match_assoc_const_range.built.after.mir b/tests/mir-opt/building/user_type_annotations.match_assoc_const_range.built.after.mir
index 3a6aa5b7c2c..4cc433f475f 100644
--- a/tests/mir-opt/building/user_type_annotations.match_assoc_const_range.built.after.mir
+++ b/tests/mir-opt/building/user_type_annotations.match_assoc_const_range.built.after.mir
@@ -1,10 +1,10 @@
 // MIR for `match_assoc_const_range` after built
 
 | User Type Annotations
-| 0: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:62:11: 62:46, inferred_ty: u32
-| 1: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:62:11: 62:46, inferred_ty: u32
-| 2: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:63:9: 63:44, inferred_ty: u32
-| 3: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:63:9: 63:44, inferred_ty: u32
+| 0: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:63:11: 63:46, inferred_ty: u32
+| 1: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:63:11: 63:46, inferred_ty: u32
+| 2: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:64:9: 64:44, inferred_ty: u32
+| 3: user_ty: Canonical { value: TypeOf(DefId(0:11 ~ user_type_annotations[ee8e]::MyTrait::FOO), UserArgs { args: [MyStruct, 'static], user_self_ty: None }), max_universe: U0, variables: [] }, span: $DIR/user_type_annotations.rs:64:9: 64:44, inferred_ty: u32
 |
 fn match_assoc_const_range() -> () {
     let mut _0: ();
diff --git a/tests/mir-opt/building/user_type_annotations.rs b/tests/mir-opt/building/user_type_annotations.rs
index d55c678d5ae..527bf62f7dc 100644
--- a/tests/mir-opt/building/user_type_annotations.rs
+++ b/tests/mir-opt/building/user_type_annotations.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zmir-opt-level=0
 //@ edition: 2024
 // skip-filecheck
 
diff --git a/tests/run-make/rustdoc-default-output/output-default.stdout b/tests/run-make/rustdoc-default-output/output-default.stdout
index 506f135ff8e..badbc0b6d15 100644
--- a/tests/run-make/rustdoc-default-output/output-default.stdout
+++ b/tests/run-make/rustdoc-default-output/output-default.stdout
@@ -194,6 +194,9 @@ Options:
         --disable-minification 
                         disable the minification of CSS/JS files
                         (perma-unstable, do not use with cached files)
+        --generate-macro-expansion 
+                        Add possibility to expand macros in the HTML source
+                        code pages
         --plugin-path DIR
                         removed, see issue #44136
                         <https://github.com/rust-lang/rust/issues/44136> for
diff --git a/tests/rustdoc-gui/macro-expansion.goml b/tests/rustdoc-gui/macro-expansion.goml
new file mode 100644
index 00000000000..b87d0e4870a
--- /dev/null
+++ b/tests/rustdoc-gui/macro-expansion.goml
@@ -0,0 +1,126 @@
+// This test ensures that the macro expansion is generated and working as expected.
+go-to: "file://" + |DOC_PATH| + "/src/macro_expansion/lib.rs.html"
+
+define-function: (
+    "check-expansion",
+    [line, original_content],
+    block {
+        assert-text: ("a[id='" + |line| + "'] + .expansion .original", |original_content|)
+        // The "original" content should be expanded.
+        assert-css: ("a[id='" + |line| + "'] + .expansion .original", {"display": "inline"})
+        // The expanded macro should be hidden.
+        assert-css: ("a[id='" + |line| + "'] + .expansion .expanded", {"display": "none"})
+
+        // We "expand" the macro.
+        click: "a[id='" + |line| + "'] + .expansion input[type=checkbox]"
+        // The "original" content is hidden.
+        assert-css: ("a[id='" + |line| + "'] + .expansion .original", {"display": "none"})
+        // The expanded macro is visible.
+        assert-css: ("a[id='" + |line| + "'] + .expansion .expanded", {"display": "inline"})
+
+        // We collapse the macro.
+        click: "a[id='" + |line| + "'] + .expansion input[type=checkbox]"
+        // The "original" content is expanded.
+        assert-css: ("a[id='" + |line| + "'] + .expansion .original", {"display": "inline"})
+        // The expanded macro is hidden.
+        assert-css: ("a[id='" + |line| + "'] + .expansion .expanded", {"display": "none"})
+    }
+)
+
+// First we check the derive macro expansion at line 33.
+call-function: ("check-expansion", {"line": 35, "original_content": "Debug"})
+// Then we check the `bar` macro expansion at line 41.
+call-function: ("check-expansion", {"line": 43, "original_content": "bar!(y)"})
+// Then we check the `println` macro expansion at line 42-44.
+call-function: ("check-expansion", {"line": 44, "original_content": 'println!("
+45    {y}
+46    ")'})
+
+// Then finally we check when there are two macro calls on a same line.
+assert-count: ("#expand-52 ~ .original", 2)
+assert-count: ("#expand-52 ~ .expanded", 2)
+
+store-value: (repeat_o, '/following-sibling::*[@class="original"]')
+store-value: (repeat_e, '/following-sibling::*[@class="expanded"]')
+store-value: (expand_id, "expand-52")
+assert-text: ('//*[@id="' + |expand_id| + '"]' + |repeat_o|, "stringify!(foo)")
+assert-text: ('//*[@id="' + |expand_id| + '"]' + |repeat_o| + |repeat_o|, "stringify!(bar)")
+assert-text: ('//*[@id="' + |expand_id| + '"]' + |repeat_e|, '"foo"')
+assert-text: ('//*[@id="' + |expand_id| + '"]' + |repeat_e| + |repeat_e|, '"bar"')
+
+// The "original" content should be expanded.
+assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_o|, {"display": "inline"})
+assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_o| + |repeat_o|, {"display": "inline"})
+// The expanded macro should be hidden.
+assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_e|, {"display": "none"})
+assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_e| + |repeat_e|, {"display": "none"})
+
+// We "expand" the macro (because the line starts with a string, the label is not at the "top
+// level" of the `<code>`, so we need to use a different selector).
+click: "#" + |expand_id|
+// The "original" content is hidden.
+assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_o|, {"display": "none"})
+assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_o| + |repeat_o|, {"display": "none"})
+// The expanded macro is visible.
+assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_e|, {"display": "inline"})
+assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_e| + |repeat_e|, {"display": "inline"})
+
+// We collapse the macro.
+click: "#" + |expand_id|
+// The "original" content is expanded.
+assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_o|, {"display": "inline"})
+assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_o| + |repeat_o|, {"display": "inline"})
+// The expanded macro is hidden.
+assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_e|, {"display": "none"})
+assert-css: ('//*[@id="' + |expand_id| + '"]' + |repeat_e| + |repeat_e|, {"display": "none"})
+
+// Checking the line 48 `println` which needs to be handled differently because the line number is
+// inside a "comment" span.
+store-value: (expand_id, "expand-48")
+assert-text: ("#" + |expand_id| + " ~ .original", 'println!("
+49    {y}
+50    ")')
+// The "original" content should be expanded.
+assert-css: ("#" + |expand_id| + " ~ .original", {"display": "inline"})
+// The expanded macro should be hidden.
+assert-css: ("#" + |expand_id| + " ~ .expanded", {"display": "none"})
+
+// We "expand" the macro.
+click: "#" + |expand_id|
+// The "original" content is hidden.
+assert-css: ("#" + |expand_id| + " ~ .original", {"display": "none"})
+// The expanded macro is visible.
+assert-css: ("#" + |expand_id| + " ~ .expanded", {"display": "inline"})
+
+// We collapse the macro.
+click: "#" + |expand_id|
+// The "original" content is expanded.
+assert-css: ("#" + |expand_id| + " ~ .original", {"display": "inline"})
+// The expanded macro is hidden.
+assert-css: ("#" + |expand_id| + " ~ .expanded", {"display": "none"})
+
+// Ensure that the toggles are focusable and can be interacted with keyboard.
+focus: "//a[@id='29']"
+press-key: "Tab"
+store-value: (expand_id, "expand-29")
+assert: "#" + |expand_id| + ":focus"
+assert-css: ("#" + |expand_id| +" ~ .expanded", {"display": "none"})
+assert-css: ("#" + |expand_id| +" ~ .original", {"display": "inline"})
+// We now expand the macro.
+press-key: "Space"
+assert-css: ("#" + |expand_id| + " ~ .expanded", {"display": "inline"})
+assert-css: ("#" + |expand_id| + " ~ .original", {"display": "none"})
+// We collapse the macro.
+press-key: "Space"
+assert-css: ("#" + |expand_id| + " ~ .expanded", {"display": "none"})
+assert-css: ("#" + |expand_id| + " ~ .original", {"display": "inline"})
+
+// Now we check a macro coming from another file.
+store-value: (expand_id, "expand-55")
+// We "expand" the macro.
+click: "#" + |expand_id|
+// The "original" content is hidden.
+assert-css: ("#" + |expand_id| + " ~ .original", {"display": "none"})
+// The expanded macro is visible.
+assert-css: ("#" + |expand_id| + " ~ .expanded", {"display": "inline"})
+assert-text: ("#" + |expand_id| + " ~ .expanded", "{ y += 2; };")
diff --git a/tests/rustdoc-gui/sidebar-source-code.goml b/tests/rustdoc-gui/sidebar-source-code.goml
index 0ac88612cef..3f6914a89d6 100644
--- a/tests/rustdoc-gui/sidebar-source-code.goml
+++ b/tests/rustdoc-gui/sidebar-source-code.goml
@@ -71,7 +71,7 @@ assert: "//*[@class='dir-entry' and @open]/*[normalize-space()='sub_mod']"
 // Only "another_folder" should be "open" in "lib2".
 assert: "//*[@class='dir-entry' and not(@open)]/*[normalize-space()='another_mod']"
 // All other trees should be collapsed.
-assert-count: ("//*[@id='src-sidebar']/details[not(normalize-space()='lib2') and not(@open)]", 11)
+assert-count: ("//*[@id='src-sidebar']/details[not(normalize-space()='lib2') and not(@open)]", 12)
 
 // We now switch to mobile mode.
 set-window-size: (600, 600)
diff --git a/tests/rustdoc-gui/src/macro_expansion/Cargo.lock b/tests/rustdoc-gui/src/macro_expansion/Cargo.lock
new file mode 100644
index 00000000000..9c5cee8fb9d
--- /dev/null
+++ b/tests/rustdoc-gui/src/macro_expansion/Cargo.lock
@@ -0,0 +1,7 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "macro_expansion"
+version = "0.1.0"
diff --git a/tests/rustdoc-gui/src/macro_expansion/Cargo.toml b/tests/rustdoc-gui/src/macro_expansion/Cargo.toml
new file mode 100644
index 00000000000..6d362850fc5
--- /dev/null
+++ b/tests/rustdoc-gui/src/macro_expansion/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "macro_expansion"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+path = "lib.rs"
diff --git a/tests/rustdoc-gui/src/macro_expansion/lib.rs b/tests/rustdoc-gui/src/macro_expansion/lib.rs
new file mode 100644
index 00000000000..62a92d5d15e
--- /dev/null
+++ b/tests/rustdoc-gui/src/macro_expansion/lib.rs
@@ -0,0 +1,56 @@
+// Test crate used to check the `--generate-macro-expansion` option.
+//@ compile-flags: -Zunstable-options --generate-macro-expansion --generate-link-to-definition
+
+mod other;
+
+#[macro_export]
+macro_rules! bar {
+    ($x:ident) => {{
+        $x += 2;
+        $x *= 2;
+    }}
+}
+
+macro_rules! bar2 {
+    () => {
+        fn foo2() -> impl std::fmt::Display {
+            String::new()
+        }
+    }
+}
+
+macro_rules! bar3 {
+    () => {
+        fn foo3() {}
+        fn foo4() -> String { String::new() }
+    }
+}
+
+bar2!();
+bar3!();
+
+#[derive(Debug, PartialEq)]
+pub struct Bar;
+
+#[derive(Debug
+)]
+pub struct Bar2;
+
+fn y_f(_: &str, _: &str, _: &str) {}
+
+fn foo() {
+    let mut y = 0;
+    bar!(y);
+    println!("
+    {y}
+    ");
+    // comment
+    println!("
+    {y}
+    ");
+    let s = y_f("\
+bla", stringify!(foo), stringify!(bar));
+
+    // Macro from another file.
+    other_macro!(y);
+}
diff --git a/tests/rustdoc-gui/src/macro_expansion/other.rs b/tests/rustdoc-gui/src/macro_expansion/other.rs
new file mode 100644
index 00000000000..8661b01be38
--- /dev/null
+++ b/tests/rustdoc-gui/src/macro_expansion/other.rs
@@ -0,0 +1,6 @@
+#[macro_export]
+macro_rules! other_macro {
+    ($x:ident) => {{
+        $x += 2;
+    }}
+}
diff --git a/tests/rustdoc-ui/lints/invalid-html-tags.rs b/tests/rustdoc-ui/lints/invalid-html-tags.rs
index 317f1fd1d46..8003e5efdd5 100644
--- a/tests/rustdoc-ui/lints/invalid-html-tags.rs
+++ b/tests/rustdoc-ui/lints/invalid-html-tags.rs
@@ -43,7 +43,7 @@ pub fn b() {}
 ///   <h3>
 //~^ ERROR unclosed HTML tag `h3`
 /// <script
-//~^ ERROR unclosed HTML tag `script`
+//~^ ERROR incomplete HTML tag `script`
 pub fn c() {}
 
 // Unclosed tags shouldn't warn if they are nested inside a <script> elem.
@@ -72,6 +72,7 @@ pub fn e() {}
 /// <div></div >
 /// <div></div
 //~^ ERROR unclosed HTML tag `div`
+//~| ERROR incomplete HTML tag `div`
 pub fn f() {}
 
 /// <!---->
@@ -105,7 +106,7 @@ pub fn j() {}
 /// uiapp.run(&env::args().collect::<Vec<_>>());
 /// ```
 ///
-/// <Vec<_> shouldn't warn!
+// <Vec<_> shouldn't warn!
 /// ``````
 pub fn k() {}
 
@@ -121,3 +122,92 @@ pub fn no_error_1() {}
 /// backslashed \<<a href="">
 //~^ ERROR unclosed HTML tag `a`
 pub fn p() {}
+
+/// <svg width="512" height="512" viewBox="0 0 512" fill="none" xmlns="http://www.w3.org/2000/svg">
+///     <rect
+///        width="256"
+///        height="256"
+///        fill="#5064C8"
+///        stroke="black"
+///     />
+/// </svg>
+pub fn no_error_2() {}
+
+/// <div>
+///     <img
+///         src="https://example.com/ferris.png"
+///         width="512"
+///         height="512"
+///     />
+/// </div>
+pub fn no_error_3() {}
+
+/// > <div
+/// > class="foo">
+/// > </div>
+pub fn no_error_4() {}
+
+/// unfinished ALLOWED_UNCLOSED
+///
+/// note: CommonMark doesn't allow an html block to start with a multiline tag,
+/// so we use `<br>` a bunch to force these to be parsed as html blocks.
+///
+/// <br>
+/// <img
+//~^ ERROR incomplete HTML tag `img`
+pub fn q() {}
+
+/// nested unfinished ALLOWED_UNCLOSED
+/// <p><img</p>
+//~^ ERROR incomplete HTML tag `img`
+pub fn r() {}
+
+/// > <br>
+/// > <img
+//~^ ERROR incomplete HTML tag `img`
+/// > href="#broken"
+pub fn s() {}
+
+/// <br>
+/// <br<br>
+//~^ ERROR incomplete HTML tag `br`
+pub fn t() {}
+
+/// <br>
+/// <br
+//~^ ERROR incomplete HTML tag `br`
+pub fn u() {}
+
+/// <a href=">" alt="<">html5 allows this</a>
+pub fn no_error_5() {}
+
+/// <br>
+/// <img title="
+/// html5
+/// allows
+/// multiline
+/// attr
+/// values
+/// these are just text, not tags:
+/// </div>
+/// <p/>
+/// <div>
+/// ">
+pub fn no_error_6() {}
+
+/// <br>
+/// <a href="data:text/html,<!DOCTYPE>
+/// <html>
+/// <body><b>this is allowed for some reason</b></body>
+/// </html>
+/// ">what</a>
+pub fn no_error_7() {}
+
+/// Technically this is allowed per the html5 spec,
+/// but there's basically no legitemate reason to do it,
+/// so we don't allow it.
+///
+/// <p <!-->foobar</p>
+//~^ ERROR Unclosed HTML comment
+//~| ERROR incomplete HTML tag `p`
+pub fn v() {}
diff --git a/tests/rustdoc-ui/lints/invalid-html-tags.stderr b/tests/rustdoc-ui/lints/invalid-html-tags.stderr
index 9c2bfcf2c3d..b6ec22c2479 100644
--- a/tests/rustdoc-ui/lints/invalid-html-tags.stderr
+++ b/tests/rustdoc-ui/lints/invalid-html-tags.stderr
@@ -52,6 +52,12 @@ error: unclosed HTML tag `p`
 LL | ///    <br/> <p>
    |              ^^^
 
+error: incomplete HTML tag `script`
+  --> $DIR/invalid-html-tags.rs:45:5
+   |
+LL | /// <script
+   |     ^^^^^^^
+
 error: unclosed HTML tag `div`
   --> $DIR/invalid-html-tags.rs:41:5
    |
@@ -64,11 +70,11 @@ error: unclosed HTML tag `h3`
 LL | ///   <h3>
    |       ^^^^
 
-error: unclosed HTML tag `script`
-  --> $DIR/invalid-html-tags.rs:45:5
+error: incomplete HTML tag `div`
+  --> $DIR/invalid-html-tags.rs:73:10
    |
-LL | /// <script
-   |     ^^^^^^
+LL | /// <div></div
+   |          ^^^^^
 
 error: unclosed HTML tag `div`
   --> $DIR/invalid-html-tags.rs:73:5
@@ -77,28 +83,73 @@ LL | /// <div></div
    |     ^^^^^
 
 error: Unclosed HTML comment
-  --> $DIR/invalid-html-tags.rs:87:5
+  --> $DIR/invalid-html-tags.rs:88:5
    |
 LL | /// <!--
-   |     ^^^
+   |     ^^^^
 
 error: unopened HTML tag `unopened-tag`
-  --> $DIR/invalid-html-tags.rs:114:26
+  --> $DIR/invalid-html-tags.rs:115:26
    |
 LL | /// Web Components style </unopened-tag>
    |                          ^^^^^^^^^^^^^^^
 
 error: unclosed HTML tag `dashed-tags`
-  --> $DIR/invalid-html-tags.rs:112:26
+  --> $DIR/invalid-html-tags.rs:113:26
    |
 LL | /// Web Components style <dashed-tags>
    |                          ^^^^^^^^^^^^^
 
 error: unclosed HTML tag `a`
-  --> $DIR/invalid-html-tags.rs:121:19
+  --> $DIR/invalid-html-tags.rs:122:19
    |
 LL | /// backslashed \<<a href="">
    |                   ^^
 
-error: aborting due to 16 previous errors
+error: incomplete HTML tag `img`
+  --> $DIR/invalid-html-tags.rs:156:5
+   |
+LL | /// <img
+   |     ^^^^
+
+error: incomplete HTML tag `img`
+  --> $DIR/invalid-html-tags.rs:161:8
+   |
+LL | /// <p><img</p>
+   |        ^^^^
+
+error: incomplete HTML tag `img`
+  --> $DIR/invalid-html-tags.rs:166:7
+   |
+LL |   /// > <img
+   |  _______^
+LL | |
+LL | | /// > href="#broken"
+   | |____________________^
+
+error: incomplete HTML tag `br`
+  --> $DIR/invalid-html-tags.rs:172:5
+   |
+LL | /// <br<br>
+   |     ^^^
+
+error: incomplete HTML tag `br`
+  --> $DIR/invalid-html-tags.rs:177:5
+   |
+LL | /// <br
+   |     ^^^
+
+error: incomplete HTML tag `p`
+  --> $DIR/invalid-html-tags.rs:210:5
+   |
+LL | /// <p <!-->foobar</p>
+   |     ^^^
+
+error: Unclosed HTML comment
+  --> $DIR/invalid-html-tags.rs:210:8
+   |
+LL | /// <p <!-->foobar</p>
+   |        ^^^^
+
+error: aborting due to 24 previous errors
 
diff --git a/tests/rustdoc/attribute-rendering.rs b/tests/rustdoc/attribute-rendering.rs
index bf9b81077f3..fb40d0a9887 100644
--- a/tests/rustdoc/attribute-rendering.rs
+++ b/tests/rustdoc/attribute-rendering.rs
@@ -1,7 +1,8 @@
 #![crate_name = "foo"]
 
 //@ has 'foo/fn.f.html'
-//@ has - //*[@'class="rust item-decl"]' '#[unsafe(export_name = "f")] pub fn f()'
+//@ has - //*[@'class="code-attribute"]' '#[unsafe(export_name = "f")]'
+//@ has - //*[@'class="rust item-decl"]' 'pub fn f()'
 #[unsafe(export_name = "\
 f")]
 pub fn f() {}
diff --git a/tests/rustdoc/attributes.rs b/tests/rustdoc/attributes.rs
index 34487a89127..33e4e31bec6 100644
--- a/tests/rustdoc/attributes.rs
+++ b/tests/rustdoc/attributes.rs
@@ -1,18 +1,81 @@
 //@ edition: 2024
 #![crate_name = "foo"]
 
-//@ has foo/fn.f.html '//pre[@class="rust item-decl"]' '#[unsafe(no_mangle)]'
+//@ has foo/fn.f.html '//*[@class="code-attribute"]' '#[unsafe(no_mangle)]'
 #[unsafe(no_mangle)]
 pub extern "C" fn f() {}
 
-//@ has foo/fn.g.html '//pre[@class="rust item-decl"]' '#[unsafe(export_name = "bar")]'
+//@ has foo/fn.g.html '//*[@class="code-attribute"]' '#[unsafe(export_name = "bar")]'
 #[unsafe(export_name = "bar")]
 pub extern "C" fn g() {}
 
-//@ has foo/fn.example.html '//pre[@class="rust item-decl"]' '#[unsafe(link_section = ".text")]'
+//@ has foo/fn.example.html '//*[@class="code-attribute"]' '#[unsafe(link_section = ".text")]'
 #[unsafe(link_section = ".text")]
 pub extern "C" fn example() {}
 
-//@ has foo/struct.Repr.html '//pre[@class="rust item-decl"]' '#[repr(C, align(8))]'
+//@ has foo/struct.Repr.html '//*[@class="code-attribute"]' '#[repr(C, align(8))]'
 #[repr(C, align(8))]
 pub struct Repr;
+
+//@ has foo/macro.macro_rule.html '//*[@class="code-attribute"]' '#[unsafe(link_section = ".text")]'
+#[unsafe(link_section = ".text")]
+#[macro_export]
+macro_rules! macro_rule {
+    () => {};
+}
+
+//@ has 'foo/enum.Enum.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "enum")]'
+#[unsafe(link_section = "enum")]
+pub enum Enum {
+    //@ has 'foo/enum.Enum.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "a")]'
+    //@ has - '//*[@class="variants"]//*[@class="code-attribute"]' '#[unsafe(link_section = "a")]'
+    #[unsafe(link_section = "a")]
+    A,
+    //@ has 'foo/enum.Enum.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "quz")]'
+    //@ has - '//*[@class="variants"]//*[@class="code-attribute"]' '#[unsafe(link_section = "quz")]'
+    #[unsafe(link_section = "quz")]
+    Quz {
+        //@ has 'foo/enum.Enum.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "b")]'
+        //@ has - '//*[@class="variants"]//*[@class="code-attribute"]' '#[unsafe(link_section = "b")]'
+        #[unsafe(link_section = "b")]
+        b: (),
+    },
+}
+
+//@ has 'foo/trait.Trait.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "trait")]'
+#[unsafe(link_section = "trait")]
+pub trait Trait {
+    //@ has 'foo/trait.Trait.html'
+    //@ has - '//*[@id="associatedconstant.BAR"]/*[@class="code-header"]/*[@class="code-attribute"]' '#[unsafe(link_section = "bar")]'
+    //@ has - '//*[@id="associatedconstant.BAR"]/*[@class="code-header"]' 'const BAR: u32 = 0u32'
+    #[unsafe(link_section = "bar")]
+    const BAR: u32 = 0;
+
+    //@ has - '//*[@class="code-attribute"]' '#[unsafe(link_section = "foo")]'
+    #[unsafe(link_section = "foo")]
+    fn foo() {}
+}
+
+//@ has 'foo/union.Union.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "union")]'
+#[unsafe(link_section = "union")]
+pub union Union {
+    //@ has 'foo/union.Union.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "x")]'
+    #[unsafe(link_section = "x")]
+    pub x: u32,
+    y: f32,
+}
+
+//@ has 'foo/struct.Struct.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "struct")]'
+#[unsafe(link_section = "struct")]
+pub struct Struct {
+    //@ has 'foo/struct.Struct.html' '//*[@class="code-attribute"]' '#[unsafe(link_section = "x")]'
+    //@ has - '//*[@id="structfield.x"]//*[@class="code-attribute"]' '#[unsafe(link_section = "x")]'
+    #[unsafe(link_section = "x")]
+    pub x: u32,
+    y: f32,
+}
+
+// Check that the attributes from the trait items show up consistently in the impl.
+//@ has 'foo/struct.Struct.html' '//*[@id="trait-implementations-list"]//*[@class="code-attribute"]' '#[unsafe(link_section = "bar")]'
+//@ has 'foo/struct.Struct.html' '//*[@id="trait-implementations-list"]//*[@class="code-attribute"]' '#[unsafe(link_section = "foo")]'
+impl Trait for Struct {}
diff --git a/tests/rustdoc/enum/enum-variant-non_exhaustive.type-alias-code.html b/tests/rustdoc/enum/enum-variant-non_exhaustive.type-alias-code.html
index 04eea709079..e8b8e93beb4 100644
--- a/tests/rustdoc/enum/enum-variant-non_exhaustive.type-alias-code.html
+++ b/tests/rustdoc/enum/enum-variant-non_exhaustive.type-alias-code.html
@@ -1,4 +1,4 @@
 <code>pub enum TypeAlias {
-    #[non_exhaustive]
+    <div class="code-attribute">#[non_exhaustive]</div>
     Variant,
-}</code>
\ No newline at end of file
+}</code>
diff --git a/tests/rustdoc/enum/enum-variant-non_exhaustive.type-code.html b/tests/rustdoc/enum/enum-variant-non_exhaustive.type-code.html
index 6c8851ea5df..51763c824eb 100644
--- a/tests/rustdoc/enum/enum-variant-non_exhaustive.type-code.html
+++ b/tests/rustdoc/enum/enum-variant-non_exhaustive.type-code.html
@@ -1,4 +1,4 @@
 <code>pub enum Type {
-    #[non_exhaustive]
+    <div class="code-attribute">#[non_exhaustive]</div>
     Variant,
-}</code>
\ No newline at end of file
+}</code>
diff --git a/tests/rustdoc/macro/macro_expansion.rs b/tests/rustdoc/macro/macro_expansion.rs
new file mode 100644
index 00000000000..c989ccad967
--- /dev/null
+++ b/tests/rustdoc/macro/macro_expansion.rs
@@ -0,0 +1,28 @@
+// This test checks that patterns and statements are also getting expanded.
+
+//@ compile-flags: -Zunstable-options --generate-macro-expansion
+
+#![crate_name = "foo"]
+
+//@ has 'src/foo/macro_expansion.rs.html'
+//@ count - '//span[@class="expansion"]' 2
+
+macro_rules! pat {
+    ($x:literal) => {
+        Some($x)
+    }
+}
+
+macro_rules! stmt {
+    ($x:expr) => {{
+        let _ = $x;
+    }}
+}
+
+fn bar() {
+    match Some("hello") {
+        pat!("blolb") => {}
+        _ => {}
+    }
+    stmt!(1)
+}
diff --git a/tests/rustdoc/type-alias/repr.rs b/tests/rustdoc/type-alias/repr.rs
index cf907980360..884ed74264a 100644
--- a/tests/rustdoc/type-alias/repr.rs
+++ b/tests/rustdoc/type-alias/repr.rs
@@ -22,7 +22,8 @@ pub union Foo2 {
 }
 
 //@ has 'foo/type.Bar2.html'
-//@ matches - '//*[@class="rust item-decl"]' '#\[repr\(C\)\]\npub union Bar2 \{*'
+//@ matches - '//*[@class="code-attribute"]' '#\[repr\(C\)\]'
+//@ matches - '//*[@class="rust item-decl"]' 'pub union Bar2 \{*'
 // Ensures that we see the doc comment of the type alias and not of the aliased type.
 //@ has - '//*[@class="toggle top-doc"]/*[@class="docblock"]' 'bar'
 /// bar
diff --git a/tests/ui/abi/c-zst.powerpc-linux.stderr b/tests/ui/abi/c-zst.powerpc-linux.stderr
index b8d6c632b97..ec6b9b8f027 100644
--- a/tests/ui/abi/c-zst.powerpc-linux.stderr
+++ b/tests/ui/abi/c-zst.powerpc-linux.stderr
@@ -27,7 +27,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                    },
                    mode: Indirect {
                        attrs: ArgAttributes {
-                           regular: NoAlias | NoCapture | NonNull | NoUndef,
+                           regular: NoAlias | CapturesAddress | NonNull | NoUndef,
                            arg_ext: None,
                            pointee_size: Size(0 bytes),
                            pointee_align: Some(
diff --git a/tests/ui/abi/c-zst.s390x-linux.stderr b/tests/ui/abi/c-zst.s390x-linux.stderr
index b8d6c632b97..ec6b9b8f027 100644
--- a/tests/ui/abi/c-zst.s390x-linux.stderr
+++ b/tests/ui/abi/c-zst.s390x-linux.stderr
@@ -27,7 +27,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                    },
                    mode: Indirect {
                        attrs: ArgAttributes {
-                           regular: NoAlias | NoCapture | NonNull | NoUndef,
+                           regular: NoAlias | CapturesAddress | NonNull | NoUndef,
                            arg_ext: None,
                            pointee_size: Size(0 bytes),
                            pointee_align: Some(
diff --git a/tests/ui/abi/c-zst.sparc64-linux.stderr b/tests/ui/abi/c-zst.sparc64-linux.stderr
index b8d6c632b97..ec6b9b8f027 100644
--- a/tests/ui/abi/c-zst.sparc64-linux.stderr
+++ b/tests/ui/abi/c-zst.sparc64-linux.stderr
@@ -27,7 +27,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                    },
                    mode: Indirect {
                        attrs: ArgAttributes {
-                           regular: NoAlias | NoCapture | NonNull | NoUndef,
+                           regular: NoAlias | CapturesAddress | NonNull | NoUndef,
                            arg_ext: None,
                            pointee_size: Size(0 bytes),
                            pointee_align: Some(
diff --git a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr
index b8d6c632b97..ec6b9b8f027 100644
--- a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr
+++ b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr
@@ -27,7 +27,7 @@ error: fn_abi_of(pass_zst) = FnAbi {
                    },
                    mode: Indirect {
                        attrs: ArgAttributes {
-                           regular: NoAlias | NoCapture | NonNull | NoUndef,
+                           regular: NoAlias | CapturesAddress | NonNull | NoUndef,
                            arg_ext: None,
                            pointee_size: Size(0 bytes),
                            pointee_align: Some(
diff --git a/tests/ui/abi/debug.generic.stderr b/tests/ui/abi/debug.generic.stderr
index 0fec35dabdd..47341da221f 100644
--- a/tests/ui/abi/debug.generic.stderr
+++ b/tests/ui/abi/debug.generic.stderr
@@ -454,7 +454,7 @@ error: ABIs are not compatible
                    },
                    mode: Indirect {
                        attrs: ArgAttributes {
-                           regular: NoAlias | NoCapture | NonNull | NoUndef,
+                           regular: NoAlias | CapturesAddress | NonNull | NoUndef,
                            arg_ext: None,
                            pointee_size: Size(32 bytes),
                            pointee_align: Some(
@@ -527,7 +527,7 @@ error: ABIs are not compatible
                    },
                    mode: Indirect {
                        attrs: ArgAttributes {
-                           regular: NoAlias | NoCapture | NonNull | NoUndef,
+                           regular: NoAlias | CapturesAddress | NonNull | NoUndef,
                            arg_ext: None,
                            pointee_size: Size(128 bytes),
                            pointee_align: Some(
diff --git a/tests/ui/abi/debug.loongarch64.stderr b/tests/ui/abi/debug.loongarch64.stderr
index ce8bd41f045..94a01a80873 100644
--- a/tests/ui/abi/debug.loongarch64.stderr
+++ b/tests/ui/abi/debug.loongarch64.stderr
@@ -454,7 +454,7 @@ error: ABIs are not compatible
                    },
                    mode: Indirect {
                        attrs: ArgAttributes {
-                           regular: NoAlias | NoCapture | NonNull | NoUndef,
+                           regular: NoAlias | CapturesAddress | NonNull | NoUndef,
                            arg_ext: None,
                            pointee_size: Size(32 bytes),
                            pointee_align: Some(
@@ -527,7 +527,7 @@ error: ABIs are not compatible
                    },
                    mode: Indirect {
                        attrs: ArgAttributes {
-                           regular: NoAlias | NoCapture | NonNull | NoUndef,
+                           regular: NoAlias | CapturesAddress | NonNull | NoUndef,
                            arg_ext: None,
                            pointee_size: Size(128 bytes),
                            pointee_align: Some(
diff --git a/tests/ui/abi/debug.riscv64.stderr b/tests/ui/abi/debug.riscv64.stderr
index ce8bd41f045..94a01a80873 100644
--- a/tests/ui/abi/debug.riscv64.stderr
+++ b/tests/ui/abi/debug.riscv64.stderr
@@ -454,7 +454,7 @@ error: ABIs are not compatible
                    },
                    mode: Indirect {
                        attrs: ArgAttributes {
-                           regular: NoAlias | NoCapture | NonNull | NoUndef,
+                           regular: NoAlias | CapturesAddress | NonNull | NoUndef,
                            arg_ext: None,
                            pointee_size: Size(32 bytes),
                            pointee_align: Some(
@@ -527,7 +527,7 @@ error: ABIs are not compatible
                    },
                    mode: Indirect {
                        attrs: ArgAttributes {
-                           regular: NoAlias | NoCapture | NonNull | NoUndef,
+                           regular: NoAlias | CapturesAddress | NonNull | NoUndef,
                            arg_ext: None,
                            pointee_size: Size(128 bytes),
                            pointee_align: Some(
diff --git a/tests/ui/associated-inherent-types/issue-111404-1.stderr b/tests/ui/associated-inherent-types/issue-111404-1.stderr
index ce49126c316..9a5b69497c0 100644
--- a/tests/ui/associated-inherent-types/issue-111404-1.stderr
+++ b/tests/ui/associated-inherent-types/issue-111404-1.stderr
@@ -32,12 +32,10 @@ LL | fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {}
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: higher-ranked subtype error
-  --> $DIR/issue-111404-1.rs:10:1
+  --> $DIR/issue-111404-1.rs:10:8
    |
 LL | fn bar(_: fn(Foo<for<'b> fn(Foo<fn(&'b ())>::Assoc)>::Assoc)) {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+   |        ^
 
 error: aborting due to 5 previous errors
 
diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr
index 3d82f572a1a..823d8d5b92f 100644
--- a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr
+++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr
@@ -25,6 +25,7 @@ error[E0599]: no method named `poll` found for struct `Pin<&mut impl Future<Outp
    |
 LL |         match fut.as_mut().poll(ctx) {
    |                            ^^^^ method not found in `Pin<&mut impl Future<Output = ()>>`
+   |
   --> $SRC_DIR/core/src/future/future.rs:LL:COL
    |
    = note: the method is available for `Pin<&mut impl Future<Output = ()>>` here
diff --git a/tests/ui/attributes/attr-on-mac-call.rs b/tests/ui/attributes/attr-on-mac-call.rs
new file mode 100644
index 00000000000..a23ced123ef
--- /dev/null
+++ b/tests/ui/attributes/attr-on-mac-call.rs
@@ -0,0 +1,73 @@
+//@ check-pass
+// Regression test for https://github.com/rust-lang/rust/issues/145779
+#![warn(unused_attributes)]
+
+fn main() {
+    #[export_name = "x"]
+    //~^ WARN attribute cannot be used on macro calls
+    //~| WARN previously accepted
+    #[unsafe(naked)]
+    //~^ WARN attribute cannot be used on macro calls
+    //~| WARN previously accepted
+    #[track_caller]
+    //~^ WARN attribute cannot be used on macro calls
+    //~| WARN previously accepted
+    #[used]
+    //~^ WARN attribute cannot be used on macro calls
+    //~| WARN previously accepted
+    #[target_feature(enable = "x")]
+    //~^ WARN attribute cannot be used on macro calls
+    //~| WARN previously accepted
+    #[deprecated]
+    //~^ WARN attribute cannot be used on macro calls
+    //~| WARN previously accepted
+    #[inline]
+    //~^ WARN attribute cannot be used on macro calls
+    //~| WARN previously accepted
+    #[link_name = "x"]
+    //~^ WARN attribute cannot be used on macro calls
+    //~| WARN previously accepted
+    #[link_section = "x"]
+    //~^ WARN attribute cannot be used on macro calls
+    //~| WARN previously accepted
+    #[link_ordinal(42)]
+    //~^ WARN attribute cannot be used on macro calls
+    //~| WARN previously accepted
+    #[non_exhaustive]
+    //~^ WARN attribute cannot be used on macro calls
+    //~| WARN previously accepted
+    #[proc_macro]
+    //~^ WARN attribute cannot be used on macro calls
+    //~| WARN previously accepted
+    #[cold]
+    //~^ WARN attribute cannot be used on macro calls
+    //~| WARN previously accepted
+    #[no_mangle]
+    //~^ WARN attribute cannot be used on macro calls
+    //~| WARN previously accepted
+    #[deprecated]
+    //~^ WARN attribute cannot be used on macro calls
+    //~| WARN previously accepted
+    #[automatically_derived]
+    //~^ WARN attribute cannot be used on macro calls
+    //~| WARN previously accepted
+    #[macro_use]
+    //~^ WARN attribute cannot be used on macro calls
+    //~| WARN previously accepted
+    #[must_use]
+    //~^ WARN attribute cannot be used on macro calls
+    //~| WARN previously accepted
+    #[no_implicit_prelude]
+    //~^ WARN attribute cannot be used on macro calls
+    //~| WARN previously accepted
+    #[path = ""]
+    //~^ WARN attribute cannot be used on macro calls
+    //~| WARN previously accepted
+    #[ignore]
+    //~^ WARN attribute cannot be used on macro calls
+    //~| WARN previously accepted
+    #[should_panic]
+    //~^ WARN attribute cannot be used on macro calls
+    //~| WARN previously accepted
+    unreachable!();
+}
diff --git a/tests/ui/attributes/attr-on-mac-call.stderr b/tests/ui/attributes/attr-on-mac-call.stderr
new file mode 100644
index 00000000000..a08d3059168
--- /dev/null
+++ b/tests/ui/attributes/attr-on-mac-call.stderr
@@ -0,0 +1,205 @@
+warning: `#[export_name]` attribute cannot be used on macro calls
+  --> $DIR/attr-on-mac-call.rs:6:5
+   |
+LL |     #[export_name = "x"]
+   |     ^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[export_name]` can be applied to functions and statics
+note: the lint level is defined here
+  --> $DIR/attr-on-mac-call.rs:3:9
+   |
+LL | #![warn(unused_attributes)]
+   |         ^^^^^^^^^^^^^^^^^
+
+warning: `#[naked]` attribute cannot be used on macro calls
+  --> $DIR/attr-on-mac-call.rs:9:5
+   |
+LL |     #[unsafe(naked)]
+   |     ^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[naked]` can only be applied to functions
+
+warning: `#[track_caller]` attribute cannot be used on macro calls
+  --> $DIR/attr-on-mac-call.rs:12:5
+   |
+LL |     #[track_caller]
+   |     ^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[track_caller]` can only be applied to functions
+
+warning: `#[used]` attribute cannot be used on macro calls
+  --> $DIR/attr-on-mac-call.rs:15:5
+   |
+LL |     #[used]
+   |     ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[used]` can only be applied to statics
+
+warning: `#[target_feature]` attribute cannot be used on macro calls
+  --> $DIR/attr-on-mac-call.rs:18:5
+   |
+LL |     #[target_feature(enable = "x")]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[target_feature]` can only be applied to functions
+
+warning: `#[deprecated]` attribute cannot be used on macro calls
+  --> $DIR/attr-on-mac-call.rs:21:5
+   |
+LL |     #[deprecated]
+   |     ^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[deprecated]` can be applied to functions, data types, modules, unions, constants, statics, macro defs, type aliases, use statements, foreign statics, struct fields, traits, associated types, associated consts, enum variants, inherent impl blocks, and crates
+
+warning: `#[inline]` attribute cannot be used on macro calls
+  --> $DIR/attr-on-mac-call.rs:24:5
+   |
+LL |     #[inline]
+   |     ^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[inline]` can only be applied to functions
+
+warning: `#[link_name]` attribute cannot be used on macro calls
+  --> $DIR/attr-on-mac-call.rs:27:5
+   |
+LL |     #[link_name = "x"]
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[link_name]` can be applied to foreign functions and foreign statics
+
+warning: `#[link_section]` attribute cannot be used on macro calls
+  --> $DIR/attr-on-mac-call.rs:30:5
+   |
+LL |     #[link_section = "x"]
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[link_section]` can be applied to statics and functions
+
+warning: `#[link_ordinal]` attribute cannot be used on macro calls
+  --> $DIR/attr-on-mac-call.rs:33:5
+   |
+LL |     #[link_ordinal(42)]
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[link_ordinal]` can be applied to foreign functions and foreign statics
+
+warning: `#[non_exhaustive]` attribute cannot be used on macro calls
+  --> $DIR/attr-on-mac-call.rs:36:5
+   |
+LL |     #[non_exhaustive]
+   |     ^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[non_exhaustive]` can be applied to data types and enum variants
+
+warning: `#[proc_macro]` attribute cannot be used on macro calls
+  --> $DIR/attr-on-mac-call.rs:39:5
+   |
+LL |     #[proc_macro]
+   |     ^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[proc_macro]` can only be applied to functions
+
+warning: `#[cold]` attribute cannot be used on macro calls
+  --> $DIR/attr-on-mac-call.rs:42:5
+   |
+LL |     #[cold]
+   |     ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[cold]` can only be applied to functions
+
+warning: `#[no_mangle]` attribute cannot be used on macro calls
+  --> $DIR/attr-on-mac-call.rs:45:5
+   |
+LL |     #[no_mangle]
+   |     ^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[no_mangle]` can be applied to functions and statics
+
+warning: `#[deprecated]` attribute cannot be used on macro calls
+  --> $DIR/attr-on-mac-call.rs:48:5
+   |
+LL |     #[deprecated]
+   |     ^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[deprecated]` can be applied to functions, data types, modules, unions, constants, statics, macro defs, type aliases, use statements, foreign statics, struct fields, traits, associated types, associated consts, enum variants, inherent impl blocks, and crates
+
+warning: `#[automatically_derived]` attribute cannot be used on macro calls
+  --> $DIR/attr-on-mac-call.rs:51:5
+   |
+LL |     #[automatically_derived]
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[automatically_derived]` can only be applied to trait impl blocks
+
+warning: `#[macro_use]` attribute cannot be used on macro calls
+  --> $DIR/attr-on-mac-call.rs:54:5
+   |
+LL |     #[macro_use]
+   |     ^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[macro_use]` can be applied to modules, extern crates, and crates
+
+warning: `#[must_use]` attribute cannot be used on macro calls
+  --> $DIR/attr-on-mac-call.rs:57:5
+   |
+LL |     #[must_use]
+   |     ^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[must_use]` can be applied to functions, data types, unions, and traits
+
+warning: `#[no_implicit_prelude]` attribute cannot be used on macro calls
+  --> $DIR/attr-on-mac-call.rs:60:5
+   |
+LL |     #[no_implicit_prelude]
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[no_implicit_prelude]` can be applied to modules and crates
+
+warning: `#[path]` attribute cannot be used on macro calls
+  --> $DIR/attr-on-mac-call.rs:63:5
+   |
+LL |     #[path = ""]
+   |     ^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[path]` can only be applied to modules
+
+warning: `#[ignore]` attribute cannot be used on macro calls
+  --> $DIR/attr-on-mac-call.rs:66:5
+   |
+LL |     #[ignore]
+   |     ^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[ignore]` can only be applied to functions
+
+warning: `#[should_panic]` attribute cannot be used on macro calls
+  --> $DIR/attr-on-mac-call.rs:69:5
+   |
+LL |     #[should_panic]
+   |     ^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[should_panic]` can only be applied to functions
+
+warning: 22 warnings emitted
+
diff --git a/tests/ui/attributes/crate-name-empty.stderr b/tests/ui/attributes/crate-name-empty.stderr
index 509a42d05f7..31d9dd0e948 100644
--- a/tests/ui/attributes/crate-name-empty.stderr
+++ b/tests/ui/attributes/crate-name-empty.stderr
@@ -1,8 +1,8 @@
 error: crate name must not be empty
-  --> $DIR/crate-name-empty.rs:3:1
+  --> $DIR/crate-name-empty.rs:3:17
    |
 LL | #![crate_name = ""]
-   | ^^^^^^^^^^^^^^^^^^^
+   |                 ^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/attributes/crate-name-macro-call.rs b/tests/ui/attributes/crate-name-macro-call.rs
index 1aae2e506e2..61076349cc3 100644
--- a/tests/ui/attributes/crate-name-macro-call.rs
+++ b/tests/ui/attributes/crate-name-macro-call.rs
@@ -1,6 +1,6 @@
 // issue: rust-lang/rust#122001
 // Ensure we reject macro calls inside `#![crate_name]` as their result wouldn't get honored anyway.
 
-#![crate_name = concat!("my", "crate")] //~ ERROR malformed `crate_name` attribute input
+#![crate_name = concat!("my", "crate")] //~ ERROR attribute value must be a literal
 
 fn main() {}
diff --git a/tests/ui/attributes/crate-name-macro-call.stderr b/tests/ui/attributes/crate-name-macro-call.stderr
index 56827aa11a4..e988b8461d7 100644
--- a/tests/ui/attributes/crate-name-macro-call.stderr
+++ b/tests/ui/attributes/crate-name-macro-call.stderr
@@ -1,10 +1,8 @@
-error: malformed `crate_name` attribute input
-  --> $DIR/crate-name-macro-call.rs:4:1
+error: attribute value must be a literal
+  --> $DIR/crate-name-macro-call.rs:4:17
    |
 LL | #![crate_name = concat!("my", "crate")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_name = "name"]`
-   |
-   = note: for more information, visit <https://doc.rust-lang.org/reference/crates-and-source-files.html#the-crate_name-attribute>
+   |                 ^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/attributes/crate-name-mismatch.stderr b/tests/ui/attributes/crate-name-mismatch.stderr
index 4021fbe7c18..6416ad2d41a 100644
--- a/tests/ui/attributes/crate-name-mismatch.stderr
+++ b/tests/ui/attributes/crate-name-mismatch.stderr
@@ -1,8 +1,8 @@
 error: `--crate-name` and `#[crate_name]` are required to match, but `foo` != `bar`
-  --> $DIR/crate-name-mismatch.rs:5:1
+  --> $DIR/crate-name-mismatch.rs:5:17
    |
 LL | #![crate_name = "bar"]
-   | ^^^^^^^^^^^^^^^^^^^^^^
+   |                 ^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/attributes/crate-only-as-outer.rs b/tests/ui/attributes/crate-only-as-outer.rs
new file mode 100644
index 00000000000..5a7d916c90d
--- /dev/null
+++ b/tests/ui/attributes/crate-only-as-outer.rs
@@ -0,0 +1,10 @@
+#![deny(unused)]
+#[crate_name = "owo"]
+//~^ ERROR: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
+
+fn main() {}
+
+mod inner {
+    #![crate_name = "iwi"]
+    //~^ ERROR: the `#![crate_name]` attribute can only be used at the crate root
+}
diff --git a/tests/ui/attributes/crate-only-as-outer.stderr b/tests/ui/attributes/crate-only-as-outer.stderr
new file mode 100644
index 00000000000..270f02af987
--- /dev/null
+++ b/tests/ui/attributes/crate-only-as-outer.stderr
@@ -0,0 +1,26 @@
+error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
+  --> $DIR/crate-only-as-outer.rs:2:1
+   |
+LL | #[crate_name = "owo"]
+   | ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: This attribute does not have an `!`, which means it is applied to this function
+  --> $DIR/crate-only-as-outer.rs:5:1
+   |
+LL | fn main() {}
+   | ^^^^^^^^^^^^
+note: the lint level is defined here
+  --> $DIR/crate-only-as-outer.rs:1:9
+   |
+LL | #![deny(unused)]
+   |         ^^^^^^
+   = note: `#[deny(unused_attributes)]` implied by `#[deny(unused)]`
+
+error: the `#![crate_name]` attribute can only be used at the crate root
+  --> $DIR/crate-only-as-outer.rs:8:5
+   |
+LL |     #![crate_name = "iwi"]
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/attributes/malformed-attrs.rs b/tests/ui/attributes/malformed-attrs.rs
index 90ca007451e..932aaf7a9e2 100644
--- a/tests/ui/attributes/malformed-attrs.rs
+++ b/tests/ui/attributes/malformed-attrs.rs
@@ -81,8 +81,7 @@
 #[export_stable = 1]
 //~^ ERROR malformed
 #[link]
-//~^ ERROR valid forms for the attribute are
-//~| WARN this was previously accepted by the compiler
+//~^ ERROR malformed
 #[link_name]
 //~^ ERROR malformed
 #[link_section]
diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr
index 98ff578918b..b85864b401e 100644
--- a/tests/ui/attributes/malformed-attrs.stderr
+++ b/tests/ui/attributes/malformed-attrs.stderr
@@ -1,5 +1,5 @@
 error[E0539]: malformed `cfg` attribute input
-  --> $DIR/malformed-attrs.rs:102:1
+  --> $DIR/malformed-attrs.rs:101:1
    |
 LL | #[cfg]
    | ^^^^^^
@@ -10,7 +10,7 @@ LL | #[cfg]
    = note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute>
 
 error: malformed `cfg_attr` attribute input
-  --> $DIR/malformed-attrs.rs:104:1
+  --> $DIR/malformed-attrs.rs:103:1
    |
 LL | #[cfg_attr]
    | ^^^^^^^^^^^
@@ -22,7 +22,7 @@ LL | #[cfg_attr(condition, attribute, other_attribute, ...)]
    |           ++++++++++++++++++++++++++++++++++++++++++++
 
 error[E0463]: can't find crate for `wloop`
-  --> $DIR/malformed-attrs.rs:211:1
+  --> $DIR/malformed-attrs.rs:210:1
    |
 LL | extern crate wloop;
    | ^^^^^^^^^^^^^^^^^^^ can't find crate
@@ -41,34 +41,8 @@ LL | #![windows_subsystem = "console"]
 LL | #![windows_subsystem = "windows"]
    |                      +++++++++++
 
-error: malformed `crate_name` attribute input
-  --> $DIR/malformed-attrs.rs:74:1
-   |
-LL | #[crate_name]
-   | ^^^^^^^^^^^^^ help: must be of the form: `#[crate_name = "name"]`
-   |
-   = note: for more information, visit <https://doc.rust-lang.org/reference/crates-and-source-files.html#the-crate_name-attribute>
-
-error: malformed `sanitize` attribute input
-  --> $DIR/malformed-attrs.rs:92:1
-   |
-LL | #[sanitize]
-   | ^^^^^^^^^^^
-   |
-help: the following are the possible correct uses
-   |
-LL | #[sanitize(address = "on|off")]
-   |           ++++++++++++++++++++
-LL | #[sanitize(cfi = "on|off")]
-   |           ++++++++++++++++
-LL | #[sanitize(hwaddress = "on|off")]
-   |           ++++++++++++++++++++++
-LL | #[sanitize(kcfi = "on|off")]
-   |           +++++++++++++++++
-   = and 5 other candidates
-
 error: malformed `instruction_set` attribute input
-  --> $DIR/malformed-attrs.rs:106:1
+  --> $DIR/malformed-attrs.rs:105:1
    |
 LL | #[instruction_set]
    | ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[instruction_set(set)]`
@@ -76,13 +50,13 @@ LL | #[instruction_set]
    = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/codegen.html#the-instruction_set-attribute>
 
 error: malformed `patchable_function_entry` attribute input
-  --> $DIR/malformed-attrs.rs:108:1
+  --> $DIR/malformed-attrs.rs:107:1
    |
 LL | #[patchable_function_entry]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[patchable_function_entry(prefix_nops = m, entry_nops = n)]`
 
 error: malformed `must_not_suspend` attribute input
-  --> $DIR/malformed-attrs.rs:132:1
+  --> $DIR/malformed-attrs.rs:131:1
    |
 LL | #[must_not_suspend()]
    | ^^^^^^^^^^^^^^^^^^^^^
@@ -97,13 +71,13 @@ LL + #[must_not_suspend]
    |
 
 error: malformed `cfi_encoding` attribute input
-  --> $DIR/malformed-attrs.rs:134:1
+  --> $DIR/malformed-attrs.rs:133:1
    |
 LL | #[cfi_encoding]
    | ^^^^^^^^^^^^^^^ help: must be of the form: `#[cfi_encoding = "encoding"]`
 
 error: malformed `allow` attribute input
-  --> $DIR/malformed-attrs.rs:178:1
+  --> $DIR/malformed-attrs.rs:177:1
    |
 LL | #[allow]
    | ^^^^^^^^
@@ -119,7 +93,7 @@ LL | #[allow(lint1, lint2, lint3, reason = "...")]
    |        +++++++++++++++++++++++++++++++++++++
 
 error: malformed `expect` attribute input
-  --> $DIR/malformed-attrs.rs:180:1
+  --> $DIR/malformed-attrs.rs:179:1
    |
 LL | #[expect]
    | ^^^^^^^^^
@@ -135,7 +109,7 @@ LL | #[expect(lint1, lint2, lint3, reason = "...")]
    |         +++++++++++++++++++++++++++++++++++++
 
 error: malformed `warn` attribute input
-  --> $DIR/malformed-attrs.rs:182:1
+  --> $DIR/malformed-attrs.rs:181:1
    |
 LL | #[warn]
    | ^^^^^^^
@@ -151,7 +125,7 @@ LL | #[warn(lint1, lint2, lint3, reason = "...")]
    |       +++++++++++++++++++++++++++++++++++++
 
 error: malformed `deny` attribute input
-  --> $DIR/malformed-attrs.rs:184:1
+  --> $DIR/malformed-attrs.rs:183:1
    |
 LL | #[deny]
    | ^^^^^^^
@@ -167,7 +141,7 @@ LL | #[deny(lint1, lint2, lint3, reason = "...")]
    |       +++++++++++++++++++++++++++++++++++++
 
 error: malformed `forbid` attribute input
-  --> $DIR/malformed-attrs.rs:186:1
+  --> $DIR/malformed-attrs.rs:185:1
    |
 LL | #[forbid]
    | ^^^^^^^^^
@@ -183,7 +157,7 @@ LL | #[forbid(lint1, lint2, lint3, reason = "...")]
    |         +++++++++++++++++++++++++++++++++++++
 
 error: malformed `debugger_visualizer` attribute input
-  --> $DIR/malformed-attrs.rs:188:1
+  --> $DIR/malformed-attrs.rs:187:1
    |
 LL | #[debugger_visualizer]
    | ^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[debugger_visualizer(natvis_file = "...", gdb_script_file = "...")]`
@@ -191,13 +165,13 @@ LL | #[debugger_visualizer]
    = note: for more information, visit <https://doc.rust-lang.org/reference/attributes/debugger.html#the-debugger_visualizer-attribute>
 
 error: malformed `thread_local` attribute input
-  --> $DIR/malformed-attrs.rs:203:1
+  --> $DIR/malformed-attrs.rs:202:1
    |
 LL | #[thread_local()]
    | ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[thread_local]`
 
 error: malformed `no_link` attribute input
-  --> $DIR/malformed-attrs.rs:207:1
+  --> $DIR/malformed-attrs.rs:206:1
    |
 LL | #[no_link()]
    | ^^^^^^^^^^^^ help: must be of the form: `#[no_link]`
@@ -205,7 +179,7 @@ LL | #[no_link()]
    = note: for more information, visit <https://doc.rust-lang.org/reference/items/extern-crates.html#the-no_link-attribute>
 
 error: malformed `macro_export` attribute input
-  --> $DIR/malformed-attrs.rs:214:1
+  --> $DIR/malformed-attrs.rs:213:1
    |
 LL | #[macro_export = 18]
    | ^^^^^^^^^^^^^^^^^^^^
@@ -221,25 +195,25 @@ LL + #[macro_export]
    |
 
 error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type
-  --> $DIR/malformed-attrs.rs:99:1
+  --> $DIR/malformed-attrs.rs:98:1
    |
 LL | #[proc_macro = 18]
    | ^^^^^^^^^^^^^^^^^^
 
 error: the `#[proc_macro_attribute]` attribute is only usable with crates of the `proc-macro` crate type
-  --> $DIR/malformed-attrs.rs:116:1
+  --> $DIR/malformed-attrs.rs:115:1
    |
 LL | #[proc_macro_attribute = 19]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type
-  --> $DIR/malformed-attrs.rs:123:1
+  --> $DIR/malformed-attrs.rs:122:1
    |
 LL | #[proc_macro_derive]
    | ^^^^^^^^^^^^^^^^^^^^
 
 error[E0658]: allow_internal_unsafe side-steps the unsafe_code lint
-  --> $DIR/malformed-attrs.rs:216:1
+  --> $DIR/malformed-attrs.rs:215:1
    |
 LL | #[allow_internal_unsafe = 1]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -268,18 +242,8 @@ LL | #[doc]
    = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
    = note: for more information, visit <https://doc.rust-lang.org/rustdoc/write-documentation/the-doc-attribute.html>
 
-error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`
-  --> $DIR/malformed-attrs.rs:83:1
-   |
-LL | #[link]
-   | ^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
-   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
-
 error: invalid argument
-  --> $DIR/malformed-attrs.rs:188:1
+  --> $DIR/malformed-attrs.rs:187:1
    |
 LL | #[debugger_visualizer]
    | ^^^^^^^^^^^^^^^^^^^^^^
@@ -496,6 +460,12 @@ LL | #[used()]
    |
    = help: `#[used]` can only be applied to statics
 
+error[E0539]: malformed `crate_name` attribute input
+  --> $DIR/malformed-attrs.rs:74:1
+   |
+LL | #[crate_name]
+   | ^^^^^^^^^^^^^ help: must be of the form: `#[crate_name = "name"]`
+
 error[E0539]: malformed `target_feature` attribute input
   --> $DIR/malformed-attrs.rs:79:1
    |
@@ -514,8 +484,27 @@ LL | #[export_stable = 1]
    | |               didn't expect any arguments here
    | help: must be of the form: `#[export_stable]`
 
+error[E0539]: malformed `link` attribute input
+  --> $DIR/malformed-attrs.rs:83:1
+   |
+LL | #[link]
+   | ^^^^^^^ expected this to be a list
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL | #[link(name = "...")]
+   |       ++++++++++++++
+LL | #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |       +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+LL | #[link(name = "...", kind = "dylib|static|...")]
+   |       +++++++++++++++++++++++++++++++++++++++++
+LL | #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |       ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+   = and 1 other candidate
+
 error[E0539]: malformed `link_name` attribute input
-  --> $DIR/malformed-attrs.rs:86:1
+  --> $DIR/malformed-attrs.rs:85:1
    |
 LL | #[link_name]
    | ^^^^^^^^^^^^ help: must be of the form: `#[link_name = "name"]`
@@ -523,7 +512,7 @@ LL | #[link_name]
    = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_name-attribute>
 
 error[E0539]: malformed `link_section` attribute input
-  --> $DIR/malformed-attrs.rs:88:1
+  --> $DIR/malformed-attrs.rs:87:1
    |
 LL | #[link_section]
    | ^^^^^^^^^^^^^^^ help: must be of the form: `#[link_section = "name"]`
@@ -531,7 +520,7 @@ LL | #[link_section]
    = note: for more information, visit <https://doc.rust-lang.org/reference/abi.html#the-link_section-attribute>
 
 error[E0539]: malformed `coverage` attribute input
-  --> $DIR/malformed-attrs.rs:90:1
+  --> $DIR/malformed-attrs.rs:89:1
    |
 LL | #[coverage]
    | ^^^^^^^^^^^ this attribute is only valid with either `on` or `off` as an argument
@@ -543,8 +532,26 @@ LL | #[coverage(off)]
 LL | #[coverage(on)]
    |           ++++
 
+error[E0539]: malformed `sanitize` attribute input
+  --> $DIR/malformed-attrs.rs:91:1
+   |
+LL | #[sanitize]
+   | ^^^^^^^^^^^ expected this to be a list
+   |
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL | #[sanitize(address = "on|off")]
+   |           ++++++++++++++++++++
+LL | #[sanitize(cfi = "on|off")]
+   |           ++++++++++++++++
+LL | #[sanitize(hwaddress = "on|off")]
+   |           ++++++++++++++++++++++
+LL | #[sanitize(kcfi = "on|off")]
+   |           +++++++++++++++++
+   = and 5 other candidates
+
 error[E0565]: malformed `no_implicit_prelude` attribute input
-  --> $DIR/malformed-attrs.rs:97:1
+  --> $DIR/malformed-attrs.rs:96:1
    |
 LL | #[no_implicit_prelude = 23]
    | ^^^^^^^^^^^^^^^^^^^^^^----^
@@ -553,7 +560,7 @@ LL | #[no_implicit_prelude = 23]
    | help: must be of the form: `#[no_implicit_prelude]`
 
 error[E0565]: malformed `proc_macro` attribute input
-  --> $DIR/malformed-attrs.rs:99:1
+  --> $DIR/malformed-attrs.rs:98:1
    |
 LL | #[proc_macro = 18]
    | ^^^^^^^^^^^^^----^
@@ -562,7 +569,7 @@ LL | #[proc_macro = 18]
    | help: must be of the form: `#[proc_macro]`
 
 error[E0565]: malformed `coroutine` attribute input
-  --> $DIR/malformed-attrs.rs:111:5
+  --> $DIR/malformed-attrs.rs:110:5
    |
 LL |     #[coroutine = 63] || {}
    |     ^^^^^^^^^^^^----^
@@ -571,7 +578,7 @@ LL |     #[coroutine = 63] || {}
    |     help: must be of the form: `#[coroutine]`
 
 error[E0565]: malformed `proc_macro_attribute` attribute input
-  --> $DIR/malformed-attrs.rs:116:1
+  --> $DIR/malformed-attrs.rs:115:1
    |
 LL | #[proc_macro_attribute = 19]
    | ^^^^^^^^^^^^^^^^^^^^^^^----^
@@ -580,7 +587,7 @@ LL | #[proc_macro_attribute = 19]
    | help: must be of the form: `#[proc_macro_attribute]`
 
 error[E0539]: malformed `must_use` attribute input
-  --> $DIR/malformed-attrs.rs:119:1
+  --> $DIR/malformed-attrs.rs:118:1
    |
 LL | #[must_use = 1]
    | ^^^^^^^^^^^^^-^
@@ -598,7 +605,7 @@ LL + #[must_use]
    |
 
 error[E0539]: malformed `proc_macro_derive` attribute input
-  --> $DIR/malformed-attrs.rs:123:1
+  --> $DIR/malformed-attrs.rs:122:1
    |
 LL | #[proc_macro_derive]
    | ^^^^^^^^^^^^^^^^^^^^ expected this to be a list
@@ -612,7 +619,7 @@ LL | #[proc_macro_derive(TraitName, attributes(name1, name2, ...))]
    |                    ++++++++++++++++++++++++++++++++++++++++++
 
 error[E0539]: malformed `rustc_layout_scalar_valid_range_start` attribute input
-  --> $DIR/malformed-attrs.rs:128:1
+  --> $DIR/malformed-attrs.rs:127:1
    |
 LL | #[rustc_layout_scalar_valid_range_start]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -621,7 +628,7 @@ LL | #[rustc_layout_scalar_valid_range_start]
    | help: must be of the form: `#[rustc_layout_scalar_valid_range_start(start)]`
 
 error[E0539]: malformed `rustc_layout_scalar_valid_range_end` attribute input
-  --> $DIR/malformed-attrs.rs:130:1
+  --> $DIR/malformed-attrs.rs:129:1
    |
 LL | #[rustc_layout_scalar_valid_range_end]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -630,7 +637,7 @@ LL | #[rustc_layout_scalar_valid_range_end]
    | help: must be of the form: `#[rustc_layout_scalar_valid_range_end(end)]`
 
 error[E0565]: malformed `marker` attribute input
-  --> $DIR/malformed-attrs.rs:155:1
+  --> $DIR/malformed-attrs.rs:154:1
    |
 LL | #[marker = 3]
    | ^^^^^^^^^---^
@@ -639,7 +646,7 @@ LL | #[marker = 3]
    | help: must be of the form: `#[marker]`
 
 error[E0565]: malformed `fundamental` attribute input
-  --> $DIR/malformed-attrs.rs:157:1
+  --> $DIR/malformed-attrs.rs:156:1
    |
 LL | #[fundamental()]
    | ^^^^^^^^^^^^^--^
@@ -648,7 +655,7 @@ LL | #[fundamental()]
    | help: must be of the form: `#[fundamental]`
 
 error[E0565]: malformed `ffi_pure` attribute input
-  --> $DIR/malformed-attrs.rs:165:5
+  --> $DIR/malformed-attrs.rs:164:5
    |
 LL |     #[unsafe(ffi_pure = 1)]
    |     ^^^^^^^^^^^^^^^^^^---^^
@@ -657,7 +664,7 @@ LL |     #[unsafe(ffi_pure = 1)]
    |     help: must be of the form: `#[ffi_pure]`
 
 error[E0539]: malformed `link_ordinal` attribute input
-  --> $DIR/malformed-attrs.rs:167:5
+  --> $DIR/malformed-attrs.rs:166:5
    |
 LL |     #[link_ordinal]
    |     ^^^^^^^^^^^^^^^
@@ -668,7 +675,7 @@ LL |     #[link_ordinal]
    = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link_ordinal-attribute>
 
 error[E0565]: malformed `ffi_const` attribute input
-  --> $DIR/malformed-attrs.rs:171:5
+  --> $DIR/malformed-attrs.rs:170:5
    |
 LL |     #[unsafe(ffi_const = 1)]
    |     ^^^^^^^^^^^^^^^^^^^---^^
@@ -677,7 +684,7 @@ LL |     #[unsafe(ffi_const = 1)]
    |     help: must be of the form: `#[ffi_const]`
 
 error[E0539]: malformed `linkage` attribute input
-  --> $DIR/malformed-attrs.rs:173:5
+  --> $DIR/malformed-attrs.rs:172:5
    |
 LL |     #[linkage]
    |     ^^^^^^^^^^ expected this to be of the form `linkage = "..."`
@@ -695,7 +702,7 @@ LL |     #[linkage = "external"]
    = and 5 other candidates
 
 error[E0565]: malformed `automatically_derived` attribute input
-  --> $DIR/malformed-attrs.rs:191:1
+  --> $DIR/malformed-attrs.rs:190:1
    |
 LL | #[automatically_derived = 18]
    | ^^^^^^^^^^^^^^^^^^^^^^^^----^
@@ -704,7 +711,7 @@ LL | #[automatically_derived = 18]
    | help: must be of the form: `#[automatically_derived]`
 
 error[E0565]: malformed `non_exhaustive` attribute input
-  --> $DIR/malformed-attrs.rs:197:1
+  --> $DIR/malformed-attrs.rs:196:1
    |
 LL | #[non_exhaustive = 1]
    | ^^^^^^^^^^^^^^^^^---^
@@ -713,13 +720,13 @@ LL | #[non_exhaustive = 1]
    | help: must be of the form: `#[non_exhaustive]`
 
 error: valid forms for the attribute are `#[macro_use(name1, name2, ...)]` and `#[macro_use]`
-  --> $DIR/malformed-attrs.rs:209:1
+  --> $DIR/malformed-attrs.rs:208:1
    |
 LL | #[macro_use = 1]
    | ^^^^^^^^^^^^^^^^
 
 error[E0565]: malformed `allow_internal_unsafe` attribute input
-  --> $DIR/malformed-attrs.rs:216:1
+  --> $DIR/malformed-attrs.rs:215:1
    |
 LL | #[allow_internal_unsafe = 1]
    | ^^^^^^^^^^^^^^^^^^^^^^^^---^
@@ -728,7 +735,7 @@ LL | #[allow_internal_unsafe = 1]
    | help: must be of the form: `#[allow_internal_unsafe]`
 
 error[E0565]: malformed `type_const` attribute input
-  --> $DIR/malformed-attrs.rs:143:5
+  --> $DIR/malformed-attrs.rs:142:5
    |
 LL |     #[type_const = 1]
    |     ^^^^^^^^^^^^^---^
@@ -761,7 +768,7 @@ LL | #[repr]
    | ^^^^^^^
 
 warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
-  --> $DIR/malformed-attrs.rs:149:1
+  --> $DIR/malformed-attrs.rs:148:1
    |
 LL | #[diagnostic::do_not_recommend()]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -769,7 +776,7 @@ LL | #[diagnostic::do_not_recommend()]
    = note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
 
 warning: missing options for `on_unimplemented` attribute
-  --> $DIR/malformed-attrs.rs:138:1
+  --> $DIR/malformed-attrs.rs:137:1
    |
 LL | #[diagnostic::on_unimplemented]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -777,7 +784,7 @@ LL | #[diagnostic::on_unimplemented]
    = help: at least one of the `message`, `note` and `label` options are expected
 
 warning: malformed `on_unimplemented` attribute
-  --> $DIR/malformed-attrs.rs:140:1
+  --> $DIR/malformed-attrs.rs:139:1
    |
 LL | #[diagnostic::on_unimplemented = 1]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here
@@ -794,7 +801,7 @@ LL | #[inline = 5]
    = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
 
 error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]`
-  --> $DIR/malformed-attrs.rs:94:1
+  --> $DIR/malformed-attrs.rs:93:1
    |
 LL | #[ignore()]
    | ^^^^^^^^^^^
@@ -803,7 +810,7 @@ LL | #[ignore()]
    = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
 
 error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]`
-  --> $DIR/malformed-attrs.rs:223:1
+  --> $DIR/malformed-attrs.rs:222:1
    |
 LL | #[ignore = 1]
    | ^^^^^^^^^^^^^
@@ -812,7 +819,7 @@ LL | #[ignore = 1]
    = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
 
 error[E0308]: mismatched types
-  --> $DIR/malformed-attrs.rs:111:23
+  --> $DIR/malformed-attrs.rs:110:23
    |
 LL | fn test() {
    |          - help: a return type might be missing here: `-> _`
@@ -820,7 +827,7 @@ LL |     #[coroutine = 63] || {}
    |                       ^^^^^ expected `()`, found coroutine
    |
    = note: expected unit type `()`
-              found coroutine `{coroutine@$DIR/malformed-attrs.rs:111:23: 111:25}`
+              found coroutine `{coroutine@$DIR/malformed-attrs.rs:110:23: 110:25}`
 
 error: aborting due to 77 previous errors; 3 warnings emitted
 
@@ -851,18 +858,6 @@ LL | #[doc]
    = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default
 
 Future breakage diagnostic:
-error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`
-  --> $DIR/malformed-attrs.rs:83:1
-   |
-LL | #[link]
-   | ^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
-   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
-   = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default
-
-Future breakage diagnostic:
 error: valid forms for the attribute are `#[inline(always)]`, `#[inline(never)]`, and `#[inline]`
   --> $DIR/malformed-attrs.rs:52:1
    |
@@ -875,7 +870,7 @@ LL | #[inline = 5]
 
 Future breakage diagnostic:
 error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]`
-  --> $DIR/malformed-attrs.rs:94:1
+  --> $DIR/malformed-attrs.rs:93:1
    |
 LL | #[ignore()]
    | ^^^^^^^^^^^
@@ -886,7 +881,7 @@ LL | #[ignore()]
 
 Future breakage diagnostic:
 error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]`
-  --> $DIR/malformed-attrs.rs:223:1
+  --> $DIR/malformed-attrs.rs:222:1
    |
 LL | #[ignore = 1]
    | ^^^^^^^^^^^^^
diff --git a/tests/ui/attributes/malformed-never-type-options.rs b/tests/ui/attributes/malformed-never-type-options.rs
new file mode 100644
index 00000000000..0c384be0e22
--- /dev/null
+++ b/tests/ui/attributes/malformed-never-type-options.rs
@@ -0,0 +1,8 @@
+//! Regression test for #124352
+//! The `rustc_*` attribute is malformed, but ICEing without a `feature(rustc_attrs)` is still bad.
+
+#![rustc_never_type_options(: Unsize<U> = "hi")]
+//~^ ERROR expected unsuffixed literal, found `:`
+//~| ERROR use of an internal attribute
+
+fn main() {}
diff --git a/tests/ui/attributes/malformed-never-type-options.stderr b/tests/ui/attributes/malformed-never-type-options.stderr
new file mode 100644
index 00000000000..0d2ff4881f2
--- /dev/null
+++ b/tests/ui/attributes/malformed-never-type-options.stderr
@@ -0,0 +1,19 @@
+error: expected unsuffixed literal, found `:`
+  --> $DIR/malformed-never-type-options.rs:4:29
+   |
+LL | #![rustc_never_type_options(: Unsize<U> = "hi")]
+   |                             ^
+
+error[E0658]: use of an internal attribute
+  --> $DIR/malformed-never-type-options.rs:4:1
+   |
+LL | #![rustc_never_type_options(: Unsize<U> = "hi")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable
+   = note: the `#[rustc_never_type_options]` attribute is an internal implementation detail that will never be stable
+   = note: `rustc_never_type_options` is used to experiment with never type fallback and work on never type stabilization
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/binop/binops.rs b/tests/ui/binop/binops.rs
index 7142190a45b..702e9a61345 100644
--- a/tests/ui/binop/binops.rs
+++ b/tests/ui/binop/binops.rs
@@ -35,6 +35,7 @@ fn test_bool() {
     assert_eq!(true ^ true, false);
 }
 
+#[allow(integer_to_ptr_transmutes)]
 fn test_ptr() {
     unsafe {
         let p1: *const u8 = ::std::mem::transmute(0_usize);
diff --git a/tests/ui/c-variadic/issue-86053-1.stderr b/tests/ui/c-variadic/issue-86053-1.stderr
index dc323f9a234..3bf8b7ba5d8 100644
--- a/tests/ui/c-variadic/issue-86053-1.stderr
+++ b/tests/ui/c-variadic/issue-86053-1.stderr
@@ -57,10 +57,10 @@ error[E0412]: cannot find type `F` in this scope
    |
 LL |     self , ... ,   self ,   self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
    |                                                ^
+   |
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
    = note: similarly named trait `Fn` defined here
-   |
 help: a trait with a similar name exists
    |
 LL |     self , ... ,   self ,   self , ... ) where Fn : FnOnce ( & 'a & 'b usize ) {
diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr
index f6448147392..258f2132466 100644
--- a/tests/ui/check-cfg/target_feature.stderr
+++ b/tests/ui/check-cfg/target_feature.stderr
@@ -243,6 +243,7 @@ LL |     cfg!(target_feature = "_UNEXPECTED_VALUE");
 `relax`
 `relaxed-simd`
 `rtm`
+`rva23u64`
 `sb`
 `scq`
 `sha`
@@ -304,6 +305,7 @@ LL |     cfg!(target_feature = "_UNEXPECTED_VALUE");
 `ssve-fp8dot2`
 `ssve-fp8dot4`
 `ssve-fp8fma`
+`supm`
 `sve`
 `sve-b16b16`
 `sve2`
diff --git a/tests/ui/closures/issue-78720.stderr b/tests/ui/closures/issue-78720.stderr
index 3e95fab441a..987625d22c9 100644
--- a/tests/ui/closures/issue-78720.stderr
+++ b/tests/ui/closures/issue-78720.stderr
@@ -9,10 +9,10 @@ error[E0412]: cannot find type `F` in this scope
    |
 LL |     _func: F,
    |            ^
+   |
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
    = note: similarly named trait `Fn` defined here
-   |
 help: a trait with a similar name exists
    |
 LL |     _func: Fn,
diff --git a/tests/ui/closures/issue-90871.stderr b/tests/ui/closures/issue-90871.stderr
index ef1cb213f73..12020226680 100644
--- a/tests/ui/closures/issue-90871.stderr
+++ b/tests/ui/closures/issue-90871.stderr
@@ -3,6 +3,7 @@ error[E0412]: cannot find type `n` in this scope
    |
 LL |     type_ascribe!(2, n([u8; || 1]))
    |                      ^ help: a trait with a similar name exists: `Fn`
+   |
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
    = note: similarly named trait `Fn` defined here
diff --git a/tests/ui/codegen/indirect-nocapture.rs b/tests/ui/codegen/indirect-nocapture.rs
new file mode 100644
index 00000000000..78024a94c0d
--- /dev/null
+++ b/tests/ui/codegen/indirect-nocapture.rs
@@ -0,0 +1,15 @@
+// Regression test for issue #137668 where an indirect argument have been marked as nocapture
+// despite the fact that callee did in fact capture the address.
+//
+//@ run-pass
+//@ compile-flags: -Copt-level=2
+
+#[inline(never)]
+pub fn f(a: [u32; 64], b: [u32; 64]) -> bool {
+    &a as *const _ as usize != &b as *const _ as usize
+}
+
+fn main() {
+    static S: [u32; 64] = [0; 64];
+    assert!(f(S, S));
+}
diff --git a/tests/ui/coercion/fake-sized-ptr-cast.rs b/tests/ui/coercion/fake-sized-ptr-cast.rs
new file mode 100644
index 00000000000..4b6bf0eb516
--- /dev/null
+++ b/tests/ui/coercion/fake-sized-ptr-cast.rs
@@ -0,0 +1,16 @@
+// Make sure borrowck doesn't ICE because it thinks a pointer cast is a metadata-preserving
+// wide-to-wide ptr cast when it's actually (falsely) a wide-to-thin ptr cast due to an
+// impossible dyn sized bound.
+
+//@ check-pass
+
+trait Trait<T> {}
+
+fn func<'a>(x: *const (dyn Trait<()> + 'a))
+where
+    dyn Trait<u8> + 'a: Sized,
+{
+    let _x: *const dyn Trait<u8> = x as _;
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr
index 4c8a5e46751..c05584ef909 100644
--- a/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr
+++ b/tests/ui/const-generics/adt_const_params/const_param_ty_bad.stderr
@@ -32,8 +32,9 @@ LL | fn check(_: impl std::marker::UnsizedConstParamTy) {}
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `check`
 help: use parentheses to call this closure
    |
-LL |     check(|| {}());
-   |                ++
+LL -     check(|| {});
+LL +     check((|| {})());
+   |
 
 error[E0277]: `fn()` can't be used as a const parameter type
   --> $DIR/const_param_ty_bad.rs:9:11
diff --git a/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr
index b9db7461699..c9c8115660f 100644
--- a/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/expected-type-of-closure-body-to-be-a-closure-or-coroutine-ice-113776.stderr
@@ -3,10 +3,10 @@ error[E0412]: cannot find type `F` in this scope
    |
 LL |          let f: F = async { 1 };
    |                 ^
+   |
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
    = note: similarly named trait `Fn` defined here
-   |
 help: a trait with a similar name exists
    |
 LL |          let f: Fn = async { 1 };
diff --git a/tests/ui/const-generics/type-dependent/issue-71348.full.stderr b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr
index 32fa46b92b3..299ae680093 100644
--- a/tests/ui/const-generics/type-dependent/issue-71348.full.stderr
+++ b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr
@@ -1,8 +1,8 @@
 warning: hiding a lifetime that's named elsewhere is confusing
-  --> $DIR/issue-71348.rs:18:40
+  --> $DIR/issue-71348.rs:18:56
    |
 LL |     fn ask<'a, const N: &'static str>(&'a self) -> &'a <Self as Get<N>>::Target
-   |                                        ^^           -- ------------------------ the same lifetime is hidden here
+   |                                        --           -- ^^^^^^^^^^^^^^^^^^^^^^^^ the same lifetime is hidden here
    |                                        |            |
    |                                        |            the same lifetime is named here
    |                                        the lifetime is named here
diff --git a/tests/ui/consts/issue-89088.stderr b/tests/ui/consts/issue-89088.stderr
index 56025e0d9b2..5008a2eada8 100644
--- a/tests/ui/consts/issue-89088.stderr
+++ b/tests/ui/consts/issue-89088.stderr
@@ -6,6 +6,7 @@ LL | const FOO: &A = &A::Field(Cow::Borrowed("foo"));
 ...
 LL |         FOO => todo!(),
    |         ^^^ constant of non-structural type
+   |
   --> $SRC_DIR/alloc/src/borrow.rs:LL:COL
    |
    = note: `Cow<'_, str>` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
diff --git a/tests/ui/consts/ptr_comparisons.rs b/tests/ui/consts/ptr_comparisons.rs
index e142ab3a754..b8d809475cf 100644
--- a/tests/ui/consts/ptr_comparisons.rs
+++ b/tests/ui/consts/ptr_comparisons.rs
@@ -1,43 +1,205 @@
 //@ compile-flags: --crate-type=lib
 //@ check-pass
+//@ edition: 2024
+#![feature(const_raw_ptr_comparison)]
+#![feature(fn_align)]
+// Generally:
+// For any `Some` return, `None` would also be valid, unless otherwise noted.
+// For any `None` return, only `None` is valid, unless otherwise noted.
 
-#![feature(
-    core_intrinsics,
-    const_raw_ptr_comparison,
-)]
+macro_rules! do_test {
+    ($a:expr, $b:expr, $expected:pat) => {
+        const _: () = {
+            let a: *const _ = $a;
+            let b: *const _ = $b;
+            assert!(matches!(<*const u8>::guaranteed_eq(a.cast(), b.cast()), $expected));
+        };
+    };
+}
 
-const FOO: &usize = &42;
+#[repr(align(2))]
+struct T(#[allow(unused)] u16);
 
-macro_rules! check {
-    (eq, $a:expr, $b:expr) => {
-        pub const _: () =
-            assert!(std::intrinsics::ptr_guaranteed_cmp($a as *const u8, $b as *const u8) == 1);
-    };
-    (ne, $a:expr, $b:expr) => {
-        pub const _: () =
-            assert!(std::intrinsics::ptr_guaranteed_cmp($a as *const u8, $b as *const u8) == 0);
+#[repr(align(2))]
+struct AlignedZst;
+
+static A: T = T(42);
+static B: T = T(42);
+static mut MUT_STATIC: T = T(42);
+static ZST: () = ();
+static ALIGNED_ZST: AlignedZst = AlignedZst;
+static LARGE_WORD_ALIGNED: [usize; 2] = [0, 1];
+static mut MUT_LARGE_WORD_ALIGNED: [usize; 2] = [0, 1];
+
+const FN_PTR: *const () = {
+    fn foo() {}
+    unsafe { std::mem::transmute(foo as fn()) }
+};
+
+const ALIGNED_FN_PTR: *const () = {
+    #[rustc_align(2)]
+    fn aligned_foo() {}
+    unsafe { std::mem::transmute(aligned_foo as fn()) }
+};
+
+trait Trait {
+    #[allow(unused)]
+    fn method(&self) -> u8;
+}
+impl Trait for u32 {
+    fn method(&self) -> u8 { 1 }
+}
+impl Trait for i32 {
+    fn method(&self) -> u8 { 2 }
+}
+
+const VTABLE_PTR_1: *const () = {
+    let [_data, vtable] = unsafe {
+        std::mem::transmute::<&dyn Trait, [*const (); 2]>(&42_u32 as &dyn Trait)
     };
-    (!, $a:expr, $b:expr) => {
-        pub const _: () =
-            assert!(std::intrinsics::ptr_guaranteed_cmp($a as *const u8, $b as *const u8) == 2);
+    vtable
+};
+const VTABLE_PTR_2: *const () = {
+    let [_data, vtable] = unsafe {
+        std::mem::transmute::<&dyn Trait, [*const (); 2]>(&42_i32 as &dyn Trait)
     };
-}
+    vtable
+};
 
-check!(eq, 0, 0);
-check!(ne, 0, 1);
-check!(ne, FOO as *const _, 0);
-check!(ne, unsafe { (FOO as *const usize).offset(1) }, 0);
-check!(ne, unsafe { (FOO as *const usize as *const u8).offset(3) }, 0);
+// Cannot be `None`: `is_null` is stable with strong guarantees about integer-valued pointers.
+do_test!(0 as *const u8, 0 as *const u8, Some(true));
+do_test!(0 as *const u8, 1 as *const u8, Some(false));
 
-// We want pointers to be equal to themselves, but aren't checking this yet because
-// there are some open questions (e.g. whether function pointers to the same function
-// compare equal: they don't necessarily do at runtime).
-check!(!, FOO as *const _, FOO as *const _);
+// Integer-valued pointers can always be compared.
+do_test!(1 as *const u8, 1 as *const u8, Some(true));
+do_test!(1 as *const u8, 2 as *const u8, Some(false));
+
+// Cannot be `None`: `static`s' addresses, references, (and within and one-past-the-end of those),
+// and `fn` pointers cannot be null, and `is_null` is stable with strong guarantees, and
+// `is_null` is implemented using `guaranteed_cmp`.
+do_test!(&A, 0 as *const u8, Some(false));
+do_test!((&raw const A).cast::<u8>().wrapping_add(1), 0 as *const u8, Some(false));
+do_test!((&raw const A).wrapping_add(1), 0 as *const u8, Some(false));
+do_test!(&ZST, 0 as *const u8, Some(false));
+do_test!(&(), 0 as *const u8, Some(false));
+do_test!(const { &() }, 0 as *const u8, Some(false));
+do_test!(FN_PTR, 0 as *const u8, Some(false));
+
+// This pointer is out-of-bounds, but still cannot be equal to 0 because of alignment.
+do_test!((&raw const A).cast::<u8>().wrapping_add(size_of::<T>() + 1), 0 as *const u8, Some(false));
 
 // aside from 0, these pointers might end up pretty much anywhere.
-check!(!, FOO as *const _, 1); // this one could be `ne` by taking into account alignment
-check!(!, FOO as *const _, 1024);
+do_test!(&A, align_of::<T>() as *const u8, None);
+do_test!((&raw const A).wrapping_byte_add(1), (align_of::<T>() + 1) as *const u8, None);
+
+// except that they must still be aligned
+do_test!(&A, 1 as *const u8, Some(false));
+do_test!((&raw const A).wrapping_byte_add(1), align_of::<T>() as *const u8, Some(false));
+
+// If `ptr.wrapping_sub(int)` cannot be null (because it is in-bounds or one-past-the-end of
+// `ptr`'s allocation, or because it is misaligned from `ptr`'s allocation), then we know that
+// `ptr != int`, even if `ptr` itself is out-of-bounds or one-past-the-end of its allocation.
+do_test!((&raw const A).wrapping_byte_add(1), 1 as *const u8, Some(false));
+do_test!((&raw const A).wrapping_byte_add(2), 2 as *const u8, Some(false));
+do_test!((&raw const A).wrapping_byte_add(3), 1 as *const u8, Some(false));
+do_test!((&raw const ZST).wrapping_byte_add(1), 1 as *const u8, Some(false));
+do_test!(VTABLE_PTR_1.wrapping_byte_add(1), 1 as *const u8, Some(false));
+do_test!(FN_PTR.wrapping_byte_add(1), 1 as *const u8, Some(false));
+do_test!(&A, size_of::<T>().wrapping_neg() as *const u8, Some(false));
+do_test!(&LARGE_WORD_ALIGNED, size_of::<usize>().wrapping_neg() as *const u8, Some(false));
+// (`ptr - int != 0` due to misalignment)
+do_test!((&raw const A).wrapping_byte_add(2), 1 as *const u8, Some(false));
+do_test!((&raw const ALIGNED_ZST).wrapping_byte_add(2), 1 as *const u8, Some(false));
 
 // When pointers go out-of-bounds, they *might* become null, so these comparions cannot work.
-check!(!, unsafe { (FOO as *const usize).wrapping_add(2) }, 0);
-check!(!, unsafe { (FOO as *const usize).wrapping_sub(1) }, 0);
+do_test!((&raw const A).wrapping_add(2), 0 as *const u8, None);
+do_test!((&raw const A).wrapping_sub(1), 0 as *const u8, None);
+
+// Statics cannot be duplicated
+do_test!(&A, &A, Some(true));
+
+// Two non-ZST statics cannot have the same address
+do_test!(&A, &B, Some(false));
+do_test!(&A, &raw const MUT_STATIC, Some(false));
+
+// One-past-the-end of one static can be equal to the address of another static.
+do_test!(&A, (&raw const B).wrapping_add(1), None);
+
+// Cannot know if ZST static is at the same address with anything non-null (if alignment allows).
+do_test!(&A, &ZST, None);
+do_test!(&A, &ALIGNED_ZST, None);
+
+// Unclear if ZST statics can be placed "in the middle of" non-ZST statics.
+// For now, we conservatively say they could, and return None here.
+do_test!(&ZST, (&raw const A).wrapping_byte_add(1), None);
+
+// As per https://doc.rust-lang.org/nightly/reference/items/static-items.html#r-items.static.storage-disjointness
+// immutable statics are allowed to overlap with const items and promoteds.
+do_test!(&A, &T(42), None);
+do_test!(&A, const { &T(42) }, None);
+do_test!(&A, { const X: T = T(42); &X }, None);
+
+// These could return Some(false), since only immutable statics can overlap with const items
+// and promoteds.
+do_test!(&raw const MUT_STATIC, &T(42), None);
+do_test!(&raw const MUT_STATIC, const { &T(42) }, None);
+do_test!(&raw const MUT_STATIC, { const X: T = T(42); &X }, None);
+
+// An odd offset from a 2-aligned allocation can never be equal to an even offset from a
+// 2-aligned allocation, even if the offsets are out-of-bounds.
+do_test!(&A, (&raw const B).wrapping_byte_add(1), Some(false));
+do_test!(&A, (&raw const B).wrapping_byte_add(5), Some(false));
+do_test!(&A, (&raw const ALIGNED_ZST).wrapping_byte_add(1), Some(false));
+do_test!(&ALIGNED_ZST, (&raw const A).wrapping_byte_add(1), Some(false));
+do_test!(&A, (&T(42) as *const T).wrapping_byte_add(1), Some(false));
+do_test!(&A, (const { &T(42) } as *const T).wrapping_byte_add(1), Some(false));
+do_test!(&A, ({ const X: T = T(42); &X } as *const T).wrapping_byte_add(1), Some(false));
+
+// We could return `Some(false)` for these, as pointers to different statics can never be equal if
+// that would require the statics to overlap, even if the pointers themselves are offset out of
+// bounds or one-past-the-end. We currently only check strictly in-bounds pointers when comparing
+// pointers to different statics, however.
+do_test!((&raw const A).wrapping_add(1), (&raw const B).wrapping_add(1), None);
+do_test!(
+    (&raw const LARGE_WORD_ALIGNED).cast::<usize>().wrapping_add(2),
+    (&raw const MUT_LARGE_WORD_ALIGNED).cast::<usize>().wrapping_add(1),
+    None
+);
+
+// Pointers into the same static are equal if and only if their offset is the same,
+// even if either is out-of-bounds.
+do_test!(&A, &A, Some(true));
+do_test!(&A, &A.0, Some(true));
+do_test!(&A, (&raw const A).wrapping_byte_add(1), Some(false));
+do_test!(&A, (&raw const A).wrapping_byte_add(2), Some(false));
+do_test!(&A, (&raw const A).wrapping_byte_add(51), Some(false));
+do_test!((&raw const A).wrapping_byte_add(51), (&raw const A).wrapping_byte_add(51), Some(true));
+
+// Pointers to the same fn may be unequal, since `fn`s can be duplicated.
+do_test!(FN_PTR, FN_PTR, None);
+do_test!(ALIGNED_FN_PTR, ALIGNED_FN_PTR, None);
+
+// Pointers to different fns may be equal, since `fn`s can be deduplicated.
+do_test!(FN_PTR, ALIGNED_FN_PTR, None);
+
+// Pointers to the same vtable may be unequal, since vtables can be duplicated.
+do_test!(VTABLE_PTR_1, VTABLE_PTR_1, None);
+
+// Pointers to different vtables may be equal, since vtables can be deduplicated.
+do_test!(VTABLE_PTR_1, VTABLE_PTR_2, None);
+
+// Function pointers to aligned function allocations are not necessarily actually aligned,
+// due to platform-specific semantics.
+// See https://github.com/rust-lang/rust/issues/144661
+// FIXME: This could return `Some` on platforms where function pointers' addresses actually
+// correspond to function addresses including alignment, or on platforms where all functions
+// are aligned to some amount (e.g. ARM where a32 function pointers are at least 4-aligned,
+// and t32 function pointers are 2-aligned-offset-by-1).
+do_test!(ALIGNED_FN_PTR, ALIGNED_FN_PTR.wrapping_byte_offset(1), None);
+
+// Conservatively say we don't know.
+do_test!(FN_PTR, VTABLE_PTR_1, None);
+do_test!((&raw const LARGE_WORD_ALIGNED).cast::<usize>().wrapping_add(1), VTABLE_PTR_1, None);
+do_test!((&raw const MUT_LARGE_WORD_ALIGNED).cast::<usize>().wrapping_add(1), VTABLE_PTR_1, None);
+do_test!((&raw const LARGE_WORD_ALIGNED).cast::<usize>().wrapping_add(1), FN_PTR, None);
+do_test!((&raw const MUT_LARGE_WORD_ALIGNED).cast::<usize>().wrapping_add(1), FN_PTR, None);
diff --git a/tests/ui/derives/deriving-meta-unknown-trait.stderr b/tests/ui/derives/deriving-meta-unknown-trait.stderr
index 28753b8f9f2..7ee90ae9eb0 100644
--- a/tests/ui/derives/deriving-meta-unknown-trait.stderr
+++ b/tests/ui/derives/deriving-meta-unknown-trait.stderr
@@ -3,6 +3,7 @@ error: cannot find derive macro `Eqr` in this scope
    |
 LL | #[derive(Eqr)]
    |          ^^^ help: a derive macro with a similar name exists: `Eq`
+   |
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
    = note: similarly named derive macro `Eq` defined here
@@ -12,6 +13,7 @@ error: cannot find derive macro `Eqr` in this scope
    |
 LL | #[derive(Eqr)]
    |          ^^^ help: a derive macro with a similar name exists: `Eq`
+   |
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
    = note: similarly named derive macro `Eq` defined here
diff --git a/tests/ui/diagnostic-flags/colored-session-opt-error.rs b/tests/ui/diagnostic-flags/colored-session-opt-error.rs
index e850345fbf1..1c411048385 100644
--- a/tests/ui/diagnostic-flags/colored-session-opt-error.rs
+++ b/tests/ui/diagnostic-flags/colored-session-opt-error.rs
@@ -1,4 +1,8 @@
 //@ check-pass
 //@ ignore-windows
 //@ compile-flags: -Cremark=foo --error-format=human --color=always
+
+// FIXME(#61117): Respect debuginfo-level-tests, do not force debuginfo-level=0
+//@ compile-flags: -Cdebuginfo=0
+
 fn main() {}
diff --git a/tests/ui/did_you_mean/println-typo.stderr b/tests/ui/did_you_mean/println-typo.stderr
index a1e0b1f1ba4..7dd6fbba620 100644
--- a/tests/ui/did_you_mean/println-typo.stderr
+++ b/tests/ui/did_you_mean/println-typo.stderr
@@ -3,6 +3,7 @@ error: cannot find macro `prinltn` in this scope
    |
 LL |     prinltn!();
    |     ^^^^^^^ help: a macro with a similar name exists: `println`
+   |
   --> $SRC_DIR/std/src/macros.rs:LL:COL
    |
    = note: similarly named macro `println` defined here
diff --git a/tests/ui/error-codes/E0458.rs b/tests/ui/error-codes/E0458.rs
index 35e7e84d479..0e35ba43bfb 100644
--- a/tests/ui/error-codes/E0458.rs
+++ b/tests/ui/error-codes/E0458.rs
@@ -1,4 +1,4 @@
-#[link(kind = "wonderful_unicorn")] extern "C" {} //~ ERROR E0458
+#[link(kind = "wonderful_unicorn")] extern "C" {} //~ ERROR malformed `link` attribute input [E0539]
                                                   //~| ERROR E0459
 
 fn main() {
diff --git a/tests/ui/error-codes/E0458.stderr b/tests/ui/error-codes/E0458.stderr
index c13ae4e7862..524765ea12a 100644
--- a/tests/ui/error-codes/E0458.stderr
+++ b/tests/ui/error-codes/E0458.stderr
@@ -1,8 +1,27 @@
-error[E0458]: unknown link kind `wonderful_unicorn`, expected one of: static, dylib, framework, raw-dylib, link-arg
-  --> $DIR/E0458.rs:1:15
+error[E0539]: malformed `link` attribute input
+  --> $DIR/E0458.rs:1:1
    |
 LL | #[link(kind = "wonderful_unicorn")] extern "C" {}
-   |               ^^^^^^^^^^^^^^^^^^^ unknown link kind
+   | ^^^^^^^^^^^^^^-------------------^^
+   |               |
+   |               valid arguments are "static", "dylib", "framework", "raw-dylib" or "link-arg"
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(kind = "wonderful_unicorn")] extern "C" {}
+LL + #[link(name = "...")] extern "C" {}
+   |
+LL - #[link(kind = "wonderful_unicorn")] extern "C" {}
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")] extern "C" {}
+   |
+LL - #[link(kind = "wonderful_unicorn")] extern "C" {}
+LL + #[link(name = "...", kind = "dylib|static|...")] extern "C" {}
+   |
+LL - #[link(kind = "wonderful_unicorn")] extern "C" {}
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")] extern "C" {}
+   |
+   = and 1 other candidate
 
 error[E0459]: `#[link]` attribute requires a `name = "string"` argument
   --> $DIR/E0458.rs:1:1
@@ -12,5 +31,5 @@ LL | #[link(kind = "wonderful_unicorn")] extern "C" {}
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0458, E0459.
-For more information about an error, try `rustc --explain E0458`.
+Some errors have detailed explanations: E0459, E0539.
+For more information about an error, try `rustc --explain E0459`.
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
index 60666481bec..e5dae4c0069 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
+++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs
@@ -69,7 +69,7 @@
 //~| WARN previously accepted
 //~| HELP can only be applied to
 //~| HELP remove the attribute
-#![link()] //~ WARN attribute should be applied to an `extern` block
+#![link(name = "x")] //~ WARN attribute should be applied to an `extern` block
 //~^ WARN this was previously accepted
 #![link_name = "1900"]
 //~^ WARN attribute cannot be used on
@@ -482,21 +482,26 @@ mod no_implicit_prelude {
 
 #[reexport_test_harness_main = "2900"]
 //~^ WARN crate-level attribute should be
+//~| HELP add a `!`
 mod reexport_test_harness_main {
     mod inner { #![reexport_test_harness_main="2900"] }
     //~^ WARN crate-level attribute should be
 
     #[reexport_test_harness_main = "2900"] fn f() { }
     //~^ WARN crate-level attribute should be
+    //~| HELP add a `!`
 
     #[reexport_test_harness_main = "2900"] struct S;
     //~^ WARN crate-level attribute should be
+    //~| HELP add a `!`
 
     #[reexport_test_harness_main = "2900"] type T = S;
     //~^ WARN crate-level attribute should be
+    //~| HELP add a `!`
 
     #[reexport_test_harness_main = "2900"] impl S { }
     //~^ WARN crate-level attribute should be
+    //~| HELP add a `!`
 }
 
 // Cannot feed "2700" to `#[macro_escape]` without signaling an error.
@@ -534,21 +539,26 @@ mod macro_escape {
 
 #[no_std]
 //~^ WARN crate-level attribute should be an inner attribute
+//~| HELP add a `!`
 mod no_std {
     mod inner { #![no_std] }
 //~^ WARN crate-level attribute should be in the root module
 
     #[no_std] fn f() { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[no_std] struct S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[no_std] type T = S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[no_std] impl S { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 }
 
 // At time of authorship, #[proc_macro_derive = "2500"] signals error
@@ -682,38 +692,38 @@ mod link_section {
 
 // Note that this is a `check-pass` test, so it will never invoke the linker.
 
-#[link()]
+#[link(name = "x")]
 //~^ WARN attribute should be applied to an `extern` block
 //~| WARN this was previously accepted
 mod link {
     //~^ NOTE not an `extern` block
 
-    mod inner { #![link()] }
+    mod inner { #![link(name = "x")] }
     //~^ WARN attribute should be applied to an `extern` block
     //~| WARN this was previously accepted
     //~| NOTE not an `extern` block
 
-    #[link()] fn f() { }
+    #[link(name = "x")] fn f() { }
     //~^ WARN attribute should be applied to an `extern` block
     //~| WARN this was previously accepted
     //~| NOTE not an `extern` block
 
-    #[link()] struct S;
+    #[link(name = "x")] struct S;
     //~^ WARN attribute should be applied to an `extern` block
     //~| WARN this was previously accepted
     //~| NOTE not an `extern` block
 
-    #[link()] type T = S;
+    #[link(name = "x")] type T = S;
     //~^ WARN attribute should be applied to an `extern` block
     //~| WARN this was previously accepted
     //~| NOTE not an `extern` block
 
-    #[link()] impl S { }
+    #[link(name = "x")] impl S { }
     //~^ WARN attribute should be applied to an `extern` block
     //~| WARN this was previously accepted
     //~| NOTE not an `extern` block
 
-    #[link()] extern "Rust" {}
+    #[link(name = "x")] extern "Rust" {}
     //~^ WARN attribute should be applied to an `extern` block
     //~| WARN this was previously accepted
 }
@@ -760,21 +770,26 @@ mod must_use {
 
 #[windows_subsystem = "windows"]
 //~^ WARN crate-level attribute should be an inner attribute
+//~| HELP add a `!`
 mod windows_subsystem {
     mod inner { #![windows_subsystem="windows"] }
     //~^ WARN crate-level attribute should be in the root module
 
     #[windows_subsystem = "windows"] fn f() { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[windows_subsystem = "windows"] struct S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[windows_subsystem = "windows"] type T = S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[windows_subsystem = "windows"] impl S { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 }
 
 // BROKEN USES OF CRATE-LEVEL BUILT-IN ATTRIBUTES
@@ -782,135 +797,170 @@ mod windows_subsystem {
 #[crate_name = "0900"]
 //~^ WARN crate-level attribute should be an inner attribute
 mod crate_name {
+//~^ NOTE This attribute does not have an `!`, which means it is applied to this module
     mod inner { #![crate_name="0900"] }
-//~^ WARN crate-level attribute should be in the root module
+//~^ WARN the `#![crate_name]` attribute can only be used at the crate root
 
     #[crate_name = "0900"] fn f() { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| NOTE This attribute does not have an `!`, which means it is applied to this function
 
     #[crate_name = "0900"] struct S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| NOTE This attribute does not have an `!`, which means it is applied to this struct
 
     #[crate_name = "0900"] type T = S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| NOTE This attribute does not have an `!`, which means it is applied to this type alias
 
     #[crate_name = "0900"] impl S { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| NOTE This attribute does not have an `!`, which means it is applied to this implementation block
 }
 
 #[crate_type = "0800"]
 //~^ WARN crate-level attribute should be an inner attribute
+//~| HELP add a `!`
 mod crate_type {
     mod inner { #![crate_type="0800"] }
 //~^ WARN crate-level attribute should be in the root module
 
     #[crate_type = "0800"] fn f() { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[crate_type = "0800"] struct S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[crate_type = "0800"] type T = S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[crate_type = "0800"] impl S { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 }
 
 #[feature(x0600)]
 //~^ WARN crate-level attribute should be an inner attribute
+//~| HELP add a `!`
 mod feature {
     mod inner { #![feature(x0600)] }
 //~^ WARN crate-level attribute should be in the root module
 
     #[feature(x0600)] fn f() { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[feature(x0600)] struct S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[feature(x0600)] type T = S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[feature(x0600)] impl S { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 }
 
 
 #[no_main]
 //~^ WARN crate-level attribute should be an inner attribute
+//~| HELP add a `!`
 mod no_main_1 {
     mod inner { #![no_main] }
 //~^ WARN crate-level attribute should be in the root module
 
     #[no_main] fn f() { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[no_main] struct S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[no_main] type T = S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[no_main] impl S { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 }
 
 #[no_builtins]
 //~^ WARN crate-level attribute should be an inner attribute
+//~| HELP add a `!`
 mod no_builtins {
     mod inner { #![no_builtins] }
     //~^ WARN crate-level attribute should be in the root module
 
     #[no_builtins] fn f() { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[no_builtins] struct S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[no_builtins] type T = S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[no_builtins] impl S { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 }
 
 #[recursion_limit="0200"]
 //~^ WARN crate-level attribute should be an inner attribute
+//~| HELP add a `!`
 mod recursion_limit {
     mod inner { #![recursion_limit="0200"] }
 //~^ WARN crate-level attribute should be in the root module
 
     #[recursion_limit="0200"] fn f() { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[recursion_limit="0200"] struct S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[recursion_limit="0200"] type T = S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[recursion_limit="0200"] impl S { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 }
 
 #[type_length_limit="0100"]
 //~^ WARN crate-level attribute should be an inner attribute
+//~| HELP add a `!`
 mod type_length_limit {
     mod inner { #![type_length_limit="0100"] }
 //~^ WARN crate-level attribute should be in the root module
 
     #[type_length_limit="0100"] fn f() { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[type_length_limit="0100"] struct S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[type_length_limit="0100"] type T = S;
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 
     #[type_length_limit="0100"] impl S { }
     //~^ WARN crate-level attribute should be an inner attribute
+    //~| HELP add a `!`
 }
 
 fn main() {}
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
index 7488c68b59f..ef74a00e5a1 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
+++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr
@@ -1,5 +1,5 @@
 warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:506:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:511:17
    |
 LL |     mod inner { #![macro_escape] }
    |                 ^^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL |     mod inner { #![macro_escape] }
    = help: try an outer attribute: `#[macro_use]`
 
 warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:503:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:508:1
    |
 LL | #[macro_escape]
    | ^^^^^^^^^^^^^^^
@@ -198,87 +198,126 @@ note: the lint level is defined here
 LL | #![warn(unused_attributes, unknown_lints)]
    |         ^^^^^^^^^^^^^^^^^
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+warning: crate-level attribute should be an inner attribute
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:483:1
    |
 LL | #[reexport_test_harness_main = "2900"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL | #![reexport_test_harness_main = "2900"]
+   |  +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:535:1
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:540:1
    |
 LL | #[no_std]
    | ^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL | #![no_std]
+   |  +
 
 warning: attribute should be applied to an `extern` block with non-Rust ABI
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:685:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:695:1
    |
-LL |   #[link()]
-   |   ^^^^^^^^^
+LL |   #[link(name = "x")]
+   |   ^^^^^^^^^^^^^^^^^^^
 ...
 LL | / mod link {
 LL | |
 LL | |
-LL | |     mod inner { #![link()] }
+LL | |     mod inner { #![link(name = "x")] }
 ...  |
 LL | | }
    | |_- not an `extern` block
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:761:1
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:771:1
    |
 LL | #[windows_subsystem = "windows"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:782:1
    |
-LL | #[crate_name = "0900"]
-   | ^^^^^^^^^^^^^^^^^^^^^^
+help: add a `!`
+   |
+LL | #![windows_subsystem = "windows"]
+   |  +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:801:1
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:821:1
    |
 LL | #[crate_type = "0800"]
    | ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL | #![crate_type = "0800"]
+   |  +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:820:1
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:845:1
    |
 LL | #[feature(x0600)]
    | ^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL | #![feature(x0600)]
+   |  +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:840:1
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:870:1
    |
 LL | #[no_main]
    | ^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL | #![no_main]
+   |  +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:859:1
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:894:1
    |
 LL | #[no_builtins]
    | ^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL | #![no_builtins]
+   |  +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:878:1
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:918:1
    |
 LL | #[recursion_limit="0200"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL | #![recursion_limit="0200"]
+   |  +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:897:1
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:942:1
    |
 LL | #[type_length_limit="0100"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL | #![type_length_limit="0100"]
+   |  +
 
 warning: attribute should be applied to an `extern` block with non-Rust ABI
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:72:1
    |
-LL | #![link()]
-   | ^^^^^^^^^^ not an `extern` block
+LL | #![link(name = "x")]
+   | ^^^^^^^^^^^^^^^^^^^^ not an `extern` block
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
@@ -321,352 +360,502 @@ LL |     #[macro_export] impl S { }
    |     ^^^^^^^^^^^^^^^
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:486:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:487:17
    |
 LL |     mod inner { #![reexport_test_harness_main="2900"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:489:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:490:5
    |
 LL |     #[reexport_test_harness_main = "2900"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![reexport_test_harness_main = "2900"] fn f() { }
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:492:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:494:5
    |
 LL |     #[reexport_test_harness_main = "2900"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![reexport_test_harness_main = "2900"] struct S;
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:495:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:498:5
    |
 LL |     #[reexport_test_harness_main = "2900"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![reexport_test_harness_main = "2900"] type T = S;
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:498:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:502:5
    |
 LL |     #[reexport_test_harness_main = "2900"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![reexport_test_harness_main = "2900"] impl S { }
+   |      +
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:538:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544:17
    |
 LL |     mod inner { #![no_std] }
    |                 ^^^^^^^^^^
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:541:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:547:5
    |
 LL |     #[no_std] fn f() { }
    |     ^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![no_std] fn f() { }
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:551:5
    |
 LL |     #[no_std] struct S;
    |     ^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![no_std] struct S;
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:547:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:555:5
    |
 LL |     #[no_std] type T = S;
    |     ^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![no_std] type T = S;
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:550:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:559:5
    |
 LL |     #[no_std] impl S { }
    |     ^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![no_std] impl S { }
+   |      +
 
 warning: attribute should be applied to an `extern` block with non-Rust ABI
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:691:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:701:17
    |
-LL |     mod inner { #![link()] }
-   |     ------------^^^^^^^^^^-- not an `extern` block
+LL |     mod inner { #![link(name = "x")] }
+   |     ------------^^^^^^^^^^^^^^^^^^^^-- not an `extern` block
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to an `extern` block with non-Rust ABI
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:706:5
    |
-LL |     #[link()] fn f() { }
-   |     ^^^^^^^^^ ---------- not an `extern` block
+LL |     #[link(name = "x")] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^^^ ---------- not an `extern` block
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to an `extern` block with non-Rust ABI
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:701:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:5
    |
-LL |     #[link()] struct S;
-   |     ^^^^^^^^^ --------- not an `extern` block
+LL |     #[link(name = "x")] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^ --------- not an `extern` block
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to an `extern` block with non-Rust ABI
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:706:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:716:5
    |
-LL |     #[link()] type T = S;
-   |     ^^^^^^^^^ ----------- not an `extern` block
+LL |     #[link(name = "x")] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^ ----------- not an `extern` block
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to an `extern` block with non-Rust ABI
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5
    |
-LL |     #[link()] impl S { }
-   |     ^^^^^^^^^ ---------- not an `extern` block
+LL |     #[link(name = "x")] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^ ---------- not an `extern` block
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: attribute should be applied to an `extern` block with non-Rust ABI
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:716:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:726:5
    |
-LL |     #[link()] extern "Rust" {}
-   |     ^^^^^^^^^
+LL |     #[link(name = "x")] extern "Rust" {}
+   |     ^^^^^^^^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:764:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:775:17
    |
 LL |     mod inner { #![windows_subsystem="windows"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:767:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:778:5
    |
 LL |     #[windows_subsystem = "windows"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![windows_subsystem = "windows"] fn f() { }
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:770:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:782:5
    |
 LL |     #[windows_subsystem = "windows"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:773:5
    |
-LL |     #[windows_subsystem = "windows"] type T = S;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: add a `!`
+   |
+LL |     #![windows_subsystem = "windows"] struct S;
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:776:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:786:5
    |
-LL |     #[windows_subsystem = "windows"] impl S { }
+LL |     #[windows_subsystem = "windows"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:785:17
    |
-LL |     mod inner { #![crate_name="0900"] }
-   |                 ^^^^^^^^^^^^^^^^^^^^^
-
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:788:5
+help: add a `!`
    |
-LL |     #[crate_name = "0900"] fn f() { }
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+LL |     #![windows_subsystem = "windows"] type T = S;
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:791:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:790:5
    |
-LL |     #[crate_name = "0900"] struct S;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:794:5
+LL |     #[windows_subsystem = "windows"] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-LL |     #[crate_name = "0900"] type T = S;
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:797:5
+help: add a `!`
    |
-LL |     #[crate_name = "0900"] impl S { }
-   |     ^^^^^^^^^^^^^^^^^^^^^^
+LL |     #![windows_subsystem = "windows"] impl S { }
+   |      +
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:804:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:825:17
    |
 LL |     mod inner { #![crate_type="0800"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:807:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:828:5
    |
 LL |     #[crate_type = "0800"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![crate_type = "0800"] fn f() { }
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:810:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:832:5
    |
 LL |     #[crate_type = "0800"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![crate_type = "0800"] struct S;
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:813:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:836:5
    |
 LL |     #[crate_type = "0800"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![crate_type = "0800"] type T = S;
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:816:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:840:5
    |
 LL |     #[crate_type = "0800"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![crate_type = "0800"] impl S { }
+   |      +
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:823:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:849:17
    |
 LL |     mod inner { #![feature(x0600)] }
    |                 ^^^^^^^^^^^^^^^^^^
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:826:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:852:5
    |
 LL |     #[feature(x0600)] fn f() { }
    |     ^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![feature(x0600)] fn f() { }
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:829:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:856:5
    |
 LL |     #[feature(x0600)] struct S;
    |     ^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![feature(x0600)] struct S;
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:832:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:860:5
    |
 LL |     #[feature(x0600)] type T = S;
    |     ^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![feature(x0600)] type T = S;
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:835:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:864:5
    |
 LL |     #[feature(x0600)] impl S { }
    |     ^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![feature(x0600)] impl S { }
+   |      +
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:843:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:874:17
    |
 LL |     mod inner { #![no_main] }
    |                 ^^^^^^^^^^^
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:846:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:877:5
    |
 LL |     #[no_main] fn f() { }
    |     ^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![no_main] fn f() { }
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:849:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:881:5
    |
 LL |     #[no_main] struct S;
    |     ^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![no_main] struct S;
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:852:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:885:5
    |
 LL |     #[no_main] type T = S;
    |     ^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![no_main] type T = S;
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:855:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:889:5
    |
 LL |     #[no_main] impl S { }
    |     ^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![no_main] impl S { }
+   |      +
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:862:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:898:17
    |
 LL |     mod inner { #![no_builtins] }
    |                 ^^^^^^^^^^^^^^^
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:865:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:901:5
    |
 LL |     #[no_builtins] fn f() { }
    |     ^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![no_builtins] fn f() { }
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:868:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:905:5
    |
 LL |     #[no_builtins] struct S;
    |     ^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![no_builtins] struct S;
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:871:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:909:5
    |
 LL |     #[no_builtins] type T = S;
    |     ^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![no_builtins] type T = S;
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:874:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:913:5
    |
 LL |     #[no_builtins] impl S { }
    |     ^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![no_builtins] impl S { }
+   |      +
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:881:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:922:17
    |
 LL |     mod inner { #![recursion_limit="0200"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:884:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:925:5
    |
 LL |     #[recursion_limit="0200"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![recursion_limit="0200"] fn f() { }
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:887:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:929:5
    |
 LL |     #[recursion_limit="0200"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![recursion_limit="0200"] struct S;
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:890:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:933:5
    |
 LL |     #[recursion_limit="0200"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![recursion_limit="0200"] type T = S;
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:893:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:937:5
    |
 LL |     #[recursion_limit="0200"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![recursion_limit="0200"] impl S { }
+   |      +
 
 warning: crate-level attribute should be in the root module
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:900:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:946:17
    |
 LL |     mod inner { #![type_length_limit="0100"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:903:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:949:5
    |
 LL |     #[type_length_limit="0100"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![type_length_limit="0100"] fn f() { }
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:906:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:953:5
    |
 LL |     #[type_length_limit="0100"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![type_length_limit="0100"] struct S;
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:909:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:957:5
    |
 LL |     #[type_length_limit="0100"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![type_length_limit="0100"] type T = S;
+   |      +
 
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:912:5
+warning: crate-level attribute should be an inner attribute
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:961:5
    |
 LL |     #[type_length_limit="0100"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL |     #![type_length_limit="0100"] impl S { }
+   |      +
 
 warning: `#[macro_use]` attribute cannot be used on functions
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:191:5
@@ -993,7 +1182,7 @@ LL |     #[no_implicit_prelude] impl S { }
    = help: `#[no_implicit_prelude]` can be applied to modules and crates
 
 warning: `#[macro_escape]` attribute cannot be used on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:510:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:515:5
    |
 LL |     #[macro_escape] fn f() { }
    |     ^^^^^^^^^^^^^^^
@@ -1002,7 +1191,7 @@ LL |     #[macro_escape] fn f() { }
    = help: `#[macro_escape]` can be applied to modules, extern crates, and crates
 
 warning: `#[macro_escape]` attribute cannot be used on structs
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:516:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:521:5
    |
 LL |     #[macro_escape] struct S;
    |     ^^^^^^^^^^^^^^^
@@ -1011,7 +1200,7 @@ LL |     #[macro_escape] struct S;
    = help: `#[macro_escape]` can be applied to modules, extern crates, and crates
 
 warning: `#[macro_escape]` attribute cannot be used on type aliases
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:522:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:527:5
    |
 LL |     #[macro_escape] type T = S;
    |     ^^^^^^^^^^^^^^^
@@ -1020,7 +1209,7 @@ LL |     #[macro_escape] type T = S;
    = help: `#[macro_escape]` can be applied to modules, extern crates, and crates
 
 warning: `#[macro_escape]` attribute cannot be used on inherent impl blocks
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:528:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:533:5
    |
 LL |     #[macro_escape] impl S { }
    |     ^^^^^^^^^^^^^^^
@@ -1029,7 +1218,7 @@ LL |     #[macro_escape] impl S { }
    = help: `#[macro_escape]` can be applied to modules, extern crates, and crates
 
 warning: `#[cold]` attribute cannot be used on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:571:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:581:1
    |
 LL | #[cold]
    | ^^^^^^^
@@ -1038,7 +1227,7 @@ LL | #[cold]
    = help: `#[cold]` can only be applied to functions
 
 warning: `#[cold]` attribute cannot be used on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:578:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:588:17
    |
 LL |     mod inner { #![cold] }
    |                 ^^^^^^^^
@@ -1047,7 +1236,7 @@ LL |     mod inner { #![cold] }
    = help: `#[cold]` can only be applied to functions
 
 warning: `#[cold]` attribute cannot be used on structs
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:586:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:596:5
    |
 LL |     #[cold] struct S;
    |     ^^^^^^^
@@ -1056,7 +1245,7 @@ LL |     #[cold] struct S;
    = help: `#[cold]` can only be applied to functions
 
 warning: `#[cold]` attribute cannot be used on type aliases
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:592:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:602:5
    |
 LL |     #[cold] type T = S;
    |     ^^^^^^^
@@ -1065,7 +1254,7 @@ LL |     #[cold] type T = S;
    = help: `#[cold]` can only be applied to functions
 
 warning: `#[cold]` attribute cannot be used on inherent impl blocks
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:598:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:608:5
    |
 LL |     #[cold] impl S { }
    |     ^^^^^^^
@@ -1074,7 +1263,7 @@ LL |     #[cold] impl S { }
    = help: `#[cold]` can only be applied to functions
 
 warning: `#[link_name]` attribute cannot be used on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:605:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:615:1
    |
 LL | #[link_name = "1900"]
    | ^^^^^^^^^^^^^^^^^^^^^
@@ -1083,7 +1272,7 @@ LL | #[link_name = "1900"]
    = help: `#[link_name]` can be applied to foreign functions and foreign statics
 
 warning: `#[link_name]` attribute cannot be used on foreign modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:611:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:621:5
    |
 LL |     #[link_name = "1900"]
    |     ^^^^^^^^^^^^^^^^^^^^^
@@ -1092,7 +1281,7 @@ LL |     #[link_name = "1900"]
    = help: `#[link_name]` can be applied to foreign functions and foreign statics
 
 warning: `#[link_name]` attribute cannot be used on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:618:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:628:17
    |
 LL |     mod inner { #![link_name="1900"] }
    |                 ^^^^^^^^^^^^^^^^^^^^
@@ -1101,7 +1290,7 @@ LL |     mod inner { #![link_name="1900"] }
    = help: `#[link_name]` can be applied to foreign functions and foreign statics
 
 warning: `#[link_name]` attribute cannot be used on functions
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:624:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:634:5
    |
 LL |     #[link_name = "1900"] fn f() { }
    |     ^^^^^^^^^^^^^^^^^^^^^
@@ -1110,7 +1299,7 @@ LL |     #[link_name = "1900"] fn f() { }
    = help: `#[link_name]` can be applied to foreign functions and foreign statics
 
 warning: `#[link_name]` attribute cannot be used on structs
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:630:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:640:5
    |
 LL |     #[link_name = "1900"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^
@@ -1119,7 +1308,7 @@ LL |     #[link_name = "1900"] struct S;
    = help: `#[link_name]` can be applied to foreign functions and foreign statics
 
 warning: `#[link_name]` attribute cannot be used on type aliases
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:636:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:646:5
    |
 LL |     #[link_name = "1900"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^
@@ -1128,7 +1317,7 @@ LL |     #[link_name = "1900"] type T = S;
    = help: `#[link_name]` can be applied to foreign functions and foreign statics
 
 warning: `#[link_name]` attribute cannot be used on inherent impl blocks
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:642:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:652:5
    |
 LL |     #[link_name = "1900"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^
@@ -1137,7 +1326,7 @@ LL |     #[link_name = "1900"] impl S { }
    = help: `#[link_name]` can be applied to foreign functions and foreign statics
 
 warning: `#[link_section]` attribute cannot be used on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:649:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:659:1
    |
 LL | #[link_section = "1800"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1146,7 +1335,7 @@ LL | #[link_section = "1800"]
    = help: `#[link_section]` can be applied to statics and functions
 
 warning: `#[link_section]` attribute cannot be used on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:655:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:665:17
    |
 LL |     mod inner { #![link_section="1800"] }
    |                 ^^^^^^^^^^^^^^^^^^^^^^^
@@ -1155,7 +1344,7 @@ LL |     mod inner { #![link_section="1800"] }
    = help: `#[link_section]` can be applied to statics and functions
 
 warning: `#[link_section]` attribute cannot be used on structs
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:663:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:673:5
    |
 LL |     #[link_section = "1800"] struct S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1164,7 +1353,7 @@ LL |     #[link_section = "1800"] struct S;
    = help: `#[link_section]` can be applied to statics and functions
 
 warning: `#[link_section]` attribute cannot be used on type aliases
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:669:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:679:5
    |
 LL |     #[link_section = "1800"] type T = S;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1173,7 +1362,7 @@ LL |     #[link_section = "1800"] type T = S;
    = help: `#[link_section]` can be applied to statics and functions
 
 warning: `#[link_section]` attribute cannot be used on inherent impl blocks
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:675:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:685:5
    |
 LL |     #[link_section = "1800"] impl S { }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -1182,7 +1371,7 @@ LL |     #[link_section = "1800"] impl S { }
    = help: `#[link_section]` can be applied to statics and functions
 
 warning: `#[must_use]` attribute cannot be used on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:736:1
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:746:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
@@ -1191,7 +1380,7 @@ LL | #[must_use]
    = help: `#[must_use]` can be applied to functions, data types, unions, and traits
 
 warning: `#[must_use]` attribute cannot be used on modules
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:741:17
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:751:17
    |
 LL |     mod inner { #![must_use] }
    |                 ^^^^^^^^^^^^
@@ -1200,7 +1389,7 @@ LL |     mod inner { #![must_use] }
    = help: `#[must_use]` can be applied to functions, data types, unions, and traits
 
 warning: `#[must_use]` attribute cannot be used on type aliases
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:760:5
    |
 LL |     #[must_use] type T = S;
    |     ^^^^^^^^^^^
@@ -1209,7 +1398,7 @@ LL |     #[must_use] type T = S;
    = help: `#[must_use]` can be applied to functions, data types, unions, and traits
 
 warning: `#[must_use]` attribute cannot be used on inherent impl blocks
-  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:755:5
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:765:5
    |
 LL |     #[must_use] impl S { }
    |     ^^^^^^^^^^^
@@ -1217,6 +1406,76 @@ LL |     #[must_use] impl S { }
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
    = help: `#[must_use]` can be applied to functions, data types, unions, and traits
 
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:797:1
+   |
+LL | #[crate_name = "0900"]
+   | ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: This attribute does not have an `!`, which means it is applied to this module
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:799:1
+   |
+LL | / mod crate_name {
+LL | |
+LL | |     mod inner { #![crate_name="0900"] }
+...  |
+LL | | }
+   | |_^
+
+warning: the `#![crate_name]` attribute can only be used at the crate root
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:801:17
+   |
+LL |     mod inner { #![crate_name="0900"] }
+   |                 ^^^^^^^^^^^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:804:5
+   |
+LL |     #[crate_name = "0900"] fn f() { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: This attribute does not have an `!`, which means it is applied to this function
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:804:28
+   |
+LL |     #[crate_name = "0900"] fn f() { }
+   |                            ^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:808:5
+   |
+LL |     #[crate_name = "0900"] struct S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: This attribute does not have an `!`, which means it is applied to this struct
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:808:28
+   |
+LL |     #[crate_name = "0900"] struct S;
+   |                            ^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:812:5
+   |
+LL |     #[crate_name = "0900"] type T = S;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: This attribute does not have an `!`, which means it is applied to this type alias
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:812:28
+   |
+LL |     #[crate_name = "0900"] type T = S;
+   |                            ^^^^^^^^^^^
+
+warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:816:5
+   |
+LL |     #[crate_name = "0900"] impl S { }
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: This attribute does not have an `!`, which means it is applied to this implementation block
+  --> $DIR/issue-43106-gating-of-builtin-attrs.rs:816:28
+   |
+LL |     #[crate_name = "0900"] impl S { }
+   |                            ^^^^^^^^^^
+
 warning: `#[should_panic]` attribute cannot be used on crates
   --> $DIR/issue-43106-gating-of-builtin-attrs.rs:50:1
    |
diff --git a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.next.stderr b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.next.stderr
index d624fb1e42b..d6294efbd28 100644
--- a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.next.stderr
+++ b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.next.stderr
@@ -1,30 +1,14 @@
-error[E0283]: type annotations needed
-  --> $DIR/ambig-hr-projection-issue-93340.rs:17:5
+error[E0282]: type annotations needed
+  --> $DIR/ambig-hr-projection-issue-93340.rs:16:5
    |
 LL |     cmp_eq
    |     ^^^^^^ cannot infer type of the type parameter `A` declared on the function `cmp_eq`
    |
-   = note: cannot satisfy `_: Scalar`
-note: required by a bound in `cmp_eq`
-  --> $DIR/ambig-hr-projection-issue-93340.rs:10:22
-   |
-LL | fn cmp_eq<'a, 'b, A: Scalar, B: Scalar, O: Scalar>(a: A::RefType<'a>, b: B::RefType<'b>) -> O {
-   |                      ^^^^^^ required by this bound in `cmp_eq`
 help: consider specifying the generic arguments
    |
 LL |     cmp_eq::<A, B, O>
    |           +++++++++++
 
-error[E0277]: expected a `Fn(<A as Scalar>::RefType<'_>, <B as Scalar>::RefType<'_>)` closure, found `for<'a, 'b> fn(<O as Scalar>::RefType<'a>, <_ as Scalar>::RefType<'b>) -> O {cmp_eq::<O, _, O>}`
-  --> $DIR/ambig-hr-projection-issue-93340.rs:14:1
-   |
-LL | / fn build_expression<A: Scalar, B: Scalar, O: Scalar>(
-LL | | ) -> impl Fn(A::RefType<'_>, B::RefType<'_>) -> O {
-   | |_________________________________________________^ expected an `Fn(<A as Scalar>::RefType<'_>, <B as Scalar>::RefType<'_>)` closure, found `for<'a, 'b> fn(<O as Scalar>::RefType<'a>, <_ as Scalar>::RefType<'b>) -> O {cmp_eq::<O, _, O>}`
-   |
-   = help: the trait `for<'a, 'b> Fn(<A as Scalar>::RefType<'a>, <B as Scalar>::RefType<'b>)` is not implemented for fn item `for<'a, 'b> fn(<O as Scalar>::RefType<'a>, <_ as Scalar>::RefType<'b>) -> O {cmp_eq::<O, _, O>}`
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0277, E0283.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.old.stderr b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.old.stderr
index 4a293d44e0e..d913b2e91ca 100644
--- a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.old.stderr
+++ b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.old.stderr
@@ -1,5 +1,5 @@
 error[E0283]: type annotations needed
-  --> $DIR/ambig-hr-projection-issue-93340.rs:17:5
+  --> $DIR/ambig-hr-projection-issue-93340.rs:16:5
    |
 LL |     cmp_eq
    |     ^^^^^^ cannot infer type of the type parameter `A` declared on the function `cmp_eq`
diff --git a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.rs b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.rs
index 6ba3c4c65d0..acfebad38db 100644
--- a/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.rs
+++ b/tests/ui/generic-associated-types/ambig-hr-projection-issue-93340.rs
@@ -13,7 +13,6 @@ fn cmp_eq<'a, 'b, A: Scalar, B: Scalar, O: Scalar>(a: A::RefType<'a>, b: B::RefT
 
 fn build_expression<A: Scalar, B: Scalar, O: Scalar>(
 ) -> impl Fn(A::RefType<'_>, B::RefType<'_>) -> O {
-    //[next]~^^ ERROR expected a `Fn(<A as Scalar>::RefType<'_>, <B as Scalar>::RefType<'_>)` closure
     cmp_eq
     //~^ ERROR type annotations needed
 }
diff --git a/tests/ui/higher-ranked/higher-ranked-lifetime-error.stderr b/tests/ui/higher-ranked/higher-ranked-lifetime-error.stderr
index d7add865aa0..2e3fd612334 100644
--- a/tests/ui/higher-ranked/higher-ranked-lifetime-error.stderr
+++ b/tests/ui/higher-ranked/higher-ranked-lifetime-error.stderr
@@ -2,7 +2,7 @@ error: implementation of `FnMut` is not general enough
   --> $DIR/higher-ranked-lifetime-error.rs:12:5
    |
 LL |     assert_all::<_, &String>(id);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnMut` is not general enough
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnMut` is not general enough
    |
    = note: `for<'a> fn(&'a String) -> &'a String {id}` must implement `FnMut<(&String,)>`
    = note: ...but it actually implements `FnMut<(&'0 String,)>`, for some specific lifetime `'0`
diff --git a/tests/ui/higher-ranked/trait-bounds/due-to-where-clause.stderr b/tests/ui/higher-ranked/trait-bounds/due-to-where-clause.stderr
index 916854e07af..6c17b1f4874 100644
--- a/tests/ui/higher-ranked/trait-bounds/due-to-where-clause.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/due-to-where-clause.stderr
@@ -2,7 +2,7 @@ error: implementation of `Foo` is not general enough
   --> $DIR/due-to-where-clause.rs:2:5
    |
 LL |     test::<FooS>(&mut 42);
-   |     ^^^^^^^^^^^^ implementation of `Foo` is not general enough
+   |     ^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough
    |
    = note: `FooS<'_>` must implement `Foo<'0>`, for any lifetime `'0`...
    = note: ...but `FooS<'_>` actually implements `Foo<'1>`, for some specific lifetime `'1`
diff --git a/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr b/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr
index 5caf0eb2fd4..7170efc8638 100644
--- a/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr
+++ b/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr
@@ -1,17 +1,9 @@
-error[E0283]: type annotations needed
+error[E0282]: type annotations needed
   --> $DIR/auto-trait-selection-freeze.rs:19:16
    |
 LL |     if false { is_trait(foo()) } else { Default::default() }
-   |                ^^^^^^^^ ----- type must be known at this point
-   |                |
-   |                cannot infer type of the type parameter `T` declared on the function `is_trait`
+   |                ^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `is_trait`
    |
-   = note: cannot satisfy `_: Trait<_>`
-note: required by a bound in `is_trait`
-  --> $DIR/auto-trait-selection-freeze.rs:11:16
-   |
-LL | fn is_trait<T: Trait<U>, U: Default>(_: T) -> U {
-   |                ^^^^^^^^ required by this bound in `is_trait`
 help: consider specifying the generic arguments
    |
 LL |     if false { is_trait::<T, U>(foo()) } else { Default::default() }
@@ -19,4 +11,4 @@ LL |     if false { is_trait::<T, U>(foo()) } else { Default::default() }
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0283`.
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/auto-trait-selection.next.stderr b/tests/ui/impl-trait/auto-trait-selection.next.stderr
index d34fdcc4496..0f33aca3019 100644
--- a/tests/ui/impl-trait/auto-trait-selection.next.stderr
+++ b/tests/ui/impl-trait/auto-trait-selection.next.stderr
@@ -1,17 +1,9 @@
-error[E0283]: type annotations needed
+error[E0282]: type annotations needed
   --> $DIR/auto-trait-selection.rs:15:16
    |
 LL |     if false { is_trait(foo()) } else { Default::default() }
-   |                ^^^^^^^^ ----- type must be known at this point
-   |                |
-   |                cannot infer type of the type parameter `T` declared on the function `is_trait`
+   |                ^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `is_trait`
    |
-   = note: cannot satisfy `_: Trait<_>`
-note: required by a bound in `is_trait`
-  --> $DIR/auto-trait-selection.rs:7:16
-   |
-LL | fn is_trait<T: Trait<U>, U: Default>(_: T) -> U {
-   |                ^^^^^^^^ required by this bound in `is_trait`
 help: consider specifying the generic arguments
    |
 LL |     if false { is_trait::<T, U>(foo()) } else { Default::default() }
@@ -19,4 +11,4 @@ LL |     if false { is_trait::<T, U>(foo()) } else { Default::default() }
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0283`.
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/call_method_without_import.no_import.stderr b/tests/ui/impl-trait/call_method_without_import.no_import.stderr
index dbac74b2247..2ca79aa7c10 100644
--- a/tests/ui/impl-trait/call_method_without_import.no_import.stderr
+++ b/tests/ui/impl-trait/call_method_without_import.no_import.stderr
@@ -3,6 +3,7 @@ error[E0599]: no method named `fmt` found for opaque type `impl Debug` in the cu
    |
 LL |         x.fmt(f);
    |           ^^^ method not found in `impl Debug`
+   |
   --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
    |
    = note: the method is available for `impl Debug` here
diff --git a/tests/ui/impl-trait/impl-generic-mismatch.stderr b/tests/ui/impl-trait/impl-generic-mismatch.stderr
index 18347bd0f97..d7fff4c445d 100644
--- a/tests/ui/impl-trait/impl-generic-mismatch.stderr
+++ b/tests/ui/impl-trait/impl-generic-mismatch.stderr
@@ -48,6 +48,7 @@ error[E0643]: method `hash` has incompatible signature for trait
    |
 LL |     fn hash(&self, hasher: &mut impl Hasher) {}
    |                                 ^^^^^^^^^^^ expected generic parameter, found `impl Trait`
+   |
   --> $SRC_DIR/core/src/hash/mod.rs:LL:COL
    |
    = note: declaration in trait here
diff --git a/tests/ui/impl-trait/recursive-in-exhaustiveness.current.stderr b/tests/ui/impl-trait/recursive-in-exhaustiveness.current.stderr
index 080c3284641..11a88b0918c 100644
--- a/tests/ui/impl-trait/recursive-in-exhaustiveness.current.stderr
+++ b/tests/ui/impl-trait/recursive-in-exhaustiveness.current.stderr
@@ -11,7 +11,7 @@ LL | fn build2<T>(x: T) -> impl Sized {
    |                       ^^^^^^^^^^
 
 error[E0720]: cannot resolve opaque type
-  --> $DIR/recursive-in-exhaustiveness.rs:39:23
+  --> $DIR/recursive-in-exhaustiveness.rs:37:23
    |
 LL | fn build3<T>(x: T) -> impl Sized {
    |                       ^^^^^^^^^^
diff --git a/tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr b/tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr
index db57be73acc..45df8cc9c0c 100644
--- a/tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr
+++ b/tests/ui/impl-trait/recursive-in-exhaustiveness.next.stderr
@@ -1,80 +1,21 @@
-error[E0284]: type annotations needed: cannot normalize `build<_>::{opaque#0}`
-  --> $DIR/recursive-in-exhaustiveness.rs:20:5
+error[E0282]: type annotations needed
+  --> $DIR/recursive-in-exhaustiveness.rs:19:17
    |
-LL |     build(x)
-   |     ^^^^^^^^ cannot normalize `build<_>::{opaque#0}`
+LL |     let (x,) = (build(x),);
+   |                 ^^^^^^^^ cannot infer type
 
-error[E0271]: type mismatch resolving `build2<(_,)>::{opaque#0} normalizes-to _`
-  --> $DIR/recursive-in-exhaustiveness.rs:30:6
+error[E0282]: type annotations needed
+  --> $DIR/recursive-in-exhaustiveness.rs:29:17
    |
-LL |     (build2(x),)
-   |      ^^^^^^^^^ types differ
+LL |     let (x,) = (build2(x),);
+   |                 ^^^^^^^^^ cannot infer type
 
-error[E0271]: type mismatch resolving `build2<(_,)>::{opaque#0} normalizes-to _`
-  --> $DIR/recursive-in-exhaustiveness.rs:30:5
+error[E0282]: type annotations needed
+  --> $DIR/recursive-in-exhaustiveness.rs:40:5
    |
-LL |     (build2(x),)
-   |     ^^^^^^^^^^^^ types differ
+LL |     build3(x)
+   |     ^^^^^^^^^ cannot infer type
 
-error[E0277]: the size for values of type `(impl Sized,)` cannot be known at compilation time
-  --> $DIR/recursive-in-exhaustiveness.rs:30:5
-   |
-LL |     (build2(x),)
-   |     ^^^^^^^^^^^^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `(impl Sized,)`
-   = note: tuples must have a statically known size to be initialized
-
-error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _`
-  --> $DIR/recursive-in-exhaustiveness.rs:41:17
-   |
-LL |     let (x,) = (build3((x,)),);
-   |                 ^^^^^^^^^^^^ types differ
-
-error[E0277]: the size for values of type `(impl Sized,)` cannot be known at compilation time
-  --> $DIR/recursive-in-exhaustiveness.rs:41:16
-   |
-LL |     let (x,) = (build3((x,)),);
-   |                ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `(impl Sized,)`
-   = note: tuples must have a statically known size to be initialized
-
-error[E0308]: mismatched types
-  --> $DIR/recursive-in-exhaustiveness.rs:41:16
-   |
-LL | fn build3<T>(x: T) -> impl Sized {
-   |                       ---------- the found opaque type
-LL |
-LL |     let (x,) = (build3((x,)),);
-   |                ^^^^^^^^^^^^^^^ types differ
-   |
-   = note: expected type `_`
-             found tuple `(impl Sized,)`
-
-error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _`
-  --> $DIR/recursive-in-exhaustiveness.rs:41:17
-   |
-LL |     let (x,) = (build3((x,)),);
-   |                 ^^^^^^^^^^^^ types differ
-   |
-   = note: the return type of a function must have a statically known size
-
-error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _`
-  --> $DIR/recursive-in-exhaustiveness.rs:41:16
-   |
-LL |     let (x,) = (build3((x,)),);
-   |                ^^^^^^^^^^^^^^^ types differ
-
-error[E0271]: type mismatch resolving `build3<(T,)>::{opaque#0} normalizes-to _`
-  --> $DIR/recursive-in-exhaustiveness.rs:41:17
-   |
-LL |     let (x,) = (build3((x,)),);
-   |                 ^^^^^^^^^^^^ types differ
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: aborting due to 10 previous errors
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0271, E0277, E0284, E0308.
-For more information about an error, try `rustc --explain E0271`.
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/recursive-in-exhaustiveness.rs b/tests/ui/impl-trait/recursive-in-exhaustiveness.rs
index dabef22af86..7aee8a630a5 100644
--- a/tests/ui/impl-trait/recursive-in-exhaustiveness.rs
+++ b/tests/ui/impl-trait/recursive-in-exhaustiveness.rs
@@ -17,8 +17,8 @@
 fn build<T>(x: T) -> impl Sized {
     //[current]~^ ERROR cannot resolve opaque type
     let (x,) = (build(x),);
+    //[next]~^ ERROR type annotations needed
     build(x)
-    //[next]~^ ERROR type annotations needed: cannot normalize `build<_>::{opaque#0}`
 }
 
 // Opaque<T> = (Opaque<T>,)
@@ -27,10 +27,8 @@ fn build<T>(x: T) -> impl Sized {
 fn build2<T>(x: T) -> impl Sized {
     //[current]~^ ERROR cannot resolve opaque type
     let (x,) = (build2(x),);
+    //[next]~^ ERROR type annotations needed
     (build2(x),)
-    //[next]~^ ERROR type mismatch resolving
-    //[next]~| ERROR type mismatch resolving
-    //[next]~| ERROR the size for values of type
 }
 
 // Opaque<T> = Opaque<(T,)>
@@ -39,13 +37,8 @@ fn build2<T>(x: T) -> impl Sized {
 fn build3<T>(x: T) -> impl Sized {
     //[current]~^ ERROR cannot resolve opaque type
     let (x,) = (build3((x,)),);
-    //[next]~^ ERROR type mismatch resolving
-    //[next]~| ERROR type mismatch resolving
-    //[next]~| ERROR type mismatch resolving
-    //[next]~| ERROR type mismatch resolving
-    //[next]~| ERROR the size for values of type
-    //[next]~| ERROR mismatched types
     build3(x)
+    //[next]~^ ERROR type annotations needed
 }
 
 fn main() {}
diff --git a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr
index 3651226e0c3..7a9254bac60 100644
--- a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr
+++ b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr
@@ -1,8 +1,8 @@
 warning: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/rpit-assoc-pair-with-lifetime.rs:3:31
+  --> $DIR/rpit-assoc-pair-with-lifetime.rs:3:82
    |
 LL | pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator<Item = (u32, &u32)> {
-   |                               ^^ the lifetime is named here                      ---- the same lifetime is elided here
+   |                               -- the lifetime is named here                      ^^^^ the same lifetime is elided here
    |
    = help: the same lifetime is referred to in inconsistent ways, making the signature confusing
    = note: `#[warn(mismatched_lifetime_syntaxes)]` on by default
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr b/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr
index fac4776905d..785e5fdeb64 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr
+++ b/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr
@@ -1,9 +1,15 @@
 error[E0282]: type annotations needed
-  --> $DIR/two_tait_defining_each_other2.rs:12:11
+  --> $DIR/two_tait_defining_each_other2.rs:12:8
    |
 LL | fn muh(x: A) -> B {
-   |           ^ cannot infer type
+   |        ^ cannot infer type
 
-error: aborting due to 1 previous error
+error[E0282]: type annotations needed
+  --> $DIR/two_tait_defining_each_other2.rs:14:5
+   |
+LL |     x // B's hidden type is A (opaquely)
+   |     ^ cannot infer type
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other2.rs b/tests/ui/impl-trait/two_tait_defining_each_other2.rs
index ec2963249f9..99262f4bc4b 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other2.rs
+++ b/tests/ui/impl-trait/two_tait_defining_each_other2.rs
@@ -12,7 +12,8 @@ trait Foo {}
 fn muh(x: A) -> B {
     //[next]~^ ERROR: type annotations needed
     x // B's hidden type is A (opaquely)
-    //[current]~^ ERROR opaque type's hidden type cannot be another opaque type
+    //[next]~^ ERROR: type annotations needed
+    //[current]~^^ ERROR opaque type's hidden type cannot be another opaque type
 }
 
 struct Bar;
diff --git a/tests/ui/imports/suggest-remove-issue-121315.stderr b/tests/ui/imports/suggest-remove-issue-121315.stderr
index 5d0bf9bea6a..c91ea8a8793 100644
--- a/tests/ui/imports/suggest-remove-issue-121315.stderr
+++ b/tests/ui/imports/suggest-remove-issue-121315.stderr
@@ -3,10 +3,10 @@ error: the item `TryFrom` is imported redundantly
    |
 LL |     use std::convert::TryFrom;
    |         ^^^^^^^^^^^^^^^^^^^^^
+   |
   --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
    |
    = note: the item `TryFrom` is already defined here
-   |
 note: the lint level is defined here
   --> $DIR/suggest-remove-issue-121315.rs:2:25
    |
@@ -18,6 +18,7 @@ error: the item `TryFrom` is imported redundantly
    |
 LL |     use std::convert::{TryFrom, TryInto};
    |                        ^^^^^^^
+   |
   --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
    |
    = note: the item `TryFrom` is already defined here
@@ -27,6 +28,7 @@ error: the item `TryInto` is imported redundantly
    |
 LL |     use std::convert::{TryFrom, TryInto};
    |                                 ^^^^^^^
+   |
   --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
    |
    = note: the item `TryInto` is already defined here
@@ -48,6 +50,7 @@ error: the item `Into` is imported redundantly
    |
 LL |     use std::convert::{AsMut, Into};
    |                               ^^^^
+   |
   --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
    |
    = note: the item `Into` is already defined here
diff --git a/tests/ui/invalid-compile-flags/print-crate-name-request-malformed-crate-name.rs b/tests/ui/invalid-compile-flags/print-crate-name-request-malformed-crate-name.rs
index c7f3c2c5403..62f1f6cd09c 100644
--- a/tests/ui/invalid-compile-flags/print-crate-name-request-malformed-crate-name.rs
+++ b/tests/ui/invalid-compile-flags/print-crate-name-request-malformed-crate-name.rs
@@ -2,4 +2,4 @@
 // See also <https://github.com/rust-lang/rust/issues/122001>.
 
 //@ compile-flags: --print=crate-name
-#![crate_name = concat!("wrapped")] //~ ERROR malformed `crate_name` attribute input
+#![crate_name = concat!("wrapped")] //~ ERROR attribute value must be a literal
diff --git a/tests/ui/invalid-compile-flags/print-crate-name-request-malformed-crate-name.stderr b/tests/ui/invalid-compile-flags/print-crate-name-request-malformed-crate-name.stderr
index b773f7c97aa..fab38dae78b 100644
--- a/tests/ui/invalid-compile-flags/print-crate-name-request-malformed-crate-name.stderr
+++ b/tests/ui/invalid-compile-flags/print-crate-name-request-malformed-crate-name.stderr
@@ -1,10 +1,8 @@
-error: malformed `crate_name` attribute input
-  --> $DIR/print-crate-name-request-malformed-crate-name.rs:5:1
+error: attribute value must be a literal
+  --> $DIR/print-crate-name-request-malformed-crate-name.rs:5:17
    |
 LL | #![crate_name = concat!("wrapped")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_name = "name"]`
-   |
-   = note: for more information, visit <https://doc.rust-lang.org/reference/crates-and-source-files.html#the-crate_name-attribute>
+   |                 ^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-1.stderr b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-1.stderr
index 64e38ed8533..d3e60948e4c 100644
--- a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-1.stderr
+++ b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-1.stderr
@@ -1,10 +1,9 @@
-error: malformed `crate_name` attribute input
+error[E0539]: malformed `crate_name` attribute input
   --> $DIR/print-file-names-request-malformed-crate-name-1.rs:4:1
    |
 LL | #![crate_name]
    | ^^^^^^^^^^^^^^ help: must be of the form: `#![crate_name = "name"]`
-   |
-   = note: for more information, visit <https://doc.rust-lang.org/reference/crates-and-source-files.html#the-crate_name-attribute>
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-2.rs b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-2.rs
index 13c9d1e0027..1ac1208ee44 100644
--- a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-2.rs
+++ b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-2.rs
@@ -4,4 +4,4 @@
 
 //@ compile-flags: --print=file-names
 #![crate_name = "this_one_is_okay"]
-#![crate_name = concat!("this_one_is_not")]  //~ ERROR malformed `crate_name` attribute input
+#![crate_name = concat!("this_one_is_not")] //~ ERROR attribute value must be a literal
diff --git a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-2.stderr b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-2.stderr
index e9a5b58e4f9..1571521ff17 100644
--- a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-2.stderr
+++ b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name-2.stderr
@@ -1,10 +1,8 @@
-error: malformed `crate_name` attribute input
-  --> $DIR/print-file-names-request-malformed-crate-name-2.rs:7:1
+error: attribute value must be a literal
+  --> $DIR/print-file-names-request-malformed-crate-name-2.rs:7:17
    |
 LL | #![crate_name = concat!("this_one_is_not")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_name = "name"]`
-   |
-   = note: for more information, visit <https://doc.rust-lang.org/reference/crates-and-source-files.html#the-crate_name-attribute>
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name.rs b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name.rs
index 5fe8bd7945f..6441017c665 100644
--- a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name.rs
+++ b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name.rs
@@ -2,4 +2,4 @@
 // See also <https://github.com/rust-lang/rust/issues/122001>.
 
 //@ compile-flags: --print=file-names
-#![crate_name = concat!("wrapped")]  //~ ERROR malformed `crate_name` attribute input
+#![crate_name = concat!("wrapped")] //~ ERROR attribute value must be a literal
diff --git a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name.stderr b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name.stderr
index e63525c6a5d..155e2e5a3fa 100644
--- a/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name.stderr
+++ b/tests/ui/invalid-compile-flags/print-file-names-request-malformed-crate-name.stderr
@@ -1,10 +1,8 @@
-error: malformed `crate_name` attribute input
-  --> $DIR/print-file-names-request-malformed-crate-name.rs:5:1
+error: attribute value must be a literal
+  --> $DIR/print-file-names-request-malformed-crate-name.rs:5:17
    |
 LL | #![crate_name = concat!("wrapped")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#![crate_name = "name"]`
-   |
-   = note: for more information, visit <https://doc.rust-lang.org/reference/crates-and-source-files.html#the-crate_name-attribute>
+   |                 ^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-17546.stderr b/tests/ui/issues/issue-17546.stderr
index 25a94dd9723..5bae738d3ec 100644
--- a/tests/ui/issues/issue-17546.stderr
+++ b/tests/ui/issues/issue-17546.stderr
@@ -3,10 +3,10 @@ error[E0573]: expected type, found variant `NoResult`
    |
 LL |     fn new() -> NoResult<MyEnum, String> {
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
   --> $SRC_DIR/core/src/result.rs:LL:COL
    |
    = note: similarly named enum `Result` defined here
-   |
 help: try using the variant's enum
    |
 LL -     fn new() -> NoResult<MyEnum, String> {
@@ -57,10 +57,10 @@ error[E0573]: expected type, found variant `NoResult`
    |
 LL | fn newer() -> NoResult<foo::MyEnum, String> {
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
   --> $SRC_DIR/core/src/result.rs:LL:COL
    |
    = note: similarly named enum `Result` defined here
-   |
 help: try using the variant's enum
    |
 LL - fn newer() -> NoResult<foo::MyEnum, String> {
diff --git a/tests/ui/issues/issue-27033.stderr b/tests/ui/issues/issue-27033.stderr
index 7a0ca888d74..129870f8c40 100644
--- a/tests/ui/issues/issue-27033.stderr
+++ b/tests/ui/issues/issue-27033.stderr
@@ -3,6 +3,7 @@ error[E0530]: match bindings cannot shadow unit variants
    |
 LL |         None @ _ => {}
    |         ^^^^ cannot be named the same as a unit variant
+   |
   --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
    |
    = note: the unit variant `None` is defined here
diff --git a/tests/ui/issues/issue-29466.rs b/tests/ui/issues/issue-29466.rs
index dbc37506a17..3962940e848 100644
--- a/tests/ui/issues/issue-29466.rs
+++ b/tests/ui/issues/issue-29466.rs
@@ -2,6 +2,9 @@
 //
 //@ run-pass
 
+// FIXME(#61117): Respect debuginfo-level-tests, do not force debuginfo-level=0
+//@ compile-flags: -Cdebuginfo=0
+
 #![allow(unused_variables)]
 
 macro_rules! m(
diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/example-from-issue48686.stderr b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/example-from-issue48686.stderr
index 5a7a5a6ebf9..2b7d6a6da27 100644
--- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/example-from-issue48686.stderr
+++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/example-from-issue48686.stderr
@@ -1,8 +1,8 @@
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/example-from-issue48686.rs:6:21
+  --> $DIR/example-from-issue48686.rs:6:50
    |
 LL |     pub fn get_mut(&'static self, x: &mut u8) -> &mut u8 {
-   |                     ^^^^^^^                      ------- the same lifetime is elided here
+   |                     -------                      ^^^^^^^ the same lifetime is elided here
    |                     |
    |                     the lifetime is named here
    |
diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/missing-lifetime-kind.stderr b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/missing-lifetime-kind.stderr
index af56a0a0ea5..c4d6e78d787 100644
--- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/missing-lifetime-kind.stderr
+++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/missing-lifetime-kind.stderr
@@ -1,8 +1,8 @@
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/missing-lifetime-kind.rs:3:22
+  --> $DIR/missing-lifetime-kind.rs:3:32
    |
 LL | fn ampersand<'a>(x: &'a u8) -> &u8 {
-   |                      ^^        --- the same lifetime is elided here
+   |                      --        ^^^ the same lifetime is elided here
    |                      |
    |                      the lifetime is named here
    |
@@ -18,10 +18,10 @@ LL | fn ampersand<'a>(x: &'a u8) -> &'a u8 {
    |                                 ++
 
 error: hiding a lifetime that's named elsewhere is confusing
-  --> $DIR/missing-lifetime-kind.rs:10:21
+  --> $DIR/missing-lifetime-kind.rs:10:31
    |
 LL | fn brackets<'a>(x: &'a u8) -> Brackets {
-   |                     ^^        -------- the same lifetime is hidden here
+   |                     --        ^^^^^^^^ the same lifetime is hidden here
    |                     |
    |                     the lifetime is named here
    |
@@ -32,10 +32,10 @@ LL | fn brackets<'a>(x: &'a u8) -> Brackets<'a> {
    |                                       ++++
 
 error: hiding a lifetime that's named elsewhere is confusing
-  --> $DIR/missing-lifetime-kind.rs:17:18
+  --> $DIR/missing-lifetime-kind.rs:17:28
    |
 LL | fn comma<'a>(x: &'a u8) -> Comma<u8> {
-   |                  ^^        --------- the same lifetime is hidden here
+   |                  --        ^^^^^^^^^ the same lifetime is hidden here
    |                  |
    |                  the lifetime is named here
    |
@@ -46,10 +46,10 @@ LL | fn comma<'a>(x: &'a u8) -> Comma<'a, u8> {
    |                                  +++
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/missing-lifetime-kind.rs:22:23
+  --> $DIR/missing-lifetime-kind.rs:22:34
    |
 LL | fn underscore<'a>(x: &'a u8) -> &'_ u8 {
-   |                       ^^         -- the same lifetime is elided here
+   |                       --         ^^ the same lifetime is elided here
    |                       |
    |                       the lifetime is named here
    |
diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/not-tied-to-crate.stderr b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/not-tied-to-crate.stderr
index cf0a29678fa..28de809faab 100644
--- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/not-tied-to-crate.stderr
+++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/not-tied-to-crate.stderr
@@ -1,8 +1,8 @@
 warning: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/not-tied-to-crate.rs:8:16
+  --> $DIR/not-tied-to-crate.rs:8:31
    |
 LL |     fn bar(x: &'static u8) -> &u8 {
-   |                ^^^^^^^        --- the same lifetime is elided here
+   |                -------        ^^^ the same lifetime is elided here
    |                |
    |                the lifetime is named here
    |
@@ -18,10 +18,10 @@ LL |     fn bar(x: &'static u8) -> &'static u8 {
    |                                +++++++
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/not-tied-to-crate.rs:14:16
+  --> $DIR/not-tied-to-crate.rs:14:31
    |
 LL |     fn baz(x: &'static u8) -> &u8 {
-   |                ^^^^^^^        --- the same lifetime is elided here
+   |                -------        ^^^ the same lifetime is elided here
    |                |
    |                the lifetime is named here
    |
diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/static.stderr b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/static.stderr
index d60bec6f7e4..5f21a2877a7 100644
--- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/static.stderr
+++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/static.stderr
@@ -1,8 +1,8 @@
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/static.rs:16:18
+  --> $DIR/static.rs:16:33
    |
 LL | fn ampersand(x: &'static u8) -> &u8 {
-   |                  ^^^^^^^        --- the same lifetime is elided here
+   |                  -------        ^^^ the same lifetime is elided here
    |                  |
    |                  the lifetime is named here
    |
@@ -18,10 +18,10 @@ LL | fn ampersand(x: &'static u8) -> &'static u8 {
    |                                  +++++++
 
 error: hiding a lifetime that's named elsewhere is confusing
-  --> $DIR/static.rs:23:17
+  --> $DIR/static.rs:23:32
    |
 LL | fn brackets(x: &'static u8) -> Brackets {
-   |                 ^^^^^^^        -------- the same lifetime is hidden here
+   |                 -------        ^^^^^^^^ the same lifetime is hidden here
    |                 |
    |                 the lifetime is named here
    |
@@ -32,10 +32,10 @@ LL | fn brackets(x: &'static u8) -> Brackets<'static> {
    |                                        +++++++++
 
 error: hiding a lifetime that's named elsewhere is confusing
-  --> $DIR/static.rs:30:14
+  --> $DIR/static.rs:30:29
    |
 LL | fn comma(x: &'static u8) -> Comma<u8> {
-   |              ^^^^^^^        --------- the same lifetime is hidden here
+   |              -------        ^^^^^^^^^ the same lifetime is hidden here
    |              |
    |              the lifetime is named here
    |
@@ -46,10 +46,10 @@ LL | fn comma(x: &'static u8) -> Comma<'static, u8> {
    |                                   ++++++++
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/static.rs:35:19
+  --> $DIR/static.rs:35:35
    |
 LL | fn underscore(x: &'static u8) -> &'_ u8 {
-   |                   ^^^^^^^         -- the same lifetime is elided here
+   |                   -------         ^^ the same lifetime is elided here
    |                   |
    |                   the lifetime is named here
    |
diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes.rs b/tests/ui/lifetimes/mismatched-lifetime-syntaxes.rs
index f6260c47202..f404c4163a9 100644
--- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes.rs
+++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes.rs
@@ -36,8 +36,8 @@ fn explicit_bound_path_to_implicit_path<'a>(v: ContainsLifetime<'a>) -> Contains
 
 fn explicit_bound_path_to_explicit_anonymous_path<'a>(
     v: ContainsLifetime<'a>,
-    //~^ ERROR eliding a lifetime that's named elsewhere is confusing
 ) -> ContainsLifetime<'_> {
+    //~^ ERROR eliding a lifetime that's named elsewhere is confusing
     v
 }
 
@@ -188,8 +188,8 @@ mod impl_trait {
 
     fn explicit_bound_path_to_impl_trait_precise_capture<'a>(
         v: ContainsLifetime<'a>,
-        //~^ ERROR eliding a lifetime that's named elsewhere is confusing
     ) -> impl FnOnce() + use<'_> {
+        //~^ ERROR eliding a lifetime that's named elsewhere is confusing
         move || _ = v
     }
 }
@@ -208,8 +208,8 @@ mod dyn_trait {
 
     fn explicit_bound_path_to_dyn_trait_bound<'a>(
         v: ContainsLifetime<'a>,
-        //~^ ERROR hiding a lifetime that's named elsewhere is confusing
     ) -> Box<dyn Iterator<Item = ContainsLifetime> + '_> {
+        //~^ ERROR hiding a lifetime that's named elsewhere is confusing
         Box::new(iter::once(v))
     }
 }
diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes.stderr b/tests/ui/lifetimes/mismatched-lifetime-syntaxes.stderr
index 20b7561c594..89768fc764a 100644
--- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes.stderr
+++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes.stderr
@@ -1,8 +1,8 @@
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:10:47
+  --> $DIR/mismatched-lifetime-syntaxes.rs:10:57
    |
 LL | fn explicit_bound_ref_to_implicit_ref<'a>(v: &'a u8) -> &u8 {
-   |                                               ^^        --- the same lifetime is elided here
+   |                                               --        ^^^ the same lifetime is elided here
    |                                               |
    |                                               the lifetime is named here
    |
@@ -18,10 +18,10 @@ LL | fn explicit_bound_ref_to_implicit_ref<'a>(v: &'a u8) -> &'a u8 {
    |                                                          ++
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:15:57
+  --> $DIR/mismatched-lifetime-syntaxes.rs:15:68
    |
 LL | fn explicit_bound_ref_to_explicit_anonymous_ref<'a>(v: &'a u8) -> &'_ u8 {
-   |                                                         ^^         -- the same lifetime is elided here
+   |                                                         --         ^^ the same lifetime is elided here
    |                                                         |
    |                                                         the lifetime is named here
    |
@@ -36,7 +36,7 @@ error: hiding a lifetime that's elided elsewhere is confusing
   --> $DIR/mismatched-lifetime-syntaxes.rs:22:48
    |
 LL | fn implicit_path_to_explicit_anonymous_path(v: ContainsLifetime) -> ContainsLifetime<'_> {
-   |                                                ^^^^^^^^^^^^^^^^                      -- the same lifetime is elided here
+   |                                                ^^^^^^^^^^^^^^^^                      ^^ the same lifetime is elided here
    |                                                |
    |                                                the lifetime is hidden here
    |
@@ -50,7 +50,7 @@ error: hiding a lifetime that's elided elsewhere is confusing
   --> $DIR/mismatched-lifetime-syntaxes.rs:27:65
    |
 LL | fn explicit_anonymous_path_to_implicit_path(v: ContainsLifetime<'_>) -> ContainsLifetime {
-   |                                                                 ^^      ---------------- the same lifetime is hidden here
+   |                                                                 ^^      ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
    |                                                                 |
    |                                                                 the lifetime is elided here
    |
@@ -61,10 +61,10 @@ LL | fn explicit_anonymous_path_to_implicit_path(v: ContainsLifetime<'_>) -> Con
    |                                                                                         ++++
 
 error: hiding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:32:65
+  --> $DIR/mismatched-lifetime-syntaxes.rs:32:73
    |
 LL | fn explicit_bound_path_to_implicit_path<'a>(v: ContainsLifetime<'a>) -> ContainsLifetime {
-   |                                                                 ^^      ---------------- the same lifetime is hidden here
+   |                                                                 --      ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
    |                                                                 |
    |                                                                 the lifetime is named here
    |
@@ -75,13 +75,12 @@ LL | fn explicit_bound_path_to_implicit_path<'a>(v: ContainsLifetime<'a>) -> Con
    |                                                                                         ++++
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:38:25
+  --> $DIR/mismatched-lifetime-syntaxes.rs:39:23
    |
 LL |     v: ContainsLifetime<'a>,
-   |                         ^^ the lifetime is named here
-LL |
+   |                         -- the lifetime is named here
 LL | ) -> ContainsLifetime<'_> {
-   |                       -- the same lifetime is elided here
+   |                       ^^ the same lifetime is elided here
    |
    = help: the same lifetime is referred to in inconsistent ways, making the signature confusing
 help: consistently use `'a`
@@ -94,7 +93,7 @@ error: hiding a lifetime that's elided elsewhere is confusing
   --> $DIR/mismatched-lifetime-syntaxes.rs:46:37
    |
 LL | fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime {
-   |                                     ^^^     ---------------- the same lifetime is hidden here
+   |                                     ^^^     ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
    |                                     |
    |                                     the lifetime is elided here
    |
@@ -108,7 +107,7 @@ error: hiding a lifetime that's elided elsewhere is confusing
   --> $DIR/mismatched-lifetime-syntaxes.rs:51:48
    |
 LL | fn explicit_anonymous_ref_to_implicit_path(v: &'_ u8) -> ContainsLifetime {
-   |                                                ^^        ---------------- the same lifetime is hidden here
+   |                                                ^^        ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
    |                                                |
    |                                                the lifetime is elided here
    |
@@ -119,10 +118,10 @@ LL | fn explicit_anonymous_ref_to_implicit_path(v: &'_ u8) -> ContainsLifetime<'
    |                                                                          ++++
 
 error: hiding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:56:48
+  --> $DIR/mismatched-lifetime-syntaxes.rs:56:58
    |
 LL | fn explicit_bound_ref_to_implicit_path<'a>(v: &'a u8) -> ContainsLifetime {
-   |                                                ^^        ---------------- the same lifetime is hidden here
+   |                                                --        ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
    |                                                |
    |                                                the lifetime is named here
    |
@@ -133,10 +132,10 @@ LL | fn explicit_bound_ref_to_implicit_path<'a>(v: &'a u8) -> ContainsLifetime<'
    |                                                                          ++++
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:61:58
+  --> $DIR/mismatched-lifetime-syntaxes.rs:61:85
    |
 LL | fn explicit_bound_ref_to_explicit_anonymous_path<'a>(v: &'a u8) -> ContainsLifetime<'_> {
-   |                                                          ^^                         -- the same lifetime is elided here
+   |                                                          --                         ^^ the same lifetime is elided here
    |                                                          |
    |                                                          the lifetime is named here
    |
@@ -151,7 +150,7 @@ error: hiding a lifetime that's elided elsewhere is confusing
   --> $DIR/mismatched-lifetime-syntaxes.rs:68:37
    |
 LL | fn implicit_path_to_implicit_ref(v: ContainsLifetime) -> &u8 {
-   |                                     ^^^^^^^^^^^^^^^^     --- the same lifetime is elided here
+   |                                     ^^^^^^^^^^^^^^^^     ^^^ the same lifetime is elided here
    |                                     |
    |                                     the lifetime is hidden here
    |
@@ -165,7 +164,7 @@ error: hiding a lifetime that's elided elsewhere is confusing
   --> $DIR/mismatched-lifetime-syntaxes.rs:73:47
    |
 LL | fn implicit_path_to_explicit_anonymous_ref(v: ContainsLifetime) -> &'_ u8 {
-   |                                               ^^^^^^^^^^^^^^^^      -- the same lifetime is elided here
+   |                                               ^^^^^^^^^^^^^^^^      ^^ the same lifetime is elided here
    |                                               |
    |                                               the lifetime is hidden here
    |
@@ -176,10 +175,10 @@ LL | fn implicit_path_to_explicit_anonymous_ref(v: ContainsLifetime<'_>) -> &'_
    |                                                               ++++
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:78:64
+  --> $DIR/mismatched-lifetime-syntaxes.rs:78:72
    |
 LL | fn explicit_bound_path_to_implicit_ref<'a>(v: ContainsLifetime<'a>) -> &u8 {
-   |                                                                ^^      --- the same lifetime is elided here
+   |                                                                --      ^^^ the same lifetime is elided here
    |                                                                |
    |                                                                the lifetime is named here
    |
@@ -190,10 +189,10 @@ LL | fn explicit_bound_path_to_implicit_ref<'a>(v: ContainsLifetime<'a>) -> &'a
    |                                                                         ++
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:83:74
+  --> $DIR/mismatched-lifetime-syntaxes.rs:83:83
    |
 LL | fn explicit_bound_path_to_explicit_anonymous_ref<'a>(v: ContainsLifetime<'a>) -> &'_ u8 {
-   |                                                                          ^^       -- the same lifetime is elided here
+   |                                                                          --       ^^ the same lifetime is elided here
    |                                                                          |
    |                                                                          the lifetime is named here
    |
@@ -205,10 +204,10 @@ LL + fn explicit_bound_path_to_explicit_anonymous_ref<'a>(v: ContainsLifetime<'a
    |
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:89:55
+  --> $DIR/mismatched-lifetime-syntaxes.rs:89:67
    |
 LL |     fn method_explicit_bound_ref_to_implicit_ref<'a>(&'a self) -> &u8 {
-   |                                                       ^^          --- the same lifetime is elided here
+   |                                                       --          ^^^ the same lifetime is elided here
    |                                                       |
    |                                                       the lifetime is named here
    |
@@ -219,10 +218,10 @@ LL |     fn method_explicit_bound_ref_to_implicit_ref<'a>(&'a self) -> &'a u8 {
    |                                                                    ++
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:94:65
+  --> $DIR/mismatched-lifetime-syntaxes.rs:94:78
    |
 LL |     fn method_explicit_bound_ref_to_explicit_anonymous_ref<'a>(&'a self) -> &'_ u8 {
-   |                                                                 ^^           -- the same lifetime is elided here
+   |                                                                 --           ^^ the same lifetime is elided here
    |                                                                 |
    |                                                                 the lifetime is named here
    |
@@ -237,7 +236,7 @@ error: hiding a lifetime that's elided elsewhere is confusing
   --> $DIR/mismatched-lifetime-syntaxes.rs:101:56
    |
 LL |     fn method_explicit_anonymous_ref_to_implicit_path(&'_ self) -> ContainsLifetime {
-   |                                                        ^^          ---------------- the same lifetime is hidden here
+   |                                                        ^^          ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
    |                                                        |
    |                                                        the lifetime is elided here
    |
@@ -248,10 +247,10 @@ LL |     fn method_explicit_anonymous_ref_to_implicit_path(&'_ self) -> Contains
    |                                                                                    ++++
 
 error: hiding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:106:56
+  --> $DIR/mismatched-lifetime-syntaxes.rs:106:68
    |
 LL |     fn method_explicit_bound_ref_to_implicit_path<'a>(&'a self) -> ContainsLifetime {
-   |                                                        ^^          ---------------- the same lifetime is hidden here
+   |                                                        --          ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
    |                                                        |
    |                                                        the lifetime is named here
    |
@@ -262,10 +261,10 @@ LL |     fn method_explicit_bound_ref_to_implicit_path<'a>(&'a self) -> Contains
    |                                                                                    ++++
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:111:66
+  --> $DIR/mismatched-lifetime-syntaxes.rs:111:95
    |
 LL |     fn method_explicit_bound_ref_to_explicit_anonymous_path<'a>(&'a self) -> ContainsLifetime<'_> {
-   |                                                                  ^^                           -- the same lifetime is elided here
+   |                                                                  --                           ^^ the same lifetime is elided here
    |                                                                  |
    |                                                                  the lifetime is named here
    |
@@ -277,10 +276,10 @@ LL +     fn method_explicit_bound_ref_to_explicit_anonymous_path<'a>(&'a self) -
    |
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:126:39
+  --> $DIR/mismatched-lifetime-syntaxes.rs:126:54
    |
 LL |     fn static_ref_to_implicit_ref(v: &'static u8) -> &u8 {
-   |                                       ^^^^^^^        --- the same lifetime is elided here
+   |                                       -------        ^^^ the same lifetime is elided here
    |                                       |
    |                                       the lifetime is named here
    |
@@ -291,10 +290,10 @@ LL |     fn static_ref_to_implicit_ref(v: &'static u8) -> &'static u8 {
    |                                                       +++++++
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:131:49
+  --> $DIR/mismatched-lifetime-syntaxes.rs:131:65
    |
 LL |     fn static_ref_to_explicit_anonymous_ref(v: &'static u8) -> &'_ u8 {
-   |                                                 ^^^^^^^         -- the same lifetime is elided here
+   |                                                 -------         ^^ the same lifetime is elided here
    |                                                 |
    |                                                 the lifetime is named here
    |
@@ -306,10 +305,10 @@ LL +     fn static_ref_to_explicit_anonymous_ref(v: &'static u8) -> &'static u8
    |
 
 error: hiding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:136:40
+  --> $DIR/mismatched-lifetime-syntaxes.rs:136:55
    |
 LL |     fn static_ref_to_implicit_path(v: &'static u8) -> ContainsLifetime {
-   |                                        ^^^^^^^        ---------------- the same lifetime is hidden here
+   |                                        -------        ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
    |                                        |
    |                                        the lifetime is named here
    |
@@ -320,10 +319,10 @@ LL |     fn static_ref_to_implicit_path(v: &'static u8) -> ContainsLifetime<'sta
    |                                                                       +++++++++
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:141:50
+  --> $DIR/mismatched-lifetime-syntaxes.rs:141:82
    |
 LL |     fn static_ref_to_explicit_anonymous_path(v: &'static u8) -> ContainsLifetime<'_> {
-   |                                                  ^^^^^^^                         -- the same lifetime is elided here
+   |                                                  -------                         ^^ the same lifetime is elided here
    |                                                  |
    |                                                  the lifetime is named here
    |
@@ -335,10 +334,10 @@ LL +     fn static_ref_to_explicit_anonymous_path(v: &'static u8) -> ContainsLif
    |
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:147:40
+  --> $DIR/mismatched-lifetime-syntaxes.rs:147:57
    |
 LL |         fn static_ref_to_implicit_ref(&'static self) -> &u8 {
-   |                                        ^^^^^^^          --- the same lifetime is elided here
+   |                                        -------          ^^^ the same lifetime is elided here
    |                                        |
    |                                        the lifetime is named here
    |
@@ -349,10 +348,10 @@ LL |         fn static_ref_to_implicit_ref(&'static self) -> &'static u8 {
    |                                                          +++++++
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:152:50
+  --> $DIR/mismatched-lifetime-syntaxes.rs:152:68
    |
 LL |         fn static_ref_to_explicit_anonymous_ref(&'static self) -> &'_ u8 {
-   |                                                  ^^^^^^^           -- the same lifetime is elided here
+   |                                                  -------           ^^ the same lifetime is elided here
    |                                                  |
    |                                                  the lifetime is named here
    |
@@ -364,10 +363,10 @@ LL +         fn static_ref_to_explicit_anonymous_ref(&'static self) -> &'static
    |
 
 error: hiding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:157:41
+  --> $DIR/mismatched-lifetime-syntaxes.rs:157:58
    |
 LL |         fn static_ref_to_implicit_path(&'static self) -> ContainsLifetime {
-   |                                         ^^^^^^^          ---------------- the same lifetime is hidden here
+   |                                         -------          ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
    |                                         |
    |                                         the lifetime is named here
    |
@@ -378,10 +377,10 @@ LL |         fn static_ref_to_implicit_path(&'static self) -> ContainsLifetime<'
    |                                                                          +++++++++
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:162:51
+  --> $DIR/mismatched-lifetime-syntaxes.rs:162:85
    |
 LL |         fn static_ref_to_explicit_anonymous_path(&'static self) -> ContainsLifetime<'_> {
-   |                                                   ^^^^^^^                           -- the same lifetime is elided here
+   |                                                   -------                           ^^ the same lifetime is elided here
    |                                                   |
    |                                                   the lifetime is named here
    |
@@ -393,10 +392,10 @@ LL +         fn static_ref_to_explicit_anonymous_path(&'static self) -> Contains
    |
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:174:55
+  --> $DIR/mismatched-lifetime-syntaxes.rs:174:81
    |
 LL |     fn explicit_bound_ref_to_impl_trait_bound<'a>(v: &'a u8) -> impl FnOnce() + '_ {
-   |                                                       ^^                        -- the same lifetime is elided here
+   |                                                       --                        ^^ the same lifetime is elided here
    |                                                       |
    |                                                       the lifetime is named here
    |
@@ -408,10 +407,10 @@ LL +     fn explicit_bound_ref_to_impl_trait_bound<'a>(v: &'a u8) -> impl FnOnce
    |
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:179:65
+  --> $DIR/mismatched-lifetime-syntaxes.rs:179:95
    |
 LL |     fn explicit_bound_ref_to_impl_trait_precise_capture<'a>(v: &'a u8) -> impl FnOnce() + use<'_> {
-   |                                                                 ^^ the lifetime is named here -- the same lifetime is elided here
+   |                                                                 -- the lifetime is named here ^^ the same lifetime is elided here
    |
    = help: the same lifetime is referred to in inconsistent ways, making the signature confusing
 help: consistently use `'a`
@@ -421,10 +420,10 @@ LL +     fn explicit_bound_ref_to_impl_trait_precise_capture<'a>(v: &'a u8) -> i
    |
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:184:72
+  --> $DIR/mismatched-lifetime-syntaxes.rs:184:96
    |
 LL |     fn explicit_bound_path_to_impl_trait_bound<'a>(v: ContainsLifetime<'a>) -> impl FnOnce() + '_ {
-   |                                                                        ^^                      -- the same lifetime is elided here
+   |                                                                        --                      ^^ the same lifetime is elided here
    |                                                                        |
    |                                                                        the lifetime is named here
    |
@@ -436,13 +435,12 @@ LL +     fn explicit_bound_path_to_impl_trait_bound<'a>(v: ContainsLifetime<'a>)
    |
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:190:29
+  --> $DIR/mismatched-lifetime-syntaxes.rs:191:30
    |
 LL |         v: ContainsLifetime<'a>,
-   |                             ^^ the lifetime is named here
-LL |
+   |                             -- the lifetime is named here
 LL |     ) -> impl FnOnce() + use<'_> {
-   |                              -- the same lifetime is elided here
+   |                              ^^ the same lifetime is elided here
    |
    = help: the same lifetime is referred to in inconsistent ways, making the signature confusing
 help: consistently use `'a`
@@ -452,10 +450,10 @@ LL +     ) -> impl FnOnce() + use<'a> {
    |
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:204:54
+  --> $DIR/mismatched-lifetime-syntaxes.rs:204:88
    |
 LL |     fn explicit_bound_ref_to_dyn_trait_bound<'a>(v: &'a u8) -> Box<dyn Iterator<Item = &u8> + '_> {
-   |                                                      ^^ the lifetime is named here     --- the same lifetime is elided here
+   |                                                      -- the lifetime is named here     ^^^ the same lifetime is elided here
    |
    = help: the same lifetime is referred to in inconsistent ways, making the signature confusing
 help: consistently use `'a`
@@ -464,13 +462,12 @@ LL |     fn explicit_bound_ref_to_dyn_trait_bound<'a>(v: &'a u8) -> Box<dyn Iter
    |                                                                                         ++
 
 error: hiding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:210:29
+  --> $DIR/mismatched-lifetime-syntaxes.rs:211:34
    |
 LL |         v: ContainsLifetime<'a>,
-   |                             ^^ the lifetime is named here
-LL |
+   |                             -- the lifetime is named here
 LL |     ) -> Box<dyn Iterator<Item = ContainsLifetime> + '_> {
-   |                                  ---------------- the same lifetime is hidden here
+   |                                  ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
    |
    = help: the same lifetime is referred to in inconsistent ways, making the signature confusing
 help: consistently use `'a`
@@ -479,10 +476,10 @@ LL |     ) -> Box<dyn Iterator<Item = ContainsLifetime<'a>> + '_> {
    |                                                  ++++
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:222:33
+  --> $DIR/mismatched-lifetime-syntaxes.rs:222:52
    |
 LL |     fn multiple_inputs<'a>(v: (&'a u8, &'a u8)) -> &u8 {
-   |                                 ^^      ^^         --- the same lifetime is elided here
+   |                                 --      --         ^^^ the same lifetime is elided here
    |                                 |       |
    |                                 |       the lifetime is named here
    |                                 the lifetime is named here
@@ -494,10 +491,10 @@ LL |     fn multiple_inputs<'a>(v: (&'a u8, &'a u8)) -> &'a u8 {
    |                                                     ++
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:227:33
+  --> $DIR/mismatched-lifetime-syntaxes.rs:227:44
    |
 LL |     fn multiple_outputs<'a>(v: &'a u8) -> (&u8, &u8) {
-   |                                 ^^         ---  --- the same lifetime is elided here
+   |                                 --         ^^^  ^^^ the same lifetime is elided here
    |                                 |          |
    |                                 |          the same lifetime is elided here
    |                                 the lifetime is named here
@@ -509,10 +506,10 @@ LL |     fn multiple_outputs<'a>(v: &'a u8) -> (&'a u8, &'a u8) {
    |                                             ++      ++
 
 error: hiding or eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:232:53
+  --> $DIR/mismatched-lifetime-syntaxes.rs:232:62
    |
 LL |     fn all_three_categories<'a>(v: ContainsLifetime<'a>) -> (&u8, ContainsLifetime) {
-   |                                                     ^^       ---  ---------------- the same lifetime is hidden here
+   |                                                     --       ^^^  ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
    |                                                     |        |
    |                                                     |        the same lifetime is elided here
    |                                                     the lifetime is named here
@@ -524,10 +521,10 @@ LL |     fn all_three_categories<'a>(v: ContainsLifetime<'a>) -> (&'a u8, Contai
    |                                                               ++                     ++++
 
 error: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/mismatched-lifetime-syntaxes.rs:237:38
+  --> $DIR/mismatched-lifetime-syntaxes.rs:237:49
    |
 LL |     fn explicit_bound_output<'a>(v: &'a u8) -> (&u8, &'a u8, ContainsLifetime<'a>) {
-   |                                      ^^         ---   --                      -- the same lifetime is named here
+   |                                      --         ^^^   --                      -- the same lifetime is named here
    |                                      |          |     |
    |                                      |          |     the same lifetime is named here
    |                                      |          the same lifetime is elided here
@@ -543,7 +540,7 @@ error: hiding a lifetime that's elided elsewhere is confusing
   --> $DIR/mismatched-lifetime-syntaxes.rs:250:45
    |
 LL |         fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime;
-   |                                             ^^^     ---------------- the same lifetime is hidden here
+   |                                             ^^^     ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
    |                                             |
    |                                             the lifetime is elided here
    |
@@ -557,7 +554,7 @@ error: hiding a lifetime that's elided elsewhere is confusing
   --> $DIR/mismatched-lifetime-syntaxes.rs:253:49
    |
 LL |         fn method_implicit_ref_to_implicit_path(&self) -> ContainsLifetime;
-   |                                                 ^^^^^     ---------------- the same lifetime is hidden here
+   |                                                 ^^^^^     ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
    |                                                 |
    |                                                 the lifetime is elided here
    |
@@ -571,7 +568,7 @@ error: hiding a lifetime that's elided elsewhere is confusing
   --> $DIR/mismatched-lifetime-syntaxes.rs:258:45
    |
 LL |         fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime {
-   |                                             ^^^     ---------------- the same lifetime is hidden here
+   |                                             ^^^     ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
    |                                             |
    |                                             the lifetime is elided here
    |
@@ -585,7 +582,7 @@ error: hiding a lifetime that's elided elsewhere is confusing
   --> $DIR/mismatched-lifetime-syntaxes.rs:263:49
    |
 LL |         fn method_implicit_ref_to_implicit_path(&self) -> ContainsLifetime {
-   |                                                 ^^^^^     ---------------- the same lifetime is hidden here
+   |                                                 ^^^^^     ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
    |                                                 |
    |                                                 the lifetime is elided here
    |
@@ -599,7 +596,7 @@ error: hiding a lifetime that's elided elsewhere is confusing
   --> $DIR/mismatched-lifetime-syntaxes.rs:277:45
    |
 LL |         fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime;
-   |                                             ^^^     ---------------- the same lifetime is hidden here
+   |                                             ^^^     ^^^^^^^^^^^^^^^^ the same lifetime is hidden here
    |                                             |
    |                                             the lifetime is elided here
    |
diff --git a/tests/ui/limits/huge-enum.rs b/tests/ui/limits/huge-enum.rs
index 66c5be20693..6d5b86411f3 100644
--- a/tests/ui/limits/huge-enum.rs
+++ b/tests/ui/limits/huge-enum.rs
@@ -2,6 +2,9 @@
 //@ normalize-stderr: "std::option::Option<\[u32; \d+\]>" -> "TYPE"
 //@ normalize-stderr: "\[u32; \d+\]" -> "TYPE"
 
+// FIXME(#61117): Respect debuginfo-level-tests, do not force debuginfo-level=0
+//@ compile-flags: -Cdebuginfo=0
+
 #[cfg(target_pointer_width = "32")]
 type BIG = Option<[u32; (1<<29)-1]>;
 
diff --git a/tests/ui/limits/huge-enum.stderr b/tests/ui/limits/huge-enum.stderr
index 18168b3fa5c..5b97a2104a3 100644
--- a/tests/ui/limits/huge-enum.stderr
+++ b/tests/ui/limits/huge-enum.stderr
@@ -1,5 +1,5 @@
 error: values of the type `Option<TYPE>` are too big for the target architecture
-  --> $DIR/huge-enum.rs:12:9
+  --> $DIR/huge-enum.rs:15:9
    |
 LL |     let big: BIG = None;
    |         ^^^
diff --git a/tests/ui/link-native-libs/issue-43925.rs b/tests/ui/link-native-libs/issue-43925.rs
index 1a210887154..e3ce71352c0 100644
--- a/tests/ui/link-native-libs/issue-43925.rs
+++ b/tests/ui/link-native-libs/issue-43925.rs
@@ -1,4 +1,6 @@
-#[link(name = "foo", cfg("rlib"))] //~ ERROR link cfg must have a single predicate argument
+#[link(name = "foo", cfg("rlib"))]
+//~^ ERROR link cfg is unstable
+//~| ERROR `cfg` predicate key must be an identifier
 extern "C" {}
 
 fn main() {}
diff --git a/tests/ui/link-native-libs/issue-43925.stderr b/tests/ui/link-native-libs/issue-43925.stderr
index 7cc347c6163..82d204222df 100644
--- a/tests/ui/link-native-libs/issue-43925.stderr
+++ b/tests/ui/link-native-libs/issue-43925.stderr
@@ -1,8 +1,18 @@
-error: link cfg must have a single predicate argument
+error[E0658]: link cfg is unstable
   --> $DIR/issue-43925.rs:1:22
    |
 LL | #[link(name = "foo", cfg("rlib"))]
    |                      ^^^^^^^^^^^
+   |
+   = help: add `#![feature(link_cfg)]` 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: `cfg` predicate key must be an identifier
+  --> $DIR/issue-43925.rs:1:26
+   |
+LL | #[link(name = "foo", cfg("rlib"))]
+   |                          ^^^^^^
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/link-native-libs/issue-43926.rs b/tests/ui/link-native-libs/issue-43926.rs
index 6d3003552dc..293ad3f4ec1 100644
--- a/tests/ui/link-native-libs/issue-43926.rs
+++ b/tests/ui/link-native-libs/issue-43926.rs
@@ -1,4 +1,4 @@
-#[link(name = "foo", cfg())] //~ ERROR link cfg must have a single predicate argument
+#[link(name = "foo", cfg())] //~ ERROR malformed `link` attribute input
 extern "C" {}
 
 fn main() {}
diff --git a/tests/ui/link-native-libs/issue-43926.stderr b/tests/ui/link-native-libs/issue-43926.stderr
index 7c5c50a38a9..9e3ec21cc94 100644
--- a/tests/ui/link-native-libs/issue-43926.stderr
+++ b/tests/ui/link-native-libs/issue-43926.stderr
@@ -1,8 +1,28 @@
-error: link cfg must have a single predicate argument
-  --> $DIR/issue-43926.rs:1:22
+error[E0805]: malformed `link` attribute input
+  --> $DIR/issue-43926.rs:1:1
    |
 LL | #[link(name = "foo", cfg())]
-   |                      ^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^-----^^
+   |                      |
+   |                      expected a single argument here
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(name = "foo", cfg())]
+LL + #[link(name = "...")]
+   |
+LL - #[link(name = "foo", cfg())]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link(name = "foo", cfg())]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link(name = "foo", cfg())]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0805`.
diff --git a/tests/ui/link-native-libs/link-attr-validation-early.rs b/tests/ui/link-native-libs/link-attr-validation-early.rs
index a7dd80f8920..89a34ac6ca1 100644
--- a/tests/ui/link-native-libs/link-attr-validation-early.rs
+++ b/tests/ui/link-native-libs/link-attr-validation-early.rs
@@ -1,8 +1,6 @@
 // Top-level ill-formed
-#[link] //~ ERROR valid forms for the attribute are
-        //~| WARN this was previously accepted
-#[link = "foo"] //~ ERROR valid forms for the attribute are
-                //~| WARN this was previously accepted
+#[link] //~ ERROR malformed
+#[link = "foo"] //~ ERROR malformed
 extern "C" {}
 
 fn main() {}
diff --git a/tests/ui/link-native-libs/link-attr-validation-early.stderr b/tests/ui/link-native-libs/link-attr-validation-early.stderr
index d4fc2e272f8..e4799b1a161 100644
--- a/tests/ui/link-native-libs/link-attr-validation-early.stderr
+++ b/tests/ui/link-native-libs/link-attr-validation-early.stderr
@@ -1,47 +1,45 @@
-error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`
+error[E0539]: malformed `link` attribute input
   --> $DIR/link-attr-validation-early.rs:2:1
    |
 LL | #[link]
-   | ^^^^^^^
+   | ^^^^^^^ expected this to be a list
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
    = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
-   = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL | #[link(name = "...")]
+   |       ++++++++++++++
+LL | #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |       +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+LL | #[link(name = "...", kind = "dylib|static|...")]
+   |       +++++++++++++++++++++++++++++++++++++++++
+LL | #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |       ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+   = and 1 other candidate
 
-error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`
-  --> $DIR/link-attr-validation-early.rs:4:1
+error[E0539]: malformed `link` attribute input
+  --> $DIR/link-attr-validation-early.rs:3:1
    |
 LL | #[link = "foo"]
-   | ^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^ expected this to be a list
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
    = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
-
-error: aborting due to 2 previous errors
-
-Future incompatibility report: Future breakage diagnostic:
-error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`
-  --> $DIR/link-attr-validation-early.rs:2:1
+help: try changing it to one of the following valid forms of the attribute
    |
-LL | #[link]
-   | ^^^^^^^
+LL - #[link = "foo"]
+LL + #[link(name = "...")]
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
-   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
-   = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default
-
-Future breakage diagnostic:
-error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`
-  --> $DIR/link-attr-validation-early.rs:4:1
+LL - #[link = "foo"]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
    |
-LL | #[link = "foo"]
-   | ^^^^^^^^^^^^^^^
+LL - #[link = "foo"]
+LL + #[link(name = "...", kind = "dylib|static|...")]
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
-   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
-   = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default
+LL - #[link = "foo"]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
+
+error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/link-native-libs/link-attr-validation-late.rs b/tests/ui/link-native-libs/link-attr-validation-late.rs
index 4eeb8ba4884..d2947b5f61a 100644
--- a/tests/ui/link-native-libs/link-attr-validation-late.rs
+++ b/tests/ui/link-native-libs/link-attr-validation-late.rs
@@ -1,38 +1,36 @@
 #![feature(link_cfg)]
 
 // Top-level ill-formed
-#[link(name = "...", "literal")] //~ ERROR unexpected `#[link]` argument
-#[link(name = "...", unknown)] //~ ERROR unexpected `#[link]` argument
+#[link(name = "...", "literal")] //~ ERROR malformed `link` attribute input
+#[link(name = "...", unknown)] //~ ERROR malformed `link` attribute input
 extern "C" {}
 
 // Duplicate arguments
-#[link(name = "foo", name = "bar")] //~ ERROR multiple `name` arguments
-#[link(name = "...", kind = "dylib", kind = "bar")] //~ ERROR multiple `kind` arguments
-#[link(name = "...", modifiers = "+verbatim", modifiers = "bar")] //~ ERROR multiple `modifiers` arguments
-#[link(name = "...", cfg(false), cfg(false))] //~ ERROR multiple `cfg` arguments
-#[link(wasm_import_module = "foo", wasm_import_module = "bar")] //~ ERROR multiple `wasm_import_module` arguments
+#[link(name = "foo", name = "bar")] //~ ERROR malformed `link` attribute input
+#[link(name = "...", kind = "dylib", kind = "bar")] //~ ERROR malformed `link` attribute input
+#[link(name = "...", modifiers = "+verbatim", modifiers = "bar")] //~ ERROR malformed `link` attribute input
+#[link(name = "...", cfg(false), cfg(false))] //~ ERROR malformed `link` attribute input
+#[link(wasm_import_module = "foo", wasm_import_module = "bar")] //~ ERROR malformed `link` attribute input
 extern "C" {}
 
 // Ill-formed arguments
-#[link(name)] //~ ERROR link name must be of the form `name = "string"`
-              //~| ERROR `#[link]` attribute requires a `name = "string"` argument
-#[link(name())] //~ ERROR link name must be of the form `name = "string"`
-              //~| ERROR `#[link]` attribute requires a `name = "string"` argument
-#[link(name = "...", kind)] //~ ERROR link kind must be of the form `kind = "string"`
-#[link(name = "...", kind())] //~ ERROR link kind must be of the form `kind = "string"`
-#[link(name = "...", modifiers)] //~ ERROR link modifiers must be of the form `modifiers = "string"`
-#[link(name = "...", modifiers())] //~ ERROR link modifiers must be of the form `modifiers = "string"`
-#[link(name = "...", cfg)] //~ ERROR link cfg must be of the form `cfg(/* predicate */)`
-#[link(name = "...", cfg = "literal")] //~ ERROR link cfg must be of the form `cfg(/* predicate */)`
-#[link(name = "...", cfg("literal"))] //~ ERROR link cfg must have a single predicate argument
-#[link(name = "...", wasm_import_module)] //~ ERROR wasm import module must be of the form `wasm_import_module = "string"`
-#[link(name = "...", wasm_import_module())] //~ ERROR wasm import module must be of the form `wasm_import_module = "string"`
+#[link(name)] //~ ERROR malformed `link` attribute input
+#[link(name())] //~ ERROR malformed `link` attribute input
+#[link(name = "...", kind)] //~ ERROR malformed `link` attribute input
+#[link(name = "...", kind())] //~ ERROR malformed `link` attribute input
+#[link(name = "...", modifiers)] //~ ERROR malformed `link` attribute input
+#[link(name = "...", modifiers())] //~ ERROR malformed `link` attribute input
+#[link(name = "...", cfg)] //~ ERROR malformed `link` attribute input
+#[link(name = "...", cfg = "literal")] //~ ERROR malformed `link` attribute input
+#[link(name = "...", cfg("literal"))] //~ ERROR `cfg` predicate key must be an identifier
+#[link(name = "...", wasm_import_module)] //~ ERROR malformed `link` attribute input
+#[link(name = "...", wasm_import_module())] //~ ERROR malformed `link` attribute input
 extern "C" {}
 
 // Basic modifier validation
 #[link(name = "...", modifiers = "")] //~ ERROR invalid linking modifier syntax, expected '+' or '-' prefix
 #[link(name = "...", modifiers = "no-plus-minus")] //~ ERROR invalid linking modifier syntax, expected '+' or '-' prefix
-#[link(name = "...", modifiers = "+unknown")] //~ ERROR unknown linking modifier `unknown`
+#[link(name = "...", modifiers = "+unknown")] //~ ERROR malformed `link` attribute input
 #[link(name = "...", modifiers = "+verbatim,+verbatim")] //~ ERROR multiple `verbatim` modifiers
 extern "C" {}
 
diff --git a/tests/ui/link-native-libs/link-attr-validation-late.stderr b/tests/ui/link-native-libs/link-attr-validation-late.stderr
index f3989c09360..834dca0bc0b 100644
--- a/tests/ui/link-native-libs/link-attr-validation-late.stderr
+++ b/tests/ui/link-native-libs/link-attr-validation-late.stderr
@@ -1,147 +1,472 @@
-error: unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type
-  --> $DIR/link-attr-validation-late.rs:4:22
+error[E0565]: malformed `link` attribute input
+  --> $DIR/link-attr-validation-late.rs:4:1
    |
 LL | #[link(name = "...", "literal")]
-   |                      ^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^---------^^
+   |                      |
+   |                      didn't expect a literal here
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(name = "...", "literal")]
+LL + #[link(name = "...")]
+   |
+LL - #[link(name = "...", "literal")]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link(name = "...", "literal")]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link(name = "...", "literal")]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
 
-error: unexpected `#[link]` argument, expected one of: name, kind, modifiers, cfg, wasm_import_module, import_name_type
-  --> $DIR/link-attr-validation-late.rs:5:22
+error[E0539]: malformed `link` attribute input
+  --> $DIR/link-attr-validation-late.rs:5:1
    |
 LL | #[link(name = "...", unknown)]
-   |                      ^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^-------^^
+   |                      |
+   |                      valid arguments are "name", "kind", "modifiers", "cfg", "wasm_import_module" or "import_name_type"
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(name = "...", unknown)]
+LL + #[link(name = "...")]
+   |
+LL - #[link(name = "...", unknown)]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link(name = "...", unknown)]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link(name = "...", unknown)]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
 
-error: multiple `name` arguments in a single `#[link]` attribute
-  --> $DIR/link-attr-validation-late.rs:9:22
+error[E0538]: malformed `link` attribute input
+  --> $DIR/link-attr-validation-late.rs:9:1
    |
 LL | #[link(name = "foo", name = "bar")]
-   |                      ^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^------------^^
+   |                      |
+   |                      found `name` used as a key more than once
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(name = "foo", name = "bar")]
+LL + #[link(name = "...")]
+   |
+LL - #[link(name = "foo", name = "bar")]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link(name = "foo", name = "bar")]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link(name = "foo", name = "bar")]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
 
-error: multiple `kind` arguments in a single `#[link]` attribute
-  --> $DIR/link-attr-validation-late.rs:10:38
+error[E0538]: malformed `link` attribute input
+  --> $DIR/link-attr-validation-late.rs:10:1
    |
 LL | #[link(name = "...", kind = "dylib", kind = "bar")]
-   |                                      ^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------^^
+   |                                      |
+   |                                      found `kind` used as a key more than once
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(name = "...", kind = "dylib", kind = "bar")]
+LL + #[link(name = "...")]
+   |
+LL - #[link(name = "...", kind = "dylib", kind = "bar")]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link(name = "...", kind = "dylib", kind = "bar")]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link(name = "...", kind = "dylib", kind = "bar")]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
 
-error: multiple `modifiers` arguments in a single `#[link]` attribute
-  --> $DIR/link-attr-validation-late.rs:11:47
+error[E0538]: malformed `link` attribute input
+  --> $DIR/link-attr-validation-late.rs:11:1
    |
 LL | #[link(name = "...", modifiers = "+verbatim", modifiers = "bar")]
-   |                                               ^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------^^
+   |                                               |
+   |                                               found `modifiers` used as a key more than once
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(name = "...", modifiers = "+verbatim", modifiers = "bar")]
+LL + #[link(name = "...")]
+   |
+LL - #[link(name = "...", modifiers = "+verbatim", modifiers = "bar")]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link(name = "...", modifiers = "+verbatim", modifiers = "bar")]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link(name = "...", modifiers = "+verbatim", modifiers = "bar")]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
 
-error: multiple `cfg` arguments in a single `#[link]` attribute
-  --> $DIR/link-attr-validation-late.rs:12:34
+error[E0538]: malformed `link` attribute input
+  --> $DIR/link-attr-validation-late.rs:12:1
    |
 LL | #[link(name = "...", cfg(false), cfg(false))]
-   |                                  ^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------^^
+   |                                  |
+   |                                  found `cfg` used as a key more than once
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(name = "...", cfg(false), cfg(false))]
+LL + #[link(name = "...")]
+   |
+LL - #[link(name = "...", cfg(false), cfg(false))]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link(name = "...", cfg(false), cfg(false))]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link(name = "...", cfg(false), cfg(false))]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
 
-error: multiple `wasm_import_module` arguments in a single `#[link]` attribute
-  --> $DIR/link-attr-validation-late.rs:13:36
+error[E0538]: malformed `link` attribute input
+  --> $DIR/link-attr-validation-late.rs:13:1
    |
 LL | #[link(wasm_import_module = "foo", wasm_import_module = "bar")]
-   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: link name must be of the form `name = "string"`
-  --> $DIR/link-attr-validation-late.rs:17:8
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------------^^
+   |                                    |
+   |                                    found `wasm_import_module` used as a key more than once
    |
-LL | #[link(name)]
-   |        ^^^^
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(wasm_import_module = "foo", wasm_import_module = "bar")]
+LL + #[link(name = "...")]
+   |
+LL - #[link(wasm_import_module = "foo", wasm_import_module = "bar")]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link(wasm_import_module = "foo", wasm_import_module = "bar")]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link(wasm_import_module = "foo", wasm_import_module = "bar")]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
 
-error[E0459]: `#[link]` attribute requires a `name = "string"` argument
+error[E0539]: malformed `link` attribute input
   --> $DIR/link-attr-validation-late.rs:17:1
    |
 LL | #[link(name)]
-   | ^^^^^^^^^^^^^ missing `name` argument
-
-error: link name must be of the form `name = "string"`
-  --> $DIR/link-attr-validation-late.rs:19:8
+   | ^^^^^^^----^^
+   |        |
+   |        expected this to be of the form `name = "..."`
    |
-LL | #[link(name())]
-   |        ^^^^^^
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL | #[link(name = "...")]
+   |             +++++++
+LL | #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |             ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+LL | #[link(name = "...", kind = "dylib|static|...")]
+   |             ++++++++++++++++++++++++++++++++++
+LL | #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |             +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+   = and 1 other candidate
 
-error[E0459]: `#[link]` attribute requires a `name = "string"` argument
-  --> $DIR/link-attr-validation-late.rs:19:1
+error[E0539]: malformed `link` attribute input
+  --> $DIR/link-attr-validation-late.rs:18:1
    |
 LL | #[link(name())]
-   | ^^^^^^^^^^^^^^^ missing `name` argument
+   | ^^^^^^^------^^
+   |        |
+   |        expected this to be of the form `name = "..."`
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(name())]
+LL + #[link(name = "...")]
+   |
+LL - #[link(name())]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link(name())]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link(name())]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
 
-error: link kind must be of the form `kind = "string"`
-  --> $DIR/link-attr-validation-late.rs:21:22
+error[E0539]: malformed `link` attribute input
+  --> $DIR/link-attr-validation-late.rs:19:1
    |
 LL | #[link(name = "...", kind)]
-   |                      ^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^----^^
+   |                      |
+   |                      expected this to be of the form `kind = "..."`
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(name = "...", kind)]
+LL + #[link(name = "...")]
+   |
+LL - #[link(name = "...", kind)]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL | #[link(name = "...", kind = "dylib|static|...")]
+   |                           ++++++++++++++++++++
+LL | #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |                           +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+   = and 1 other candidate
 
-error: link kind must be of the form `kind = "string"`
-  --> $DIR/link-attr-validation-late.rs:22:22
+error[E0539]: malformed `link` attribute input
+  --> $DIR/link-attr-validation-late.rs:20:1
    |
 LL | #[link(name = "...", kind())]
-   |                      ^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^------^^
+   |                      |
+   |                      expected this to be of the form `kind = "..."`
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(name = "...", kind())]
+LL + #[link(name = "...")]
+   |
+LL - #[link(name = "...", kind())]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link(name = "...", kind())]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link(name = "...", kind())]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
 
-error: link modifiers must be of the form `modifiers = "string"`
-  --> $DIR/link-attr-validation-late.rs:23:22
+error[E0539]: malformed `link` attribute input
+  --> $DIR/link-attr-validation-late.rs:21:1
    |
 LL | #[link(name = "...", modifiers)]
-   |                      ^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^---------^^
+   |                      |
+   |                      expected this to be of the form `modifiers = "..."`
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(name = "...", modifiers)]
+LL + #[link(name = "...")]
+   |
+LL - #[link(name = "...", modifiers)]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link(name = "...", modifiers)]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link(name = "...", modifiers)]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
 
-error: link modifiers must be of the form `modifiers = "string"`
-  --> $DIR/link-attr-validation-late.rs:24:22
+error[E0539]: malformed `link` attribute input
+  --> $DIR/link-attr-validation-late.rs:22:1
    |
 LL | #[link(name = "...", modifiers())]
-   |                      ^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^-----------^^
+   |                      |
+   |                      expected this to be of the form `modifiers = "..."`
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(name = "...", modifiers())]
+LL + #[link(name = "...")]
+   |
+LL - #[link(name = "...", modifiers())]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link(name = "...", modifiers())]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link(name = "...", modifiers())]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
 
-error: link cfg must be of the form `cfg(/* predicate */)`
-  --> $DIR/link-attr-validation-late.rs:25:22
+error[E0539]: malformed `link` attribute input
+  --> $DIR/link-attr-validation-late.rs:23:1
    |
 LL | #[link(name = "...", cfg)]
-   |                      ^^^
+   | ^^^^^^^^^^^^^^^^^^^^^---^^
+   |                      |
+   |                      expected this to be a list
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(name = "...", cfg)]
+LL + #[link(name = "...")]
+   |
+LL - #[link(name = "...", cfg)]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link(name = "...", cfg)]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link(name = "...", cfg)]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
 
-error: link cfg must be of the form `cfg(/* predicate */)`
-  --> $DIR/link-attr-validation-late.rs:26:22
+error[E0539]: malformed `link` attribute input
+  --> $DIR/link-attr-validation-late.rs:24:1
    |
 LL | #[link(name = "...", cfg = "literal")]
-   |                      ^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^---------------^^
+   |                      |
+   |                      expected this to be a list
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(name = "...", cfg = "literal")]
+LL + #[link(name = "...")]
+   |
+LL - #[link(name = "...", cfg = "literal")]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link(name = "...", cfg = "literal")]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link(name = "...", cfg = "literal")]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
 
-error: link cfg must have a single predicate argument
-  --> $DIR/link-attr-validation-late.rs:27:22
+error: `cfg` predicate key must be an identifier
+  --> $DIR/link-attr-validation-late.rs:25:26
    |
 LL | #[link(name = "...", cfg("literal"))]
-   |                      ^^^^^^^^^^^^^^
+   |                          ^^^^^^^^^
 
-error: wasm import module must be of the form `wasm_import_module = "string"`
-  --> $DIR/link-attr-validation-late.rs:28:22
+error[E0539]: malformed `link` attribute input
+  --> $DIR/link-attr-validation-late.rs:26:1
    |
 LL | #[link(name = "...", wasm_import_module)]
-   |                      ^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^------------------^^
+   |                      |
+   |                      expected this to be of the form `wasm_import_module = "..."`
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(name = "...", wasm_import_module)]
+LL + #[link(name = "...")]
+   |
+LL - #[link(name = "...", wasm_import_module)]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link(name = "...", wasm_import_module)]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link(name = "...", wasm_import_module)]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
 
-error: wasm import module must be of the form `wasm_import_module = "string"`
-  --> $DIR/link-attr-validation-late.rs:29:22
+error[E0539]: malformed `link` attribute input
+  --> $DIR/link-attr-validation-late.rs:27:1
    |
 LL | #[link(name = "...", wasm_import_module())]
-   |                      ^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^--------------------^^
+   |                      |
+   |                      expected this to be of the form `wasm_import_module = "..."`
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(name = "...", wasm_import_module())]
+LL + #[link(name = "...")]
+   |
+LL - #[link(name = "...", wasm_import_module())]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link(name = "...", wasm_import_module())]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link(name = "...", wasm_import_module())]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
 
 error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
-  --> $DIR/link-attr-validation-late.rs:33:34
+  --> $DIR/link-attr-validation-late.rs:31:34
    |
 LL | #[link(name = "...", modifiers = "")]
    |                                  ^^
 
 error: invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed
-  --> $DIR/link-attr-validation-late.rs:34:34
+  --> $DIR/link-attr-validation-late.rs:32:34
    |
 LL | #[link(name = "...", modifiers = "no-plus-minus")]
    |                                  ^^^^^^^^^^^^^^^
 
-error: unknown linking modifier `unknown`, expected one of: bundle, verbatim, whole-archive, as-needed
-  --> $DIR/link-attr-validation-late.rs:35:34
+error[E0539]: malformed `link` attribute input
+  --> $DIR/link-attr-validation-late.rs:33:1
    |
 LL | #[link(name = "...", modifiers = "+unknown")]
-   |                                  ^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------^^
+   |                                  |
+   |                                  valid arguments are "bundle", "verbatim", "whole-archive" or "as-needed"
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(name = "...", modifiers = "+unknown")]
+LL + #[link(name = "...")]
+   |
+LL - #[link(name = "...", modifiers = "+unknown")]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link(name = "...", modifiers = "+unknown")]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link(name = "...", modifiers = "+unknown")]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
 
 error: multiple `verbatim` modifiers in a single `modifiers` argument
-  --> $DIR/link-attr-validation-late.rs:36:34
+  --> $DIR/link-attr-validation-late.rs:34:34
    |
 LL | #[link(name = "...", modifiers = "+verbatim,+verbatim")]
    |                                  ^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 24 previous errors
+error: aborting due to 22 previous errors
 
-For more information about this error, try `rustc --explain E0459`.
+Some errors have detailed explanations: E0538, E0539, E0565.
+For more information about an error, try `rustc --explain E0538`.
diff --git a/tests/ui/link-native-libs/modifiers-override-4.rs b/tests/ui/link-native-libs/modifiers-override-4.rs
new file mode 100644
index 00000000000..cc5b07e20cc
--- /dev/null
+++ b/tests/ui/link-native-libs/modifiers-override-4.rs
@@ -0,0 +1,12 @@
+#[link(name = "foo")]
+#[link(
+//~^ ERROR malformed `link` attribute input
+    name = "bar",
+    kind = "static",
+    modifiers = "+whole-archive,-whole-archive",
+    //~^ ERROR multiple `whole-archive` modifiers in a single `modifiers` argument
+    modifiers = "+bundle"
+)]
+extern "C" {}
+
+fn main() {}
diff --git a/tests/ui/link-native-libs/modifiers-override-4.stderr b/tests/ui/link-native-libs/modifiers-override-4.stderr
new file mode 100644
index 00000000000..317e89cb39c
--- /dev/null
+++ b/tests/ui/link-native-libs/modifiers-override-4.stderr
@@ -0,0 +1,67 @@
+error[E0538]: malformed `link` attribute input
+  --> $DIR/modifiers-override-4.rs:2:1
+   |
+LL | / #[link(
+LL | |
+LL | |     name = "bar",
+LL | |     kind = "static",
+...  |
+LL | |     modifiers = "+bundle"
+   | |     --------------------- found `modifiers` used as a key more than once
+LL | | )]
+   | |__^
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(
+LL -
+LL -     name = "bar",
+LL -     kind = "static",
+LL -     modifiers = "+whole-archive,-whole-archive",
+LL -
+LL -     modifiers = "+bundle"
+LL - )]
+LL + #[link(name = "...")]
+   |
+LL - #[link(
+LL -
+LL -     name = "bar",
+LL -     kind = "static",
+LL -     modifiers = "+whole-archive,-whole-archive",
+LL -
+LL -     modifiers = "+bundle"
+LL - )]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link(
+LL -
+LL -     name = "bar",
+LL -     kind = "static",
+LL -     modifiers = "+whole-archive,-whole-archive",
+LL -
+LL -     modifiers = "+bundle"
+LL - )]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link(
+LL -
+LL -     name = "bar",
+LL -     kind = "static",
+LL -     modifiers = "+whole-archive,-whole-archive",
+LL -
+LL -     modifiers = "+bundle"
+LL - )]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
+
+error: multiple `whole-archive` modifiers in a single `modifiers` argument
+  --> $DIR/modifiers-override-4.rs:6:17
+   |
+LL |     modifiers = "+whole-archive,-whole-archive",
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0538`.
diff --git a/tests/ui/link-native-libs/modifiers-override.rs b/tests/ui/link-native-libs/modifiers-override.rs
index cd2d003664a..a44b7d37ed8 100644
--- a/tests/ui/link-native-libs/modifiers-override.rs
+++ b/tests/ui/link-native-libs/modifiers-override.rs
@@ -4,13 +4,8 @@
 #[link(
     name = "bar",
     kind = "static",
-    modifiers = "+whole-archive,-whole-archive",
-    //~^ ERROR multiple `whole-archive` modifiers in a single `modifiers` argument
-    modifiers = "+bundle"
-    //~^ ERROR multiple `modifiers` arguments in a single `#[link]` attribute
 )]
 extern "C" {}
 //~^ ERROR overriding linking modifiers from command line is not supported
-//~| ERROR overriding linking modifiers from command line is not supported
 
 fn main() {}
diff --git a/tests/ui/link-native-libs/modifiers-override.stderr b/tests/ui/link-native-libs/modifiers-override.stderr
index 64427651e9f..3cc99c96c7c 100644
--- a/tests/ui/link-native-libs/modifiers-override.stderr
+++ b/tests/ui/link-native-libs/modifiers-override.stderr
@@ -1,28 +1,8 @@
-error: multiple `modifiers` arguments in a single `#[link]` attribute
-  --> $DIR/modifiers-override.rs:9:5
-   |
-LL |     modifiers = "+bundle"
-   |     ^^^^^^^^^^^^^^^^^^^^^
-
-error: multiple `whole-archive` modifiers in a single `modifiers` argument
-  --> $DIR/modifiers-override.rs:7:17
-   |
-LL |     modifiers = "+whole-archive,-whole-archive",
-   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: overriding linking modifiers from command line is not supported
-  --> $DIR/modifiers-override.rs:12:1
-   |
-LL | extern "C" {}
-   | ^^^^^^^^^^^^^
-
 error: overriding linking modifiers from command line is not supported
-  --> $DIR/modifiers-override.rs:12:1
+  --> $DIR/modifiers-override.rs:8:1
    |
 LL | extern "C" {}
    | ^^^^^^^^^^^^^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: aborting due to 4 previous errors
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.rs
index 50ad8a173ad..542f34b3eb1 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.rs
@@ -1,7 +1,10 @@
-//@ only-windows
-//@ only-x86
+//@ add-core-stubs
+//@ compile-flags: --target i686-pc-windows-msvc
+//@ needs-llvm-components: x86
+#![feature(no_core, rustc_attrs, lang_items)]
+#![no_core]
+#![crate_type = "lib"]
+
 #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)]
-//~^ ERROR import name type must be of the form `import_name_type = "string"`
+//~^ ERROR malformed
 extern "C" { }
-
-fn main() {}
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.stderr
index d2cf7a0ba1f..6121762fb03 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-invalid-format.stderr
@@ -1,8 +1,28 @@
-error: import name type must be of the form `import_name_type = "string"`
-  --> $DIR/import-name-type-invalid-format.rs:3:42
+error[E0539]: malformed `link` attribute input
+  --> $DIR/import-name-type-invalid-format.rs:8:1
    |
 LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)]
-   |                                          ^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------^^
+   |                                          |
+   |                                          expected this to be of the form `import_name_type = "..."`
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)]
+LL + #[link(name = "...")]
+   |
+LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = 6)]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.rs
index cf456b9b261..e2418642aea 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.rs
@@ -1,8 +1,11 @@
 // ignore-tidy-linelength
-//@ only-windows
-//@ only-x86
+//@ add-core-stubs
+//@ compile-flags: --target i686-pc-windows-msvc
+//@ needs-llvm-components: x86
+#![feature(no_core, rustc_attrs, lang_items)]
+#![no_core]
+#![crate_type = "lib"]
+
 #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")]
-//~^ ERROR multiple `import_name_type` arguments in a single `#[link]` attribute
+//~^ ERROR malformed
 extern "C" { }
-
-fn main() {}
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.stderr
index 8e65baf65df..adfe915b464 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-multiple.stderr
@@ -1,8 +1,28 @@
-error: multiple `import_name_type` arguments in a single `#[link]` attribute
-  --> $DIR/import-name-type-multiple.rs:4:74
+error[E0538]: malformed `link` attribute input
+  --> $DIR/import-name-type-multiple.rs:9:1
    |
 LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")]
-   |                                                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------------------------------^^
+   |                                                                          |
+   |                                                                          found `import_name_type` used as a key more than once
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")]
+LL + #[link(name = "...")]
+   |
+LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated", import_name_type = "decorated")]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0538`.
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.rs
index b3859ba1ce6..174e8682f29 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.rs
@@ -1,7 +1,10 @@
-//@ only-windows
-//@ only-x86
+//@ add-core-stubs
+//@ compile-flags: --target i686-pc-windows-msvc
+//@ needs-llvm-components: x86
+#![feature(no_core, rustc_attrs, lang_items)]
+#![no_core]
+#![crate_type = "lib"]
+
 #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")]
-//~^ ERROR unknown import name type `unknown`, expected one of: decorated, noprefix, undecorated
+//~^ ERROR malformed
 extern "C" { }
-
-fn main() {}
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.stderr
index 4b8b90eb6e2..fc24a6bed17 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unknown-value.stderr
@@ -1,8 +1,28 @@
-error: unknown import name type `unknown`, expected one of: decorated, noprefix, undecorated
-  --> $DIR/import-name-type-unknown-value.rs:3:42
+error[E0539]: malformed `link` attribute input
+  --> $DIR/import-name-type-unknown-value.rs:8:1
    |
 LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")]
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------------^^
+   |                                          |
+   |                                          valid arguments are "decorated", "noprefix" or "undecorated"
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")]
+LL + #[link(name = "...")]
+   |
+LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link(name = "foo", kind = "raw-dylib", import_name_type = "unknown")]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
 
 error: aborting due to 1 previous error
 
+For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.rs
index 3ead5cb1fd7..ca6aef79c95 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.rs
@@ -1,5 +1,10 @@
-//@ only-windows
-//@ only-x86
+//@ add-core-stubs
+//@ compile-flags: --target i686-pc-windows-msvc
+//@ needs-llvm-components: x86
+#![feature(no_core, rustc_attrs, lang_items)]
+#![no_core]
+#![crate_type = "lib"]
+
 #[link(name = "foo", import_name_type = "decorated")]
 //~^ ERROR import name type can only be used with link kind `raw-dylib`
 extern "C" { }
@@ -11,5 +16,3 @@ extern "C" { }
 // Specifying `import_name_type` before `kind` shouldn't raise an error.
 #[link(name = "bar", import_name_type = "decorated", kind = "raw-dylib")]
 extern "C" { }
-
-fn main() {}
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.stderr
index 75cadc471c4..075e4ffffb8 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-unsupported-link-kind.stderr
@@ -1,11 +1,11 @@
 error: import name type can only be used with link kind `raw-dylib`
-  --> $DIR/import-name-type-unsupported-link-kind.rs:3:22
+  --> $DIR/import-name-type-unsupported-link-kind.rs:8:22
    |
 LL | #[link(name = "foo", import_name_type = "decorated")]
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: import name type can only be used with link kind `raw-dylib`
-  --> $DIR/import-name-type-unsupported-link-kind.rs:7:39
+  --> $DIR/import-name-type-unsupported-link-kind.rs:12:39
    |
 LL | #[link(name = "bar", kind = "static", import_name_type = "decorated")]
    |                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.rs b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.rs
index ab0dcda64e6..5f1410f7d2a 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.rs
@@ -1,7 +1,10 @@
-//@ only-windows
-//@ ignore-x86
+//@ add-core-stubs
+//@ compile-flags: --target aarch64-pc-windows-msvc
+//@ needs-llvm-components: aarch64
+#![feature(no_core, rustc_attrs, lang_items)]
+#![no_core]
+#![crate_type = "lib"]
+
 #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated")]
 //~^ ERROR import name type is only supported on x86
 extern "C" { }
-
-fn main() {}
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.stderr b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.stderr
index 757f1f7994e..ad3b9f79c84 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.stderr
+++ b/tests/ui/linkage-attr/raw-dylib/windows/import-name-type-x86-only.stderr
@@ -1,5 +1,5 @@
 error: import name type is only supported on x86
-  --> $DIR/import-name-type-x86-only.rs:3:42
+  --> $DIR/import-name-type-x86-only.rs:8:42
    |
 LL | #[link(name = "foo", kind = "raw-dylib", import_name_type = "decorated")]
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs
index 301e690be38..8651a4e7175 100644
--- a/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs
+++ b/tests/ui/linkage-attr/raw-dylib/windows/link-ordinal-not-foreign-fn.rs
@@ -10,7 +10,7 @@ fn test() {}
 //~^ ERROR attribute cannot be used on
 static mut imported_val: i32 = 123;
 
-#[link(name = "exporter", kind = "raw-dylib")]
+#[link(name = "exporter")]
 extern "C" {
     #[link_ordinal(13)]
     fn imported_function();
diff --git a/tests/ui/lint/inert-attr-macro.rs b/tests/ui/lint/inert-attr-macro.rs
index d345cbc0f07..c2ccba7f9ba 100644
--- a/tests/ui/lint/inert-attr-macro.rs
+++ b/tests/ui/lint/inert-attr-macro.rs
@@ -1,6 +1,5 @@
 //@ check-pass
 
-#![feature(rustc_attrs)]
 #![warn(unused)]
 
 macro_rules! foo {
@@ -8,16 +7,18 @@ macro_rules! foo {
 }
 
 fn main() {
-    #[rustc_dummy] foo!(); //~ WARN unused attribute `rustc_dummy`
+    #[inline] foo!(); //~ WARN `#[inline]` attribute cannot be used on macro calls
+    //~^ WARN previously accepted
 
     // This does nothing, since `#[allow(warnings)]` is itself
     // an inert attribute on a macro call
-    #[allow(warnings)] #[rustc_dummy] foo!(); //~ WARN unused attribute `allow`
-    //~^ WARN unused attribute `rustc_dummy`
+    #[allow(warnings)] #[inline] foo!(); //~ WARN unused attribute `allow`
+    //~^ WARN `#[inline]` attribute cannot be used on macro calls
+    //~| WARN previously accepted
 
     // This does work, since the attribute is on a parent
     // of the macro invocation.
-    #[allow(warnings)] { #[rustc_dummy] foo!(); }
+    #[allow(warnings)] { #[inline] foo!(); }
 
     // Ok, `cfg` and `cfg_attr` are expanded eagerly and do not warn.
     #[cfg(true)] foo!();
diff --git a/tests/ui/lint/inert-attr-macro.stderr b/tests/ui/lint/inert-attr-macro.stderr
index fc02ee34ae6..9ab6e3ddc74 100644
--- a/tests/ui/lint/inert-attr-macro.stderr
+++ b/tests/ui/lint/inert-attr-macro.stderr
@@ -1,16 +1,13 @@
-warning: unused attribute `rustc_dummy`
-  --> $DIR/inert-attr-macro.rs:11:5
+warning: `#[inline]` attribute cannot be used on macro calls
+  --> $DIR/inert-attr-macro.rs:10:5
    |
-LL |     #[rustc_dummy] foo!();
-   |     ^^^^^^^^^^^^^^
+LL |     #[inline] foo!();
+   |     ^^^^^^^^^
    |
-note: the built-in attribute `rustc_dummy` will be ignored, since it's applied to the macro invocation `foo`
-  --> $DIR/inert-attr-macro.rs:11:20
-   |
-LL |     #[rustc_dummy] foo!();
-   |                    ^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[inline]` can only be applied to functions
 note: the lint level is defined here
-  --> $DIR/inert-attr-macro.rs:4:9
+  --> $DIR/inert-attr-macro.rs:3:9
    |
 LL | #![warn(unused)]
    |         ^^^^^^
@@ -19,26 +16,23 @@ LL | #![warn(unused)]
 warning: unused attribute `allow`
   --> $DIR/inert-attr-macro.rs:15:5
    |
-LL |     #[allow(warnings)] #[rustc_dummy] foo!();
+LL |     #[allow(warnings)] #[inline] foo!();
    |     ^^^^^^^^^^^^^^^^^^
    |
 note: the built-in attribute `allow` will be ignored, since it's applied to the macro invocation `foo`
-  --> $DIR/inert-attr-macro.rs:15:39
+  --> $DIR/inert-attr-macro.rs:15:34
    |
-LL |     #[allow(warnings)] #[rustc_dummy] foo!();
-   |                                       ^^^
+LL |     #[allow(warnings)] #[inline] foo!();
+   |                                  ^^^
 
-warning: unused attribute `rustc_dummy`
+warning: `#[inline]` attribute cannot be used on macro calls
   --> $DIR/inert-attr-macro.rs:15:24
    |
-LL |     #[allow(warnings)] #[rustc_dummy] foo!();
-   |                        ^^^^^^^^^^^^^^
-   |
-note: the built-in attribute `rustc_dummy` will be ignored, since it's applied to the macro invocation `foo`
-  --> $DIR/inert-attr-macro.rs:15:39
+LL |     #[allow(warnings)] #[inline] foo!();
+   |                        ^^^^^^^^^
    |
-LL |     #[allow(warnings)] #[rustc_dummy] foo!();
-   |                                       ^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[inline]` can only be applied to functions
 
 warning: 3 warnings emitted
 
diff --git a/tests/ui/lint/int_to_ptr-unsized.rs b/tests/ui/lint/int_to_ptr-unsized.rs
new file mode 100644
index 00000000000..bbdc2474561
--- /dev/null
+++ b/tests/ui/lint/int_to_ptr-unsized.rs
@@ -0,0 +1,23 @@
+// Checks for the `integer_to_pointer_transmutes` lint with unsized types
+//
+// Related to https://github.com/rust-lang/rust/issues/145935
+
+//@ check-pass
+
+#![allow(non_camel_case_types)]
+#![allow(unused_unsafe)]
+
+#[cfg(target_pointer_width = "64")]
+type usizemetadata = i128;
+
+#[cfg(target_pointer_width = "32")]
+type usizemetadata = i64;
+
+unsafe fn unsized_type(a: usize) {
+    let _ref = unsafe { std::mem::transmute::<usizemetadata, &'static str>(0xff) };
+    //~^ WARN transmuting an integer to a pointer
+    let _ptr = unsafe { std::mem::transmute::<usizemetadata, *const [u8]>(0xff) };
+    //~^ WARN transmuting an integer to a pointer
+}
+
+fn main() {}
diff --git a/tests/ui/lint/int_to_ptr-unsized.stderr b/tests/ui/lint/int_to_ptr-unsized.stderr
new file mode 100644
index 00000000000..9799af8b12c
--- /dev/null
+++ b/tests/ui/lint/int_to_ptr-unsized.stderr
@@ -0,0 +1,27 @@
+warning: transmuting an integer to a pointer creates a pointer without provenance
+  --> $DIR/int_to_ptr-unsized.rs:17:25
+   |
+LL |     let _ref = unsafe { std::mem::transmute::<usizemetadata, &'static str>(0xff) };
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+   = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+   = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+   = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+   = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+   = note: `#[warn(integer_to_ptr_transmutes)]` on by default
+
+warning: transmuting an integer to a pointer creates a pointer without provenance
+  --> $DIR/int_to_ptr-unsized.rs:19:25
+   |
+LL |     let _ptr = unsafe { std::mem::transmute::<usizemetadata, *const [u8]>(0xff) };
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+   = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+   = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+   = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+   = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+
+warning: 2 warnings emitted
+
diff --git a/tests/ui/lint/int_to_ptr.fixed b/tests/ui/lint/int_to_ptr.fixed
new file mode 100644
index 00000000000..8f373492e6f
--- /dev/null
+++ b/tests/ui/lint/int_to_ptr.fixed
@@ -0,0 +1,47 @@
+// Checks for the `integer_to_pointer_transmutes` lint
+
+//@ check-pass
+//@ run-rustfix
+
+#![allow(unused_unsafe)]
+#![allow(dead_code)]
+
+unsafe fn should_lint(a: usize) {
+    let _ptr: *const u8 = unsafe { std::ptr::with_exposed_provenance::<u8>(a) };
+    //~^ WARN transmuting an integer to a pointer
+    let _ptr: *mut u8 = unsafe { std::ptr::with_exposed_provenance_mut::<u8>(a) };
+    //~^ WARN transmuting an integer to a pointer
+    let _ref: &'static u8 = unsafe { &*std::ptr::with_exposed_provenance::<u8>(a) };
+    //~^ WARN transmuting an integer to a pointer
+    let _ref: &'static mut u8 = unsafe { &mut *std::ptr::with_exposed_provenance_mut::<u8>(a) };
+    //~^ WARN transmuting an integer to a pointer
+
+    let _ptr = unsafe { std::ptr::with_exposed_provenance::<u8>(42usize) };
+    //~^ WARN transmuting an integer to a pointer
+    let _ptr = unsafe { std::ptr::with_exposed_provenance::<u8>(a + a) };
+    //~^ WARN transmuting an integer to a pointer
+}
+
+const unsafe fn should_lintin_const(a: usize) {
+    let _ptr: *const u8 = unsafe { std::ptr::with_exposed_provenance::<u8>(a) };
+    //~^ WARN transmuting an integer to a pointer
+    let _ptr: *mut u8 = unsafe { std::ptr::with_exposed_provenance_mut::<u8>(a) };
+    //~^ WARN transmuting an integer to a pointer
+    let _ref: &'static u8 = unsafe { &*std::ptr::with_exposed_provenance::<u8>(a) };
+    //~^ WARN transmuting an integer to a pointer
+    let _ref: &'static mut u8 = unsafe { &mut *std::ptr::with_exposed_provenance_mut::<u8>(a) };
+    //~^ WARN transmuting an integer to a pointer
+
+    let _ptr = unsafe { std::ptr::with_exposed_provenance::<u8>(42usize) };
+    //~^ WARN transmuting an integer to a pointer
+    let _ptr = unsafe { std::ptr::with_exposed_provenance::<u8>(a + a) };
+    //~^ WARN transmuting an integer to a pointer
+}
+
+unsafe fn should_not_lint(a: usize) {
+    let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(0usize) }; // linted by other lints
+    let _ptr = unsafe { std::mem::transmute::<usize, *const ()>(a) }; // inner type is a ZST
+    let _ptr = unsafe { std::mem::transmute::<usize, fn()>(a) }; // omit fn-ptr for now
+}
+
+fn main() {}
diff --git a/tests/ui/lint/int_to_ptr.rs b/tests/ui/lint/int_to_ptr.rs
new file mode 100644
index 00000000000..7f60da47b85
--- /dev/null
+++ b/tests/ui/lint/int_to_ptr.rs
@@ -0,0 +1,47 @@
+// Checks for the `integer_to_pointer_transmutes` lint
+
+//@ check-pass
+//@ run-rustfix
+
+#![allow(unused_unsafe)]
+#![allow(dead_code)]
+
+unsafe fn should_lint(a: usize) {
+    let _ptr: *const u8 = unsafe { std::mem::transmute::<usize, *const u8>(a) };
+    //~^ WARN transmuting an integer to a pointer
+    let _ptr: *mut u8 = unsafe { std::mem::transmute::<usize, *mut u8>(a) };
+    //~^ WARN transmuting an integer to a pointer
+    let _ref: &'static u8 = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
+    //~^ WARN transmuting an integer to a pointer
+    let _ref: &'static mut u8 = unsafe { std::mem::transmute::<usize, &'static mut u8>(a) };
+    //~^ WARN transmuting an integer to a pointer
+
+    let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(42usize) };
+    //~^ WARN transmuting an integer to a pointer
+    let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a + a) };
+    //~^ WARN transmuting an integer to a pointer
+}
+
+const unsafe fn should_lintin_const(a: usize) {
+    let _ptr: *const u8 = unsafe { std::mem::transmute::<usize, *const u8>(a) };
+    //~^ WARN transmuting an integer to a pointer
+    let _ptr: *mut u8 = unsafe { std::mem::transmute::<usize, *mut u8>(a) };
+    //~^ WARN transmuting an integer to a pointer
+    let _ref: &'static u8 = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
+    //~^ WARN transmuting an integer to a pointer
+    let _ref: &'static mut u8 = unsafe { std::mem::transmute::<usize, &'static mut u8>(a) };
+    //~^ WARN transmuting an integer to a pointer
+
+    let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(42usize) };
+    //~^ WARN transmuting an integer to a pointer
+    let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a + a) };
+    //~^ WARN transmuting an integer to a pointer
+}
+
+unsafe fn should_not_lint(a: usize) {
+    let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(0usize) }; // linted by other lints
+    let _ptr = unsafe { std::mem::transmute::<usize, *const ()>(a) }; // inner type is a ZST
+    let _ptr = unsafe { std::mem::transmute::<usize, fn()>(a) }; // omit fn-ptr for now
+}
+
+fn main() {}
diff --git a/tests/ui/lint/int_to_ptr.stderr b/tests/ui/lint/int_to_ptr.stderr
new file mode 100644
index 00000000000..4035bda8fb2
--- /dev/null
+++ b/tests/ui/lint/int_to_ptr.stderr
@@ -0,0 +1,207 @@
+warning: transmuting an integer to a pointer creates a pointer without provenance
+  --> $DIR/int_to_ptr.rs:10:36
+   |
+LL |     let _ptr: *const u8 = unsafe { std::mem::transmute::<usize, *const u8>(a) };
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+   = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+   = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+   = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+   = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+   = note: `#[warn(integer_to_ptr_transmutes)]` on by default
+help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance
+   |
+LL -     let _ptr: *const u8 = unsafe { std::mem::transmute::<usize, *const u8>(a) };
+LL +     let _ptr: *const u8 = unsafe { std::ptr::with_exposed_provenance::<u8>(a) };
+   |
+
+warning: transmuting an integer to a pointer creates a pointer without provenance
+  --> $DIR/int_to_ptr.rs:12:34
+   |
+LL |     let _ptr: *mut u8 = unsafe { std::mem::transmute::<usize, *mut u8>(a) };
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+   = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+   = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+   = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+   = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+help: use `std::ptr::with_exposed_provenance_mut` instead to use a previously exposed provenance
+   |
+LL -     let _ptr: *mut u8 = unsafe { std::mem::transmute::<usize, *mut u8>(a) };
+LL +     let _ptr: *mut u8 = unsafe { std::ptr::with_exposed_provenance_mut::<u8>(a) };
+   |
+
+warning: transmuting an integer to a pointer creates a pointer without provenance
+  --> $DIR/int_to_ptr.rs:14:38
+   |
+LL |     let _ref: &'static u8 = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+   = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+   = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+   = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+   = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance
+   |
+LL -     let _ref: &'static u8 = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
+LL +     let _ref: &'static u8 = unsafe { &*std::ptr::with_exposed_provenance::<u8>(a) };
+   |
+
+warning: transmuting an integer to a pointer creates a pointer without provenance
+  --> $DIR/int_to_ptr.rs:16:42
+   |
+LL |     let _ref: &'static mut u8 = unsafe { std::mem::transmute::<usize, &'static mut u8>(a) };
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+   = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+   = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+   = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+   = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+help: use `std::ptr::with_exposed_provenance_mut` instead to use a previously exposed provenance
+   |
+LL -     let _ref: &'static mut u8 = unsafe { std::mem::transmute::<usize, &'static mut u8>(a) };
+LL +     let _ref: &'static mut u8 = unsafe { &mut *std::ptr::with_exposed_provenance_mut::<u8>(a) };
+   |
+
+warning: transmuting an integer to a pointer creates a pointer without provenance
+  --> $DIR/int_to_ptr.rs:19:25
+   |
+LL |     let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(42usize) };
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+   = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+   = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+   = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+   = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance
+   |
+LL -     let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(42usize) };
+LL +     let _ptr = unsafe { std::ptr::with_exposed_provenance::<u8>(42usize) };
+   |
+
+warning: transmuting an integer to a pointer creates a pointer without provenance
+  --> $DIR/int_to_ptr.rs:21:25
+   |
+LL |     let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a + a) };
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+   = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+   = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+   = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+   = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance
+   |
+LL -     let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a + a) };
+LL +     let _ptr = unsafe { std::ptr::with_exposed_provenance::<u8>(a + a) };
+   |
+
+warning: transmuting an integer to a pointer creates a pointer without provenance
+  --> $DIR/int_to_ptr.rs:26:36
+   |
+LL |     let _ptr: *const u8 = unsafe { std::mem::transmute::<usize, *const u8>(a) };
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+   = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+   = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+   = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+   = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance
+   |
+LL -     let _ptr: *const u8 = unsafe { std::mem::transmute::<usize, *const u8>(a) };
+LL +     let _ptr: *const u8 = unsafe { std::ptr::with_exposed_provenance::<u8>(a) };
+   |
+
+warning: transmuting an integer to a pointer creates a pointer without provenance
+  --> $DIR/int_to_ptr.rs:28:34
+   |
+LL |     let _ptr: *mut u8 = unsafe { std::mem::transmute::<usize, *mut u8>(a) };
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+   = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+   = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+   = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+   = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+help: use `std::ptr::with_exposed_provenance_mut` instead to use a previously exposed provenance
+   |
+LL -     let _ptr: *mut u8 = unsafe { std::mem::transmute::<usize, *mut u8>(a) };
+LL +     let _ptr: *mut u8 = unsafe { std::ptr::with_exposed_provenance_mut::<u8>(a) };
+   |
+
+warning: transmuting an integer to a pointer creates a pointer without provenance
+  --> $DIR/int_to_ptr.rs:30:38
+   |
+LL |     let _ref: &'static u8 = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+   = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+   = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+   = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+   = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance
+   |
+LL -     let _ref: &'static u8 = unsafe { std::mem::transmute::<usize, &'static u8>(a) };
+LL +     let _ref: &'static u8 = unsafe { &*std::ptr::with_exposed_provenance::<u8>(a) };
+   |
+
+warning: transmuting an integer to a pointer creates a pointer without provenance
+  --> $DIR/int_to_ptr.rs:32:42
+   |
+LL |     let _ref: &'static mut u8 = unsafe { std::mem::transmute::<usize, &'static mut u8>(a) };
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+   = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+   = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+   = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+   = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+help: use `std::ptr::with_exposed_provenance_mut` instead to use a previously exposed provenance
+   |
+LL -     let _ref: &'static mut u8 = unsafe { std::mem::transmute::<usize, &'static mut u8>(a) };
+LL +     let _ref: &'static mut u8 = unsafe { &mut *std::ptr::with_exposed_provenance_mut::<u8>(a) };
+   |
+
+warning: transmuting an integer to a pointer creates a pointer without provenance
+  --> $DIR/int_to_ptr.rs:35:25
+   |
+LL |     let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(42usize) };
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+   = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+   = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+   = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+   = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance
+   |
+LL -     let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(42usize) };
+LL +     let _ptr = unsafe { std::ptr::with_exposed_provenance::<u8>(42usize) };
+   |
+
+warning: transmuting an integer to a pointer creates a pointer without provenance
+  --> $DIR/int_to_ptr.rs:37:25
+   |
+LL |     let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a + a) };
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this is dangerous because dereferencing the resulting pointer is undefined behavior
+   = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance
+   = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`
+   = help: for more information about transmute, see <https://doc.rust-lang.org/std/mem/fn.transmute.html#transmutation-between-pointers-and-integers>
+   = help: for more information about exposed provenance, see <https://doc.rust-lang.org/std/ptr/index.html#exposed-provenance>
+help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance
+   |
+LL -     let _ptr = unsafe { std::mem::transmute::<usize, *const u8>(a + a) };
+LL +     let _ptr = unsafe { std::ptr::with_exposed_provenance::<u8>(a + a) };
+   |
+
+warning: 12 warnings emitted
+
diff --git a/tests/ui/lint/linker-warning.stderr b/tests/ui/lint/linker-warning.stderr
index c678562ab54..ae5f6b3adec 100644
--- a/tests/ui/lint/linker-warning.stderr
+++ b/tests/ui/lint/linker-warning.stderr
@@ -1,4 +1,4 @@
-warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+warning: crate-level attribute should be an inner attribute
   --> $DIR/linker-warning.rs:7:1
    |
 LL | #[allow(linker_messages)]
@@ -9,6 +9,10 @@ note: the lint level is defined here
    |
 LL | #![warn(unused_attributes)]
    |         ^^^^^^^^^^^^^^^^^
+help: add a `!`
+   |
+LL | #![allow(linker_messages)]
+   |  +
 
 warning: unused attribute
   --> $DIR/linker-warning.rs:4:1
diff --git a/tests/ui/lint/lint-misplaced-attr.stderr b/tests/ui/lint/lint-misplaced-attr.stderr
index abaf4620e6f..bcfda170080 100644
--- a/tests/ui/lint/lint-misplaced-attr.stderr
+++ b/tests/ui/lint/lint-misplaced-attr.stderr
@@ -10,11 +10,16 @@ note: the lint level is defined here
 LL | #![deny(unused_attributes)]
    |         ^^^^^^^^^^^^^^^^^
 
-error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+error: crate-level attribute should be an inner attribute
   --> $DIR/lint-misplaced-attr.rs:10:1
    |
 LL | #[crate_type = "bin"] fn main() {}
    | ^^^^^^^^^^^^^^^^^^^^^
+   |
+help: add a `!`
+   |
+LL | #![crate_type = "bin"] fn main() {}
+   |  +
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/lint/unused/concat-in-crate-deprecated-issue-137687.rs b/tests/ui/lint/unused/concat-in-crate-deprecated-issue-137687.rs
new file mode 100644
index 00000000000..22dd55f4421
--- /dev/null
+++ b/tests/ui/lint/unused/concat-in-crate-deprecated-issue-137687.rs
@@ -0,0 +1,6 @@
+//@ check-pass
+#[deprecated = concat !()]
+macro_rules! a {
+    () => {};
+}
+fn main() {}
diff --git a/tests/ui/lint/unused/concat-in-crate-name-issue-137687.rs b/tests/ui/lint/unused/concat-in-crate-name-issue-137687.rs
new file mode 100644
index 00000000000..c507b6590c2
--- /dev/null
+++ b/tests/ui/lint/unused/concat-in-crate-name-issue-137687.rs
@@ -0,0 +1,9 @@
+#![deny(unused)]
+
+#[crate_name = concat !()]
+//~^ ERROR crate-level attribute should be an inner attribute
+macro_rules! a {
+    //~^ ERROR unused macro definition
+    () => {};
+}
+fn main() {}
diff --git a/tests/ui/lint/unused/concat-in-crate-name-issue-137687.stderr b/tests/ui/lint/unused/concat-in-crate-name-issue-137687.stderr
new file mode 100644
index 00000000000..b06e65af7bc
--- /dev/null
+++ b/tests/ui/lint/unused/concat-in-crate-name-issue-137687.stderr
@@ -0,0 +1,31 @@
+error: unused macro definition: `a`
+  --> $DIR/concat-in-crate-name-issue-137687.rs:5:14
+   |
+LL | macro_rules! a {
+   |              ^
+   |
+note: the lint level is defined here
+  --> $DIR/concat-in-crate-name-issue-137687.rs:1:9
+   |
+LL | #![deny(unused)]
+   |         ^^^^^^
+   = note: `#[deny(unused_macros)]` implied by `#[deny(unused)]`
+
+error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
+  --> $DIR/concat-in-crate-name-issue-137687.rs:3:1
+   |
+LL | #[crate_name = concat !()]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: This attribute does not have an `!`, which means it is applied to this macro def
+  --> $DIR/concat-in-crate-name-issue-137687.rs:5:1
+   |
+LL | / macro_rules! a {
+LL | |
+LL | |     () => {};
+LL | | }
+   | |_^
+   = note: `#[deny(unused_attributes)]` implied by `#[deny(unused)]`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/lint/unused/unused-attr-duplicate.rs b/tests/ui/lint/unused/unused-attr-duplicate.rs
index cfa6c2b4228..a334c49788c 100644
--- a/tests/ui/lint/unused/unused-attr-duplicate.rs
+++ b/tests/ui/lint/unused/unused-attr-duplicate.rs
@@ -11,8 +11,12 @@
 // - no_main: extra setup
 #![deny(unused_attributes)]
 #![crate_name = "unused_attr_duplicate"]
-#![crate_name = "unused_attr_duplicate2"] //~ ERROR unused attribute
-//~^ WARN this was previously accepted
+#![crate_name = "unused_attr_duplicate2"]
+//~^ ERROR unused attribute
+//~| WARN this was previously accepted
+//~| ERROR unused attribute
+//~| WARN this was previously accepted
+// FIXME(jdonszelmann) this error is given twice now. I'll look at this in the future
 #![recursion_limit = "128"]
 #![recursion_limit = "256"] //~ ERROR unused attribute
 //~^ WARN this was previously accepted
diff --git a/tests/ui/lint/unused/unused-attr-duplicate.stderr b/tests/ui/lint/unused/unused-attr-duplicate.stderr
index 6c44e884ba5..203211d0d56 100644
--- a/tests/ui/lint/unused/unused-attr-duplicate.stderr
+++ b/tests/ui/lint/unused/unused-attr-duplicate.stderr
@@ -1,14 +1,15 @@
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:33:1
+  --> $DIR/unused-attr-duplicate.rs:14:1
    |
-LL | #[no_link]
-   | ^^^^^^^^^^ help: remove this attribute
+LL | #![crate_name = "unused_attr_duplicate2"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:32:1
+  --> $DIR/unused-attr-duplicate.rs:13:1
    |
-LL | #[no_link]
-   | ^^^^^^^^^^
+LL | #![crate_name = "unused_attr_duplicate"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 note: the lint level is defined here
   --> $DIR/unused-attr-duplicate.rs:12:9
    |
@@ -16,291 +17,304 @@ LL | #![deny(unused_attributes)]
    |         ^^^^^^^^^^^^^^^^^
 
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:14:1
+  --> $DIR/unused-attr-duplicate.rs:37:1
    |
-LL | #![crate_name = "unused_attr_duplicate2"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+LL | #[no_link]
+   | ^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:13:1
+  --> $DIR/unused-attr-duplicate.rs:36:1
    |
-LL | #![crate_name = "unused_attr_duplicate"]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+LL | #[no_link]
+   | ^^^^^^^^^^
 
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:17:1
+  --> $DIR/unused-attr-duplicate.rs:21:1
    |
 LL | #![recursion_limit = "256"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:16:1
+  --> $DIR/unused-attr-duplicate.rs:20:1
    |
 LL | #![recursion_limit = "128"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:20:1
+  --> $DIR/unused-attr-duplicate.rs:24:1
    |
 LL | #![type_length_limit = "1"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:19:1
+  --> $DIR/unused-attr-duplicate.rs:23:1
    |
 LL | #![type_length_limit = "1048576"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:23:1
+  --> $DIR/unused-attr-duplicate.rs:27:1
    |
 LL | #![no_std]
    | ^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:22:1
+  --> $DIR/unused-attr-duplicate.rs:26:1
    |
 LL | #![no_std]
    | ^^^^^^^^^^
 
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:27:1
+  --> $DIR/unused-attr-duplicate.rs:31:1
    |
 LL | #![windows_subsystem = "windows"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:26:1
+  --> $DIR/unused-attr-duplicate.rs:30:1
    |
 LL | #![windows_subsystem = "console"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:30:1
+  --> $DIR/unused-attr-duplicate.rs:34:1
    |
 LL | #![no_builtins]
    | ^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:29:1
+  --> $DIR/unused-attr-duplicate.rs:33:1
    |
 LL | #![no_builtins]
    | ^^^^^^^^^^^^^^^
 
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:40:5
+  --> $DIR/unused-attr-duplicate.rs:44:5
    |
 LL |     #[macro_export]
    |     ^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:39:5
+  --> $DIR/unused-attr-duplicate.rs:43:5
    |
 LL |     #[macro_export]
    |     ^^^^^^^^^^^^^^^
 
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:37:1
+  --> $DIR/unused-attr-duplicate.rs:41:1
    |
 LL | #[macro_use]
    | ^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:36:1
+  --> $DIR/unused-attr-duplicate.rs:40:1
    |
 LL | #[macro_use]
    | ^^^^^^^^^^^^
 
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:47:1
+  --> $DIR/unused-attr-duplicate.rs:51:1
    |
 LL | #[path = "bar.rs"]
    | ^^^^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:46:1
+  --> $DIR/unused-attr-duplicate.rs:50:1
    |
 LL | #[path = "auxiliary/lint_unused_extern_crate.rs"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:53:1
+  --> $DIR/unused-attr-duplicate.rs:57:1
    |
 LL | #[ignore = "some text"]
    | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:52:1
+  --> $DIR/unused-attr-duplicate.rs:56:1
    |
 LL | #[ignore]
    | ^^^^^^^^^
 
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:55:1
+  --> $DIR/unused-attr-duplicate.rs:59:1
    |
 LL | #[should_panic(expected = "values don't match")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:54:1
+  --> $DIR/unused-attr-duplicate.rs:58:1
    |
 LL | #[should_panic]
    | ^^^^^^^^^^^^^^^
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:60:1
+  --> $DIR/unused-attr-duplicate.rs:64:1
    |
 LL | #[must_use = "some message"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:59:1
+  --> $DIR/unused-attr-duplicate.rs:63:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:66:1
+  --> $DIR/unused-attr-duplicate.rs:70:1
    |
 LL | #[non_exhaustive]
    | ^^^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:65:1
+  --> $DIR/unused-attr-duplicate.rs:69:1
    |
 LL | #[non_exhaustive]
    | ^^^^^^^^^^^^^^^^^
 
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:72:1
+  --> $DIR/unused-attr-duplicate.rs:76:1
    |
 LL | #[automatically_derived]
    | ^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:71:1
+  --> $DIR/unused-attr-duplicate.rs:75:1
    |
 LL | #[automatically_derived]
    | ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:76:1
+  --> $DIR/unused-attr-duplicate.rs:80:1
    |
 LL | #[inline(never)]
    | ^^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:75:1
+  --> $DIR/unused-attr-duplicate.rs:79:1
    |
 LL | #[inline(always)]
    | ^^^^^^^^^^^^^^^^^
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:79:1
+  --> $DIR/unused-attr-duplicate.rs:83:1
    |
 LL | #[cold]
    | ^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:78:1
+  --> $DIR/unused-attr-duplicate.rs:82:1
    |
 LL | #[cold]
    | ^^^^^^^
 
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:81:1
+  --> $DIR/unused-attr-duplicate.rs:85:1
    |
 LL | #[track_caller]
    | ^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:80:1
+  --> $DIR/unused-attr-duplicate.rs:84:1
    |
 LL | #[track_caller]
    | ^^^^^^^^^^^^^^^
 
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:88:5
+  --> $DIR/unused-attr-duplicate.rs:92:5
    |
 LL |     #[link_name = "this_does_not_exist"]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:90:5
+  --> $DIR/unused-attr-duplicate.rs:94:5
    |
 LL |     #[link_name = "rust_dbg_extern_identity_u32"]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:94:1
+  --> $DIR/unused-attr-duplicate.rs:98:1
    |
 LL | #[export_name = "exported_symbol_name"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:96:1
+  --> $DIR/unused-attr-duplicate.rs:100:1
    |
 LL | #[export_name = "exported_symbol_name2"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:100:1
+  --> $DIR/unused-attr-duplicate.rs:104:1
    |
 LL | #[no_mangle]
    | ^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:99:1
+  --> $DIR/unused-attr-duplicate.rs:103:1
    |
 LL | #[no_mangle]
    | ^^^^^^^^^^^^
 
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:104:1
+  --> $DIR/unused-attr-duplicate.rs:108:1
    |
 LL | #[used]
    | ^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:103:1
+  --> $DIR/unused-attr-duplicate.rs:107:1
    |
 LL | #[used]
    | ^^^^^^^
 
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:107:1
+  --> $DIR/unused-attr-duplicate.rs:111:1
    |
 LL | #[link_section = ".text"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:110:1
+  --> $DIR/unused-attr-duplicate.rs:114:1
    |
 LL | #[link_section = ".bss"]
    | ^^^^^^^^^^^^^^^^^^^^^^^^
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 
 error: unused attribute
-  --> $DIR/unused-attr-duplicate.rs:25:1
+  --> $DIR/unused-attr-duplicate.rs:14:1
+   |
+LL | #![crate_name = "unused_attr_duplicate2"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
+   |
+note: attribute also specified here
+  --> $DIR/unused-attr-duplicate.rs:13:1
+   |
+LL | #![crate_name = "unused_attr_duplicate"]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: unused attribute
+  --> $DIR/unused-attr-duplicate.rs:29:1
    |
 LL | #![no_implicit_prelude]
    | ^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/unused-attr-duplicate.rs:24:1
+  --> $DIR/unused-attr-duplicate.rs:28:1
    |
 LL | #![no_implicit_prelude]
    | ^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 24 previous errors
+error: aborting due to 25 previous errors
 
diff --git a/tests/ui/lint/unused/unused-attr-macro-rules.stderr b/tests/ui/lint/unused/unused-attr-macro-rules.stderr
index 9d61120463c..af64be8f6e9 100644
--- a/tests/ui/lint/unused/unused-attr-macro-rules.stderr
+++ b/tests/ui/lint/unused/unused-attr-macro-rules.stderr
@@ -1,4 +1,4 @@
-error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
+error: crate-level attribute should be an inner attribute
   --> $DIR/unused-attr-macro-rules.rs:11:1
    |
 LL | #[recursion_limit="1"]
@@ -9,6 +9,10 @@ note: the lint level is defined here
    |
 LL | #![deny(unused_attributes)]
    |         ^^^^^^^^^^^^^^^^^
+help: add a `!`
+   |
+LL | #![recursion_limit="1"]
+   |  +
 
 error: `#[macro_use]` attribute cannot be used on macro defs
   --> $DIR/unused-attr-macro-rules.rs:7:1
diff --git a/tests/ui/lint/unused/unused_attributes-must_use.fixed b/tests/ui/lint/unused/unused_attributes-must_use.fixed
index 2e800cbff3f..fa596da95cc 100644
--- a/tests/ui/lint/unused/unused_attributes-must_use.fixed
+++ b/tests/ui/lint/unused/unused_attributes-must_use.fixed
@@ -65,7 +65,8 @@ extern "Rust" {
     fn foreign_foo() -> i64;
 }
 
- //~ ERROR unused attribute
+//~^ ERROR `#[must_use]` attribute cannot be used on macro calls
+//~| WARN this was previously accepted by the compiler but is being phased out
 global_asm!("");
 
  //~ ERROR attribute cannot be used on
diff --git a/tests/ui/lint/unused/unused_attributes-must_use.rs b/tests/ui/lint/unused/unused_attributes-must_use.rs
index c41c6c1d706..3e72dd1e438 100644
--- a/tests/ui/lint/unused/unused_attributes-must_use.rs
+++ b/tests/ui/lint/unused/unused_attributes-must_use.rs
@@ -65,7 +65,9 @@ extern "Rust" {
     fn foreign_foo() -> i64;
 }
 
-#[must_use] //~ ERROR unused attribute
+#[must_use]
+//~^ ERROR `#[must_use]` attribute cannot be used on macro calls
+//~| WARN this was previously accepted by the compiler but is being phased out
 global_asm!("");
 
 #[must_use] //~ ERROR attribute cannot be used on
diff --git a/tests/ui/lint/unused/unused_attributes-must_use.stderr b/tests/ui/lint/unused/unused_attributes-must_use.stderr
index 03baea3a004..001ec52ddd9 100644
--- a/tests/ui/lint/unused/unused_attributes-must_use.stderr
+++ b/tests/ui/lint/unused/unused_attributes-must_use.stderr
@@ -1,14 +1,11 @@
-error: unused attribute `must_use`
+error: `#[must_use]` attribute cannot be used on macro calls
   --> $DIR/unused_attributes-must_use.rs:68:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
    |
-note: the built-in attribute `must_use` will be ignored, since it's applied to the macro invocation `global_asm`
-  --> $DIR/unused_attributes-must_use.rs:69:1
-   |
-LL | global_asm!("");
-   | ^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = help: `#[must_use]` can be applied to functions, data types, unions, and traits
 note: the lint level is defined here
   --> $DIR/unused_attributes-must_use.rs:4:9
    |
@@ -88,7 +85,7 @@ LL |     #[must_use]
    = help: `#[must_use]` can be applied to functions, data types, unions, and traits
 
 error: `#[must_use]` attribute cannot be used on type aliases
-  --> $DIR/unused_attributes-must_use.rs:71:1
+  --> $DIR/unused_attributes-must_use.rs:73:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
@@ -97,7 +94,7 @@ LL | #[must_use]
    = help: `#[must_use]` can be applied to functions, data types, unions, and traits
 
 error: `#[must_use]` attribute cannot be used on function params
-  --> $DIR/unused_attributes-must_use.rs:75:8
+  --> $DIR/unused_attributes-must_use.rs:77:8
    |
 LL | fn qux<#[must_use] T>(_: T) {}
    |        ^^^^^^^^^^^
@@ -106,7 +103,7 @@ LL | fn qux<#[must_use] T>(_: T) {}
    = help: `#[must_use]` can be applied to functions, data types, unions, and traits
 
 error: `#[must_use]` attribute cannot be used on associated consts
-  --> $DIR/unused_attributes-must_use.rs:80:5
+  --> $DIR/unused_attributes-must_use.rs:82:5
    |
 LL |     #[must_use]
    |     ^^^^^^^^^^^
@@ -115,7 +112,7 @@ LL |     #[must_use]
    = help: `#[must_use]` can be applied to functions, data types, unions, and traits
 
 error: `#[must_use]` attribute cannot be used on associated types
-  --> $DIR/unused_attributes-must_use.rs:83:5
+  --> $DIR/unused_attributes-must_use.rs:85:5
    |
 LL |     #[must_use]
    |     ^^^^^^^^^^^
@@ -124,7 +121,7 @@ LL |     #[must_use]
    = help: `#[must_use]` can be applied to functions, data types, unions, and traits
 
 error: `#[must_use]` attribute cannot be used on trait impl blocks
-  --> $DIR/unused_attributes-must_use.rs:93:1
+  --> $DIR/unused_attributes-must_use.rs:95:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
@@ -133,7 +130,7 @@ LL | #[must_use]
    = help: `#[must_use]` can be applied to functions, data types, unions, and traits
 
 error: `#[must_use]` attribute cannot be used on trait methods in impl blocks
-  --> $DIR/unused_attributes-must_use.rs:98:5
+  --> $DIR/unused_attributes-must_use.rs:100:5
    |
 LL |     #[must_use]
    |     ^^^^^^^^^^^
@@ -142,7 +139,7 @@ LL |     #[must_use]
    = help: `#[must_use]` can be applied to data types, functions, unions, required trait methods, provided trait methods, inherent methods, foreign functions, and traits
 
 error: `#[must_use]` attribute cannot be used on trait aliases
-  --> $DIR/unused_attributes-must_use.rs:105:1
+  --> $DIR/unused_attributes-must_use.rs:107:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
@@ -151,7 +148,7 @@ LL | #[must_use]
    = help: `#[must_use]` can be applied to functions, data types, unions, and traits
 
 error: `#[must_use]` attribute cannot be used on macro defs
-  --> $DIR/unused_attributes-must_use.rs:109:1
+  --> $DIR/unused_attributes-must_use.rs:111:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
@@ -160,7 +157,7 @@ LL | #[must_use]
    = help: `#[must_use]` can be applied to functions, data types, unions, and traits
 
 error: `#[must_use]` attribute cannot be used on statements
-  --> $DIR/unused_attributes-must_use.rs:118:5
+  --> $DIR/unused_attributes-must_use.rs:120:5
    |
 LL |     #[must_use]
    |     ^^^^^^^^^^^
@@ -169,7 +166,7 @@ LL |     #[must_use]
    = help: `#[must_use]` can be applied to functions, data types, unions, and traits
 
 error: `#[must_use]` attribute cannot be used on closures
-  --> $DIR/unused_attributes-must_use.rs:123:13
+  --> $DIR/unused_attributes-must_use.rs:125:13
    |
 LL |     let x = #[must_use]
    |             ^^^^^^^^^^^
@@ -178,7 +175,7 @@ LL |     let x = #[must_use]
    = help: `#[must_use]` can be applied to methods, data types, functions, unions, foreign functions, and traits
 
 error: `#[must_use]` attribute cannot be used on match arms
-  --> $DIR/unused_attributes-must_use.rs:146:9
+  --> $DIR/unused_attributes-must_use.rs:148:9
    |
 LL |         #[must_use]
    |         ^^^^^^^^^^^
@@ -187,7 +184,7 @@ LL |         #[must_use]
    = help: `#[must_use]` can be applied to functions, data types, unions, and traits
 
 error: `#[must_use]` attribute cannot be used on struct fields
-  --> $DIR/unused_attributes-must_use.rs:155:28
+  --> $DIR/unused_attributes-must_use.rs:157:28
    |
 LL |     let s = PatternField { #[must_use]  foo: 123 };
    |                            ^^^^^^^^^^^
@@ -196,7 +193,7 @@ LL |     let s = PatternField { #[must_use]  foo: 123 };
    = help: `#[must_use]` can be applied to functions, data types, unions, and traits
 
 error: `#[must_use]` attribute cannot be used on pattern fields
-  --> $DIR/unused_attributes-must_use.rs:157:24
+  --> $DIR/unused_attributes-must_use.rs:159:24
    |
 LL |     let PatternField { #[must_use] foo } = s;
    |                        ^^^^^^^^^^^
@@ -205,7 +202,7 @@ LL |     let PatternField { #[must_use] foo } = s;
    = help: `#[must_use]` can be applied to functions, data types, unions, and traits
 
 error: unused `X` that must be used
-  --> $DIR/unused_attributes-must_use.rs:128:5
+  --> $DIR/unused_attributes-must_use.rs:130:5
    |
 LL |     X;
    |     ^
@@ -221,7 +218,7 @@ LL |     let _ = X;
    |     +++++++
 
 error: unused `Y` that must be used
-  --> $DIR/unused_attributes-must_use.rs:129:5
+  --> $DIR/unused_attributes-must_use.rs:131:5
    |
 LL |     Y::Z;
    |     ^^^^
@@ -232,7 +229,7 @@ LL |     let _ = Y::Z;
    |     +++++++
 
 error: unused `U` that must be used
-  --> $DIR/unused_attributes-must_use.rs:130:5
+  --> $DIR/unused_attributes-must_use.rs:132:5
    |
 LL |     U { unit: () };
    |     ^^^^^^^^^^^^^^
@@ -243,7 +240,7 @@ LL |     let _ = U { unit: () };
    |     +++++++
 
 error: unused return value of `U::method` that must be used
-  --> $DIR/unused_attributes-must_use.rs:131:5
+  --> $DIR/unused_attributes-must_use.rs:133:5
    |
 LL |     U::method();
    |     ^^^^^^^^^^^
@@ -254,7 +251,7 @@ LL |     let _ = U::method();
    |     +++++++
 
 error: unused return value of `foo` that must be used
-  --> $DIR/unused_attributes-must_use.rs:132:5
+  --> $DIR/unused_attributes-must_use.rs:134:5
    |
 LL |     foo();
    |     ^^^^^
@@ -265,7 +262,7 @@ LL |     let _ = foo();
    |     +++++++
 
 error: unused return value of `foreign_foo` that must be used
-  --> $DIR/unused_attributes-must_use.rs:135:9
+  --> $DIR/unused_attributes-must_use.rs:137:9
    |
 LL |         foreign_foo();
    |         ^^^^^^^^^^^^^
@@ -276,7 +273,7 @@ LL |         let _ = foreign_foo();
    |         +++++++
 
 error: unused return value of `Use::get_four` that must be used
-  --> $DIR/unused_attributes-must_use.rs:143:5
+  --> $DIR/unused_attributes-must_use.rs:145:5
    |
 LL |     ().get_four();
    |     ^^^^^^^^^^^^^
diff --git a/tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr b/tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr
index c14ab9e11e0..8a5c243ddf8 100644
--- a/tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr
+++ b/tests/ui/lint/use-redundant/use-redundant-issue-71450.stderr
@@ -3,10 +3,10 @@ warning: the item `String` is imported redundantly
    |
 LL |         use std::string::String;
    |             ^^^^^^^^^^^^^^^^^^^
+   |
   --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
    |
    = note: the item `String` is already defined here
-   |
 note: the lint level is defined here
   --> $DIR/use-redundant-issue-71450.rs:3:9
    |
diff --git a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.stderr b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.stderr
index 48d5c275055..71bc7d3b371 100644
--- a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.stderr
+++ b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2015.stderr
@@ -3,10 +3,10 @@ warning: the item `Some` is imported redundantly
    |
 LL | use std::option::Option::Some;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
   --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
    |
    = note: the item `Some` is already defined here
-   |
 note: the lint level is defined here
   --> $DIR/use-redundant-prelude-rust-2015.rs:3:9
    |
@@ -18,6 +18,7 @@ warning: the item `None` is imported redundantly
    |
 LL | use std::option::Option::None;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
   --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
    |
    = note: the item `None` is already defined here
@@ -27,6 +28,7 @@ warning: the item `Ok` is imported redundantly
    |
 LL | use std::result::Result::Ok;
    |     ^^^^^^^^^^^^^^^^^^^^^^^
+   |
   --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
    |
    = note: the item `Ok` is already defined here
@@ -36,6 +38,7 @@ warning: the item `Err` is imported redundantly
    |
 LL | use std::result::Result::Err;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
   --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
    |
    = note: the item `Err` is already defined here
diff --git a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.stderr b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.stderr
index 526771c597a..f9b7af2105c 100644
--- a/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.stderr
+++ b/tests/ui/lint/use-redundant/use-redundant-prelude-rust-2021.stderr
@@ -3,10 +3,10 @@ warning: the item `TryFrom` is imported redundantly
    |
 LL | use std::convert::TryFrom;
    |     ^^^^^^^^^^^^^^^^^^^^^
+   |
   --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
    |
    = note: the item `TryFrom` is already defined here
-   |
 note: the lint level is defined here
   --> $DIR/use-redundant-prelude-rust-2021.rs:3:9
    |
@@ -18,6 +18,7 @@ warning: the item `TryInto` is imported redundantly
    |
 LL | use std::convert::TryInto;
    |     ^^^^^^^^^^^^^^^^^^^^^
+   |
   --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL
    |
    = note: the item `TryInto` is already defined here
diff --git a/tests/ui/macros/format-foreign-dollar-without-spec.rs b/tests/ui/macros/format-foreign-dollar-without-spec.rs
new file mode 100644
index 00000000000..c57c1382c8d
--- /dev/null
+++ b/tests/ui/macros/format-foreign-dollar-without-spec.rs
@@ -0,0 +1,5 @@
+// https://github.com/rust-lang/rust/issues/137580
+fn main() {
+    println!("%65536$", 1);
+    //~^ ERROR never used
+}
diff --git a/tests/ui/macros/format-foreign-dollar-without-spec.stderr b/tests/ui/macros/format-foreign-dollar-without-spec.stderr
new file mode 100644
index 00000000000..d5a07c50f00
--- /dev/null
+++ b/tests/ui/macros/format-foreign-dollar-without-spec.stderr
@@ -0,0 +1,16 @@
+error: argument never used
+  --> $DIR/format-foreign-dollar-without-spec.rs:3:25
+   |
+LL |     println!("%65536$", 1);
+   |                         ^ argument never used
+   |
+note: format specifiers use curly braces, and the conversion specifier `
+      ` is unknown or unsupported
+  --> $DIR/format-foreign-dollar-without-spec.rs:3:15
+   |
+LL |     println!("%65536$", 1);
+   |               ^^^^^^^^
+   = note: printf formatting is not supported; see the documentation for `std::fmt`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/macros/macro-name-typo.stderr b/tests/ui/macros/macro-name-typo.stderr
index 9059b10faaa..1cc7ea6ec1b 100644
--- a/tests/ui/macros/macro-name-typo.stderr
+++ b/tests/ui/macros/macro-name-typo.stderr
@@ -3,6 +3,7 @@ error: cannot find macro `printlx` in this scope
    |
 LL |     printlx!("oh noes!");
    |     ^^^^^^^ help: a macro with a similar name exists: `println`
+   |
   --> $SRC_DIR/std/src/macros.rs:LL:COL
    |
    = note: similarly named macro `println` defined here
diff --git a/tests/ui/macros/macro-path-prelude-fail-3.stderr b/tests/ui/macros/macro-path-prelude-fail-3.stderr
index 485d7b7869a..3d0a074deeb 100644
--- a/tests/ui/macros/macro-path-prelude-fail-3.stderr
+++ b/tests/ui/macros/macro-path-prelude-fail-3.stderr
@@ -3,6 +3,7 @@ error: cannot find macro `inline` in this scope
    |
 LL |     inline!();
    |     ^^^^^^ help: a macro with a similar name exists: `line`
+   |
   --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
    |
    = note: similarly named macro `line` defined here
diff --git a/tests/ui/macros/missing-writer-issue-139830.stderr b/tests/ui/macros/missing-writer-issue-139830.stderr
index 34dd61328e0..0a1c6f6f3ea 100644
--- a/tests/ui/macros/missing-writer-issue-139830.stderr
+++ b/tests/ui/macros/missing-writer-issue-139830.stderr
@@ -3,10 +3,10 @@ error[E0599]: cannot write into `String`
    |
 LL |     let _ = write!(buf, "foo");
    |                    ^^^
+   |
   --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
    |
    = note: the method is available for `String` here
-   |
 note: must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method
   --> $DIR/missing-writer-issue-139830.rs:7:20
    |
diff --git a/tests/ui/malformed/malformed-regressions.rs b/tests/ui/malformed/malformed-regressions.rs
index 99f0fc904a9..407920c4e4e 100644
--- a/tests/ui/malformed/malformed-regressions.rs
+++ b/tests/ui/malformed/malformed-regressions.rs
@@ -4,9 +4,7 @@
 //~^ WARN this was previously accepted
 #[inline = ""] //~ ERROR valid forms for the attribute are
 //~^ WARN this was previously accepted
-#[link] //~ ERROR valid forms for the attribute are
-//~^ WARN this was previously accepted
-#[link = ""] //~ ERROR valid forms for the attribute are
-//~^ WARN this was previously accepted
+#[link] //~ ERROR malformed
+#[link = ""] //~ ERROR malformed
 
 fn main() {}
diff --git a/tests/ui/malformed/malformed-regressions.stderr b/tests/ui/malformed/malformed-regressions.stderr
index cab347a8062..850bcb6cbc2 100644
--- a/tests/ui/malformed/malformed-regressions.stderr
+++ b/tests/ui/malformed/malformed-regressions.stderr
@@ -9,25 +9,47 @@ LL | #[doc]
    = note: for more information, visit <https://doc.rust-lang.org/rustdoc/write-documentation/the-doc-attribute.html>
    = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default
 
-error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`
+error[E0539]: malformed `link` attribute input
   --> $DIR/malformed-regressions.rs:7:1
    |
 LL | #[link]
-   | ^^^^^^^
+   | ^^^^^^^ expected this to be a list
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
    = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL | #[link(name = "...")]
+   |       ++++++++++++++
+LL | #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |       +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+LL | #[link(name = "...", kind = "dylib|static|...")]
+   |       +++++++++++++++++++++++++++++++++++++++++
+LL | #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |       ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+   = and 1 other candidate
 
-error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`
-  --> $DIR/malformed-regressions.rs:9:1
+error[E0539]: malformed `link` attribute input
+  --> $DIR/malformed-regressions.rs:8:1
    |
 LL | #[link = ""]
-   | ^^^^^^^^^^^^
+   | ^^^^^^^^^^^^ expected this to be a list
    |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
    = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link = ""]
+LL + #[link(name = "...")]
+   |
+LL - #[link = ""]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link = ""]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link = ""]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
 
 error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]`
   --> $DIR/malformed-regressions.rs:3:1
@@ -49,6 +71,7 @@ LL | #[inline = ""]
 
 error: aborting due to 5 previous errors
 
+For more information about this error, try `rustc --explain E0539`.
 Future incompatibility report: Future breakage diagnostic:
 error: valid forms for the attribute are `#[doc(hidden)]`, `#[doc(inline)]`, and `#[doc = "string"]`
   --> $DIR/malformed-regressions.rs:1:1
@@ -62,30 +85,6 @@ LL | #[doc]
    = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default
 
 Future breakage diagnostic:
-error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`
-  --> $DIR/malformed-regressions.rs:7:1
-   |
-LL | #[link]
-   | ^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
-   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
-   = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default
-
-Future breakage diagnostic:
-error: valid forms for the attribute are `#[link(name = "...")]`, `#[link(name = "...", kind = "dylib|static|...")]`, `#[link(name = "...", wasm_import_module = "...")]`, `#[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]`, and `#[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]`
-  --> $DIR/malformed-regressions.rs:9:1
-   |
-LL | #[link = ""]
-   | ^^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #57571 <https://github.com/rust-lang/rust/issues/57571>
-   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
-   = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default
-
-Future breakage diagnostic:
 error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]`
   --> $DIR/malformed-regressions.rs:3:1
    |
diff --git a/tests/ui/methods/method-call-lifetime-args-unresolved.stderr b/tests/ui/methods/method-call-lifetime-args-unresolved.stderr
index a87c47a9f12..cc8bd18449a 100644
--- a/tests/ui/methods/method-call-lifetime-args-unresolved.stderr
+++ b/tests/ui/methods/method-call-lifetime-args-unresolved.stderr
@@ -14,6 +14,7 @@ warning: cannot specify lifetime arguments explicitly if late bound lifetime par
    |
 LL |     0.clone::<'a>();
    |               ^^
+   |
   --> $SRC_DIR/core/src/clone.rs:LL:COL
    |
    = note: the late bound lifetime parameter is introduced here
diff --git a/tests/ui/methods/rigid-alias-bound-is-not-inherent-2.rs b/tests/ui/methods/rigid-alias-bound-is-not-inherent-2.rs
new file mode 100644
index 00000000000..8363ec1b3fb
--- /dev/null
+++ b/tests/ui/methods/rigid-alias-bound-is-not-inherent-2.rs
@@ -0,0 +1,17 @@
+// Regression test for <github.com/rust-lang/rust/issues/145185>.
+
+mod module {
+    pub trait Trait {
+        fn method(&self);
+    }
+}
+
+// Note that we do not import Trait
+use std::ops::Deref;
+
+fn foo(x: impl Deref<Target: module::Trait>) {
+    x.method();
+    //~^ ERROR no method named `method` found for type parameter
+}
+
+fn main() {}
diff --git a/tests/ui/methods/rigid-alias-bound-is-not-inherent-2.stderr b/tests/ui/methods/rigid-alias-bound-is-not-inherent-2.stderr
new file mode 100644
index 00000000000..433cab9cf9e
--- /dev/null
+++ b/tests/ui/methods/rigid-alias-bound-is-not-inherent-2.stderr
@@ -0,0 +1,17 @@
+error[E0599]: no method named `method` found for type parameter `impl Deref<Target : module::Trait>` in the current scope
+  --> $DIR/rigid-alias-bound-is-not-inherent-2.rs:13:7
+   |
+LL | fn foo(x: impl Deref<Target: module::Trait>) {
+   |           --------------------------------- method `method` not found for this type parameter
+LL |     x.method();
+   |       ^^^^^^ method not found in `impl Deref<Target : module::Trait>`
+   |
+   = help: items from traits can only be used if the trait is in scope
+help: trait `Trait` which provides `method` is implemented but not in scope; perhaps you want to import it
+   |
+LL + use module::Trait;
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/methods/rigid-alias-bound-is-not-inherent-3.rs b/tests/ui/methods/rigid-alias-bound-is-not-inherent-3.rs
new file mode 100644
index 00000000000..bb316eed34d
--- /dev/null
+++ b/tests/ui/methods/rigid-alias-bound-is-not-inherent-3.rs
@@ -0,0 +1,26 @@
+use std::ops::Deref;
+
+trait Trait1 {
+    fn call_me(&self) {}
+}
+
+impl<T> Trait1 for T {}
+
+trait Trait2 {
+    fn call_me(&self) {}
+}
+
+impl<T> Trait2 for T {}
+
+pub fn foo<T, U>(x: T)
+where
+    T: Deref<Target = U>,
+    U: Trait1,
+{
+    // This should be ambiguous. The fact that there's an inherent where-bound
+    // candidate for `U` should not impact the candidates for `T`
+    x.call_me();
+    //~^ ERROR multiple applicable items in scope
+}
+
+fn main() {}
diff --git a/tests/ui/methods/rigid-alias-bound-is-not-inherent-3.stderr b/tests/ui/methods/rigid-alias-bound-is-not-inherent-3.stderr
new file mode 100644
index 00000000000..466ad4d2abc
--- /dev/null
+++ b/tests/ui/methods/rigid-alias-bound-is-not-inherent-3.stderr
@@ -0,0 +1,30 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/rigid-alias-bound-is-not-inherent-3.rs:22:7
+   |
+LL |     x.call_me();
+   |       ^^^^^^^ multiple `call_me` found
+   |
+note: candidate #1 is defined in an impl of the trait `Trait1` for the type `T`
+  --> $DIR/rigid-alias-bound-is-not-inherent-3.rs:4:5
+   |
+LL |     fn call_me(&self) {}
+   |     ^^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl of the trait `Trait2` for the type `T`
+  --> $DIR/rigid-alias-bound-is-not-inherent-3.rs:10:5
+   |
+LL |     fn call_me(&self) {}
+   |     ^^^^^^^^^^^^^^^^^
+help: disambiguate the method for candidate #1
+   |
+LL -     x.call_me();
+LL +     Trait1::call_me(&x);
+   |
+help: disambiguate the method for candidate #2
+   |
+LL -     x.call_me();
+LL +     Trait2::call_me(&x);
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/methods/rigid-alias-bound-is-not-inherent.current.stderr b/tests/ui/methods/rigid-alias-bound-is-not-inherent.current.stderr
new file mode 100644
index 00000000000..4652bf5e3c5
--- /dev/null
+++ b/tests/ui/methods/rigid-alias-bound-is-not-inherent.current.stderr
@@ -0,0 +1,30 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/rigid-alias-bound-is-not-inherent.rs:42:7
+   |
+LL |     x.method();
+   |       ^^^^^^ multiple `method` found
+   |
+note: candidate #1 is defined in the trait `Trait1`
+  --> $DIR/rigid-alias-bound-is-not-inherent.rs:21:5
+   |
+LL |     fn method(&self) {
+   |     ^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in an impl of the trait `Trait2` for the type `T`
+  --> $DIR/rigid-alias-bound-is-not-inherent.rs:27:5
+   |
+LL |     fn method(&self) {
+   |     ^^^^^^^^^^^^^^^^
+help: disambiguate the method for candidate #1
+   |
+LL -     x.method();
+LL +     Trait1::method(&x);
+   |
+help: disambiguate the method for candidate #2
+   |
+LL -     x.method();
+LL +     Trait2::method(&x);
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/methods/rigid-alias-bound-is-not-inherent.next.stderr b/tests/ui/methods/rigid-alias-bound-is-not-inherent.next.stderr
new file mode 100644
index 00000000000..afacb3a7d52
--- /dev/null
+++ b/tests/ui/methods/rigid-alias-bound-is-not-inherent.next.stderr
@@ -0,0 +1,30 @@
+error[E0034]: multiple applicable items in scope
+  --> $DIR/rigid-alias-bound-is-not-inherent.rs:42:7
+   |
+LL |     x.method();
+   |       ^^^^^^ multiple `method` found
+   |
+note: candidate #1 is defined in the trait `Trait1`
+  --> $DIR/rigid-alias-bound-is-not-inherent.rs:21:5
+   |
+LL |     fn method(&self) {
+   |     ^^^^^^^^^^^^^^^^
+note: candidate #2 is defined in the trait `Trait2`
+  --> $DIR/rigid-alias-bound-is-not-inherent.rs:27:5
+   |
+LL |     fn method(&self) {
+   |     ^^^^^^^^^^^^^^^^
+help: disambiguate the method for candidate #1
+   |
+LL -     x.method();
+LL +     Trait1::method(&x);
+   |
+help: disambiguate the method for candidate #2
+   |
+LL -     x.method();
+LL +     Trait2::method(&x);
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0034`.
diff --git a/tests/ui/methods/rigid-alias-bound-is-not-inherent.rs b/tests/ui/methods/rigid-alias-bound-is-not-inherent.rs
new file mode 100644
index 00000000000..3dd63df3f39
--- /dev/null
+++ b/tests/ui/methods/rigid-alias-bound-is-not-inherent.rs
@@ -0,0 +1,46 @@
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+// See the code below.
+//
+// We were using `DeepRejectCtxt` to ensure that `assemble_inherent_candidates_from_param`
+// did not rely on the param-env being eagerly normalized. Since aliases unify with all
+// types, this meant that a rigid param-env candidate like `<T as Deref>::Target: Trait1`
+// would be registered as a "WhereClauseCandidate", which is treated as inherent. Since
+// we evaluate these candidates for all self types in the deref chain, this candidate
+// would be satisfied for `<T as Deref>::Target`, meaning that it would be preferred over
+// an "extension" candidate like `<T as Deref>::Target: Trait2` even though it holds.
+// This is problematic, since it causes ambiguities to be broken somewhat arbitrarily.
+// And as a side-effect, it also caused our computation of "used" traits to be miscalculated
+// since inherent candidates don't count as an import usage.
+
+use std::ops::Deref;
+
+trait Trait1 {
+    fn method(&self) {
+        println!("1");
+    }
+}
+
+trait Trait2 {
+    fn method(&self) {
+        println!("2");
+    }
+}
+impl<T: Other + ?Sized> Trait2 for T {}
+
+trait Other {}
+
+fn foo<T>(x: T)
+where
+    T: Deref,
+    <T as Deref>::Target: Trait1 + Other,
+{
+    // Make sure that we don't prefer methods from where clauses for rigid aliases,
+    // just for params. We could revisit this behavior, but it would be a lang change.
+    x.method();
+    //~^ ERROR multiple applicable items in scope
+}
+
+fn main() {}
diff --git a/tests/ui/mir/validate/ice-zst-as-discr-145786.rs b/tests/ui/mir/validate/ice-zst-as-discr-145786.rs
new file mode 100644
index 00000000000..616736bcf12
--- /dev/null
+++ b/tests/ui/mir/validate/ice-zst-as-discr-145786.rs
@@ -0,0 +1,14 @@
+// Do not attempt to take the discriminant as the source
+// converted to a `u128`, that won't work for ZST.
+//
+//@ compile-flags: -Zvalidate-mir
+
+enum A {
+    B,
+    C,
+}
+
+fn main() {
+    let _: A = unsafe { std::mem::transmute(()) };
+    //~^ ERROR cannot transmute between types of different sizes, or dependently-sized types
+}
diff --git a/tests/ui/mir/validate/ice-zst-as-discr-145786.stderr b/tests/ui/mir/validate/ice-zst-as-discr-145786.stderr
new file mode 100644
index 00000000000..b0bca1eb39c
--- /dev/null
+++ b/tests/ui/mir/validate/ice-zst-as-discr-145786.stderr
@@ -0,0 +1,12 @@
+error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
+  --> $DIR/ice-zst-as-discr-145786.rs:12:25
+   |
+LL |     let _: A = unsafe { std::mem::transmute(()) };
+   |                         ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: source type: `()` (0 bits)
+   = note: target type: `A` (8 bits)
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0512`.
diff --git a/tests/ui/mismatched_types/hr-projection-mismatch.current.stderr b/tests/ui/mismatched_types/hr-projection-mismatch.current.stderr
index a2cec972e4a..6bda7840f7b 100644
--- a/tests/ui/mismatched_types/hr-projection-mismatch.current.stderr
+++ b/tests/ui/mismatched_types/hr-projection-mismatch.current.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/hr-projection-mismatch.rs:20:5
    |
 LL |     wrap::<_, Thing>();
-   |     ^^^^^^^^^^^^^^^^ one type is more general than the other
+   |     ^^^^^^^^^^^^^^^^^^ one type is more general than the other
    |
    = note: expected reference `&'a _`
               found reference `&_`
diff --git a/tests/ui/nll/ice-106874.stderr b/tests/ui/nll/ice-106874.stderr
index ead4d490a62..0edbd7b44ef 100644
--- a/tests/ui/nll/ice-106874.stderr
+++ b/tests/ui/nll/ice-106874.stderr
@@ -17,6 +17,15 @@ LL |     A(B(C::new(D::new(move |st| f(st)))))
    = note: ...but it actually implements `FnOnce<(&'1 mut V,)>`, for some specific lifetime `'1`
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
+error: implementation of `FnOnce` is not general enough
+  --> $DIR/ice-106874.rs:8:7
+   |
+LL |     A(B(C::new(D::new(move |st| f(st)))))
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
+   |
+   = note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`...
+   = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2`
+
 error: implementation of `Fn` is not general enough
   --> $DIR/ice-106874.rs:8:7
    |
@@ -34,6 +43,7 @@ LL |     A(B(C::new(D::new(move |st| f(st)))))
    |
    = note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`...
    = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: implementation of `Fn` is not general enough
   --> $DIR/ice-106874.rs:8:7
@@ -46,45 +56,36 @@ LL |     A(B(C::new(D::new(move |st| f(st)))))
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: implementation of `FnOnce` is not general enough
-  --> $DIR/ice-106874.rs:8:9
+  --> $DIR/ice-106874.rs:8:7
    |
 LL |     A(B(C::new(D::new(move |st| f(st)))))
-   |         ^^^^^^ implementation of `FnOnce` is not general enough
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
    |
    = note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`...
    = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: implementation of `Fn` is not general enough
-  --> $DIR/ice-106874.rs:8:9
+  --> $DIR/ice-106874.rs:8:7
    |
 LL |     A(B(C::new(D::new(move |st| f(st)))))
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough
    |
    = note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`...
    = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2`
-
-error: implementation of `FnOnce` is not general enough
-  --> $DIR/ice-106874.rs:8:9
-   |
-LL |     A(B(C::new(D::new(move |st| f(st)))))
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough
-   |
-   = note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`...
-   = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2`
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: higher-ranked subtype error
-  --> $DIR/ice-106874.rs:8:41
+  --> $DIR/ice-106874.rs:8:7
    |
 LL |     A(B(C::new(D::new(move |st| f(st)))))
-   |                                         ^
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: higher-ranked subtype error
   --> $DIR/ice-106874.rs:8:41
    |
 LL |     A(B(C::new(D::new(move |st| f(st)))))
    |                                         ^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 10 previous errors
 
diff --git a/tests/ui/nll/missing-universe-cause-issue-114907.stderr b/tests/ui/nll/missing-universe-cause-issue-114907.stderr
index 26ad1efec05..c2e91edd138 100644
--- a/tests/ui/nll/missing-universe-cause-issue-114907.stderr
+++ b/tests/ui/nll/missing-universe-cause-issue-114907.stderr
@@ -38,18 +38,16 @@ LL |     accept(callback);
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: higher-ranked subtype error
-  --> $DIR/missing-universe-cause-issue-114907.rs:33:21
+  --> $DIR/missing-universe-cause-issue-114907.rs:33:5
    |
 LL |     accept(callback);
-   |                     ^
+   |     ^^^^^^^^^^^^^^^^
 
 error: higher-ranked subtype error
   --> $DIR/missing-universe-cause-issue-114907.rs:33:21
    |
 LL |     accept(callback);
    |                     ^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: aborting due to 6 previous errors
 
diff --git a/tests/ui/or-patterns/exhaustiveness-non-exhaustive.rs b/tests/ui/or-patterns/exhaustiveness-non-exhaustive.rs
index 5999e04e0e2..9c0b2648384 100644
--- a/tests/ui/or-patterns/exhaustiveness-non-exhaustive.rs
+++ b/tests/ui/or-patterns/exhaustiveness-non-exhaustive.rs
@@ -7,11 +7,11 @@ fn main() {
         (0 | 1, 2 | 3) => {}
     }
     match ((0u8,),) {
-        //~^ ERROR non-exhaustive patterns: `((4_u8..=u8::MAX))`
+        //~^ ERROR non-exhaustive patterns: `((4_u8..=u8::MAX,),)`
         ((0 | 1,) | (2 | 3,),) => {}
     }
     match (Some(0u8),) {
-        //~^ ERROR non-exhaustive patterns: `(Some(2_u8..=u8::MAX))`
+        //~^ ERROR non-exhaustive patterns: `(Some(2_u8..=u8::MAX),)`
         (None | Some(0 | 1),) => {}
     }
 }
diff --git a/tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr b/tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr
index 9f691aea8a7..fe3a4aa2afc 100644
--- a/tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr
+++ b/tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr
@@ -11,30 +11,30 @@ LL ~         (0 | 1, 2 | 3) => {},
 LL +         (2_u8..=u8::MAX, _) => todo!()
    |
 
-error[E0004]: non-exhaustive patterns: `((4_u8..=u8::MAX))` not covered
+error[E0004]: non-exhaustive patterns: `((4_u8..=u8::MAX,),)` not covered
   --> $DIR/exhaustiveness-non-exhaustive.rs:9:11
    |
 LL |     match ((0u8,),) {
-   |           ^^^^^^^^^ pattern `((4_u8..=u8::MAX))` not covered
+   |           ^^^^^^^^^ pattern `((4_u8..=u8::MAX,),)` not covered
    |
    = note: the matched value is of type `((u8,),)`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
 LL ~         ((0 | 1,) | (2 | 3,),) => {},
-LL +         ((4_u8..=u8::MAX)) => todo!()
+LL +         ((4_u8..=u8::MAX,),) => todo!()
    |
 
-error[E0004]: non-exhaustive patterns: `(Some(2_u8..=u8::MAX))` not covered
+error[E0004]: non-exhaustive patterns: `(Some(2_u8..=u8::MAX),)` not covered
   --> $DIR/exhaustiveness-non-exhaustive.rs:13:11
    |
 LL |     match (Some(0u8),) {
-   |           ^^^^^^^^^^^^ pattern `(Some(2_u8..=u8::MAX))` not covered
+   |           ^^^^^^^^^^^^ pattern `(Some(2_u8..=u8::MAX),)` not covered
    |
    = note: the matched value is of type `(Option<u8>,)`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
 LL ~         (None | Some(0 | 1),) => {},
-LL +         (Some(2_u8..=u8::MAX)) => todo!()
+LL +         (Some(2_u8..=u8::MAX),) => todo!()
    |
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/panics/issue-47429-short-backtraces.rs b/tests/ui/panics/issue-47429-short-backtraces.rs
index 378ade67bfd..21428d876e2 100644
--- a/tests/ui/panics/issue-47429-short-backtraces.rs
+++ b/tests/ui/panics/issue-47429-short-backtraces.rs
@@ -6,6 +6,9 @@
 //@ check-run-results
 //@ exec-env:RUST_BACKTRACE=1
 
+// FIXME(#61117): Respect debuginfo-level-tests, do not force debuginfo-level=0
+//@ compile-flags: -Cdebuginfo=0
+
 // This is needed to avoid test output differences across std being built with v0 symbols vs legacy
 // symbols.
 //@ normalize-stderr: "begin_panic::<&str>" -> "begin_panic"
diff --git a/tests/ui/panics/issue-47429-short-backtraces.run.stderr b/tests/ui/panics/issue-47429-short-backtraces.run.stderr
index 13b59a7c7af..32aa6a3502e 100644
--- a/tests/ui/panics/issue-47429-short-backtraces.run.stderr
+++ b/tests/ui/panics/issue-47429-short-backtraces.run.stderr
@@ -1,5 +1,5 @@
 
-thread 'main' ($TID) panicked at $DIR/issue-47429-short-backtraces.rs:24:5:
+thread 'main' ($TID) panicked at $DIR/issue-47429-short-backtraces.rs:27:5:
 explicit panic
 stack backtrace:
    0: std::panicking::begin_panic
diff --git a/tests/ui/panics/runtime-switch.rs b/tests/ui/panics/runtime-switch.rs
index 7d5b4169340..61c07a97c70 100644
--- a/tests/ui/panics/runtime-switch.rs
+++ b/tests/ui/panics/runtime-switch.rs
@@ -6,6 +6,9 @@
 //@ check-run-results
 //@ exec-env:RUST_BACKTRACE=0
 
+// FIXME(#61117): Respect debuginfo-level-tests, do not force debuginfo-level=0
+//@ compile-flags: -Cdebuginfo=0
+
 // This is needed to avoid test output differences across std being built with v0 symbols vs legacy
 // symbols.
 //@ normalize-stderr: "begin_panic::<&str>" -> "begin_panic"
diff --git a/tests/ui/panics/runtime-switch.run.stderr b/tests/ui/panics/runtime-switch.run.stderr
index f3f60445952..48a12b59b69 100644
--- a/tests/ui/panics/runtime-switch.run.stderr
+++ b/tests/ui/panics/runtime-switch.run.stderr
@@ -1,5 +1,5 @@
 
-thread 'main' ($TID) panicked at $DIR/runtime-switch.rs:28:5:
+thread 'main' ($TID) panicked at $DIR/runtime-switch.rs:31:5:
 explicit panic
 stack backtrace:
    0: std::panicking::begin_panic
diff --git a/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.rs b/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.rs
index 73d173022f6..a357040a4e4 100644
--- a/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.rs
+++ b/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.rs
@@ -1,16 +1,18 @@
+// Test for #111528, the ice issue cause waiting on a query that panicked
+//
 //@ compile-flags: -Z threads=16
 //@ build-fail
+//@ compare-output-by-lines
 
-#![crate_type="rlib"]
+#![crate_type = "rlib"]
 #![allow(warnings)]
 
-#[export_name="fail"]
-pub fn a() {
-}
+#[export_name = "fail"]
+pub fn a() {}
 
-#[export_name="fail"]
+#[export_name = "fail"]
 pub fn b() {
-//~^ ERROR symbol `fail` is already defined
+    //~^ ERROR symbol `fail` is already defined
 }
 
 fn main() {}
diff --git a/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.stderr b/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.stderr
index 7963165e31b..80f63733fb3 100644
--- a/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.stderr
+++ b/tests/ui/parallel-rustc/cache-after-waiting-issue-111528.stderr
@@ -1,5 +1,5 @@
 error: symbol `fail` is already defined
-  --> $DIR/cache-after-waiting-issue-111528.rs:12:1
+  --> $DIR/cache-after-waiting-issue-111528.rs:14:1
    |
 LL | pub fn b() {
    | ^^^^^^^^^^
diff --git a/tests/ui/parallel-rustc/cycle_crash-issue-135870.rs b/tests/ui/parallel-rustc/cycle_crash-issue-135870.rs
new file mode 100644
index 00000000000..4407e3aca80
--- /dev/null
+++ b/tests/ui/parallel-rustc/cycle_crash-issue-135870.rs
@@ -0,0 +1,8 @@
+// Test for #135870, which causes a deadlock bug
+//
+//@ compile-flags: -Z threads=2
+//@ compare-output-by-lines
+
+const FOO: usize = FOO; //~ ERROR cycle detected when simplifying constant for the type system `FOO`
+
+fn main() {}
diff --git a/tests/ui/parallel-rustc/cycle_crash.stderr b/tests/ui/parallel-rustc/cycle_crash-issue-135870.stderr
index 7af3b8ee532..6e588d1f894 100644
--- a/tests/ui/parallel-rustc/cycle_crash.stderr
+++ b/tests/ui/parallel-rustc/cycle_crash-issue-135870.stderr
@@ -1,11 +1,11 @@
 error[E0391]: cycle detected when simplifying constant for the type system `FOO`
-  --> $DIR/cycle_crash.rs:3:1
+  --> $DIR/cycle_crash-issue-135870.rs:6:1
    |
 LL | const FOO: usize = FOO;
    | ^^^^^^^^^^^^^^^^
    |
 note: ...which requires const-evaluating + checking `FOO`...
-  --> $DIR/cycle_crash.rs:3:20
+  --> $DIR/cycle_crash-issue-135870.rs:6:20
    |
 LL | const FOO: usize = FOO;
    |                    ^^^
diff --git a/tests/ui/parallel-rustc/cycle_crash.rs b/tests/ui/parallel-rustc/cycle_crash.rs
deleted file mode 100644
index 94ae11aef39..00000000000
--- a/tests/ui/parallel-rustc/cycle_crash.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-//@ compile-flags: -Z threads=2
-
-const FOO: usize = FOO; //~ERROR cycle detected when simplifying constant for the type system `FOO`
-
-fn main() {}
diff --git a/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205-2.rs b/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205-2.rs
index 024df728736..523b1b2d1f3 100644
--- a/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205-2.rs
+++ b/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205-2.rs
@@ -1,6 +1,10 @@
+// Test for #118205, which causes a deadlock bug
+//
 //@ compile-flags:-C extra-filename=-1 -Z threads=16
 //@ no-prefer-dynamic
 //@ build-pass
+//@ compare-output-by-lines
+
 #![crate_name = "crateresolve1"]
 #![crate_type = "lib"]
 
diff --git a/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205.rs b/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205.rs
index 3ccc1ea5f10..65f99c30643 100644
--- a/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205.rs
+++ b/tests/ui/parallel-rustc/export-symbols-deadlock-issue-118205.rs
@@ -1,5 +1,8 @@
+// Test for #118205, which causes a deadlock bug
+//
 //@ compile-flags: -Z threads=16
 //@ build-pass
+//@ compare-output-by-lines
 
 pub static GLOBAL: isize = 3;
 
diff --git a/tests/ui/parallel-rustc/hello_world.rs b/tests/ui/parallel-rustc/hello_world.rs
index 56698fe2489..57891b92da0 100644
--- a/tests/ui/parallel-rustc/hello_world.rs
+++ b/tests/ui/parallel-rustc/hello_world.rs
@@ -1,5 +1,8 @@
+// Test for the basic function of parallel front end
+//
 //@ compile-flags: -Z threads=8
 //@ run-pass
+//@ compare-output-by-lines
 
 fn main() {
     println!("Hello world!");
diff --git a/tests/ui/parallel-rustc/read-stolen-value-issue-111520.rs b/tests/ui/parallel-rustc/read-stolen-value-issue-111520.rs
index ea8ecb67859..a6b37e62913 100644
--- a/tests/ui/parallel-rustc/read-stolen-value-issue-111520.rs
+++ b/tests/ui/parallel-rustc/read-stolen-value-issue-111520.rs
@@ -1,18 +1,21 @@
+// Test for #111520, which causes an ice bug cause of reading stolen value
+//
 //@ compile-flags: -Z threads=16
 //@ run-pass
+//@ compare-output-by-lines
 
 #[repr(transparent)]
 struct Sched {
     i: i32,
 }
 impl Sched {
-    extern "C" fn get(self) -> i32 { self.i }
+    extern "C" fn get(self) -> i32 {
+        self.i
+    }
 }
 
 fn main() {
     let s = Sched { i: 4 };
-    let f = || -> i32 {
-        s.get()
-    };
+    let f = || -> i32 { s.get() };
     println!("f: {}", f());
 }
diff --git a/tests/ui/parallel-rustc/ty-variance-issue-124423.rs b/tests/ui/parallel-rustc/ty-variance-issue-124423.rs
new file mode 100644
index 00000000000..8d7f29f7764
--- /dev/null
+++ b/tests/ui/parallel-rustc/ty-variance-issue-124423.rs
@@ -0,0 +1,58 @@
+// Test for #124423, which causes an ice bug: only `variances_of` returns `&[ty::Variance]`
+//
+//@ compile-flags: -Z threads=16
+//@ compare-output-by-lines
+
+use std::fmt::Debug;
+
+fn elided(_: &impl Copy + 'a) -> _ { x }
+//~^ ERROR ambiguous `+` in a type
+//~| ERROR use of undeclared lifetime name `'a`
+//~| ERROR the placeholder `_` is not allowed within types on item signatures for return types
+
+fn explicit<'b>(_: &'a impl Copy + 'a) -> impl 'a { x }
+//~^ ERROR ambiguous `+` in a type
+//~| ERROR at least one trait must be specified
+//~| ERROR use of undeclared lifetime name `'a`
+//~| ERROR use of undeclared lifetime name `'a`
+//~| ERROR use of undeclared lifetime name `'a`
+
+fn elided2( impl 'b) -> impl 'a + 'a { x }
+//~^ ERROR expected one of `:` or `|`, found `'b`
+//~| ERROR expected identifier, found keyword `impl`
+//~| ERROR at least one trait must be specified
+//~| ERROR use of undeclared lifetime name `'a`
+//~| ERROR use of undeclared lifetime name `'a`
+
+fn explicit2<'a>(_: &'a impl Copy + 'a) -> impl Copy + 'a { x }
+//~^ ERROR ambiguous `+` in a type
+
+fn foo<'a>(_: &impl Copy + 'a) -> impl 'b + 'a { x }
+//~^ ERROR ambiguous `+` in a type
+//~| ERROR at least one trait must be specified
+//~| ERROR use of undeclared lifetime name `'b`
+
+fn elided3(_: &impl Copy + 'a) -> Box<dyn 'a> { Box::new(x) }
+//~^ ERROR ambiguous `+` in a type
+//~| ERROR use of undeclared lifetime name `'a`
+//~| ERROR use of undeclared lifetime name `'a`
+//~| ERROR at least one trait is required for an object type
+
+fn x<'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+//~^ ERROR ambiguous `+` in a type
+//~| ERROR use of undeclared lifetime name `'a`
+//~| ERROR use of undeclared lifetime name `'a`
+//~| ERROR at least one trait is required for an object type
+//~| ERROR no function or associated item named `u32` found for struct `Box<_, _>` in the current scope
+
+fn elided4(_: &impl Copy + 'a) ->  new  { x(x) }
+//~^ ERROR ambiguous `+` in a type
+//~| ERROR use of undeclared lifetime name `'a`
+//~| ERROR cannot find type `new` in this scope
+
+trait LifetimeTrait<'a> {}
+
+impl<'a> LifetimeTrait<'a> for &'a Box<dyn 'a> {}
+//~^ ERROR at least one trait is required for an object type
+
+fn main() {}
diff --git a/tests/ui/parallel-rustc/ty-variance-issue-124423.stderr b/tests/ui/parallel-rustc/ty-variance-issue-124423.stderr
new file mode 100644
index 00000000000..7ba89f75bd1
--- /dev/null
+++ b/tests/ui/parallel-rustc/ty-variance-issue-124423.stderr
@@ -0,0 +1,287 @@
+error: ambiguous `+` in a type
+  --> $DIR/ty-variance-issue-124423.rs:8:15
+   |
+LL | fn elided(_: &impl Copy + 'a) -> _ { x }
+   |               ^^^^^^^^^^^^^^
+   |
+help: try adding parentheses
+   |
+LL | fn elided(_: &(impl Copy + 'a)) -> _ { x }
+   |               +              +
+
+error: ambiguous `+` in a type
+  --> $DIR/ty-variance-issue-124423.rs:13:24
+   |
+LL | fn explicit<'b>(_: &'a impl Copy + 'a) -> impl 'a { x }
+   |                        ^^^^^^^^^^^^^^
+   |
+help: try adding parentheses
+   |
+LL | fn explicit<'b>(_: &'a (impl Copy + 'a)) -> impl 'a { x }
+   |                        +              +
+
+error: expected identifier, found keyword `impl`
+  --> $DIR/ty-variance-issue-124423.rs:20:13
+   |
+LL | fn elided2( impl 'b) -> impl 'a + 'a { x }
+   |             ^^^^ expected identifier, found keyword
+
+error: expected one of `:` or `|`, found `'b`
+  --> $DIR/ty-variance-issue-124423.rs:20:18
+   |
+LL | fn elided2( impl 'b) -> impl 'a + 'a { x }
+   |                  ^^ expected one of `:` or `|`
+
+error: ambiguous `+` in a type
+  --> $DIR/ty-variance-issue-124423.rs:27:25
+   |
+LL | fn explicit2<'a>(_: &'a impl Copy + 'a) -> impl Copy + 'a { x }
+   |                         ^^^^^^^^^^^^^^
+   |
+help: try adding parentheses
+   |
+LL | fn explicit2<'a>(_: &'a (impl Copy + 'a)) -> impl Copy + 'a { x }
+   |                         +              +
+
+error: ambiguous `+` in a type
+  --> $DIR/ty-variance-issue-124423.rs:30:16
+   |
+LL | fn foo<'a>(_: &impl Copy + 'a) -> impl 'b + 'a { x }
+   |                ^^^^^^^^^^^^^^
+   |
+help: try adding parentheses
+   |
+LL | fn foo<'a>(_: &(impl Copy + 'a)) -> impl 'b + 'a { x }
+   |                +              +
+
+error: ambiguous `+` in a type
+  --> $DIR/ty-variance-issue-124423.rs:35:16
+   |
+LL | fn elided3(_: &impl Copy + 'a) -> Box<dyn 'a> { Box::new(x) }
+   |                ^^^^^^^^^^^^^^
+   |
+help: try adding parentheses
+   |
+LL | fn elided3(_: &(impl Copy + 'a)) -> Box<dyn 'a> { Box::new(x) }
+   |                +              +
+
+error: ambiguous `+` in a type
+  --> $DIR/ty-variance-issue-124423.rs:41:17
+   |
+LL | fn x<'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+   |                 ^^^^^^^^^^^^^^
+   |
+help: try adding parentheses
+   |
+LL | fn x<'b>(_: &'a (impl Copy + 'a)) -> Box<dyn 'b> { Box::u32(x) }
+   |                 +              +
+
+error: ambiguous `+` in a type
+  --> $DIR/ty-variance-issue-124423.rs:48:16
+   |
+LL | fn elided4(_: &impl Copy + 'a) ->  new  { x(x) }
+   |                ^^^^^^^^^^^^^^
+   |
+help: try adding parentheses
+   |
+LL | fn elided4(_: &(impl Copy + 'a)) ->  new  { x(x) }
+   |                +              +
+
+error: at least one trait must be specified
+  --> $DIR/ty-variance-issue-124423.rs:13:43
+   |
+LL | fn explicit<'b>(_: &'a impl Copy + 'a) -> impl 'a { x }
+   |                                           ^^^^^^^
+
+error: at least one trait must be specified
+  --> $DIR/ty-variance-issue-124423.rs:20:25
+   |
+LL | fn elided2( impl 'b) -> impl 'a + 'a { x }
+   |                         ^^^^^^^^^^^^
+
+error: at least one trait must be specified
+  --> $DIR/ty-variance-issue-124423.rs:30:35
+   |
+LL | fn foo<'a>(_: &impl Copy + 'a) -> impl 'b + 'a { x }
+   |                                   ^^^^^^^^^^^^
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/ty-variance-issue-124423.rs:8:27
+   |
+LL | fn elided(_: &impl Copy + 'a) -> _ { x }
+   |                           ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL | fn elided<'a>(_: &impl Copy + 'a) -> _ { x }
+   |          ++++
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/ty-variance-issue-124423.rs:13:21
+   |
+LL | fn explicit<'b>(_: &'a impl Copy + 'a) -> impl 'a { x }
+   |                     ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL | fn explicit<'a, 'b>(_: &'a impl Copy + 'a) -> impl 'a { x }
+   |             +++
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/ty-variance-issue-124423.rs:13:36
+   |
+LL | fn explicit<'b>(_: &'a impl Copy + 'a) -> impl 'a { x }
+   |                                    ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL | fn explicit<'a, 'b>(_: &'a impl Copy + 'a) -> impl 'a { x }
+   |             +++
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/ty-variance-issue-124423.rs:13:48
+   |
+LL | fn explicit<'b>(_: &'a impl Copy + 'a) -> impl 'a { x }
+   |                                                ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL | fn explicit<'a, 'b>(_: &'a impl Copy + 'a) -> impl 'a { x }
+   |             +++
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/ty-variance-issue-124423.rs:20:30
+   |
+LL | fn elided2( impl 'b) -> impl 'a + 'a { x }
+   |                              ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL | fn elided2<'a>( impl 'b) -> impl 'a + 'a { x }
+   |           ++++
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/ty-variance-issue-124423.rs:20:35
+   |
+LL | fn elided2( impl 'b) -> impl 'a + 'a { x }
+   |                                   ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL | fn elided2<'a>( impl 'b) -> impl 'a + 'a { x }
+   |           ++++
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/ty-variance-issue-124423.rs:30:40
+   |
+LL | fn foo<'a>(_: &impl Copy + 'a) -> impl 'b + 'a { x }
+   |                                        ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'b` here
+   |
+LL | fn foo<'b, 'a>(_: &impl Copy + 'a) -> impl 'b + 'a { x }
+   |        +++
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/ty-variance-issue-124423.rs:35:28
+   |
+LL | fn elided3(_: &impl Copy + 'a) -> Box<dyn 'a> { Box::new(x) }
+   |                            ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL | fn elided3<'a>(_: &impl Copy + 'a) -> Box<dyn 'a> { Box::new(x) }
+   |           ++++
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/ty-variance-issue-124423.rs:35:43
+   |
+LL | fn elided3(_: &impl Copy + 'a) -> Box<dyn 'a> { Box::new(x) }
+   |                                           ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL | fn elided3<'a>(_: &impl Copy + 'a) -> Box<dyn 'a> { Box::new(x) }
+   |           ++++
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/ty-variance-issue-124423.rs:41:14
+   |
+LL | fn x<'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+   |              ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL | fn x<'a, 'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+   |      +++
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/ty-variance-issue-124423.rs:41:29
+   |
+LL | fn x<'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+   |                             ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL | fn x<'a, 'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+   |      +++
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/ty-variance-issue-124423.rs:48:28
+   |
+LL | fn elided4(_: &impl Copy + 'a) ->  new  { x(x) }
+   |                            ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL | fn elided4<'a>(_: &impl Copy + 'a) ->  new  { x(x) }
+   |           ++++
+
+error[E0412]: cannot find type `new` in this scope
+  --> $DIR/ty-variance-issue-124423.rs:48:36
+   |
+LL | fn elided4(_: &impl Copy + 'a) ->  new  { x(x) }
+   |                                    ^^^ not found in this scope
+
+error[E0224]: at least one trait is required for an object type
+  --> $DIR/ty-variance-issue-124423.rs:35:39
+   |
+LL | fn elided3(_: &impl Copy + 'a) -> Box<dyn 'a> { Box::new(x) }
+   |                                       ^^^^^^
+
+error[E0224]: at least one trait is required for an object type
+  --> $DIR/ty-variance-issue-124423.rs:41:40
+   |
+LL | fn x<'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+   |                                        ^^^^^^
+
+error[E0224]: at least one trait is required for an object type
+  --> $DIR/ty-variance-issue-124423.rs:55:40
+   |
+LL | impl<'a> LifetimeTrait<'a> for &'a Box<dyn 'a> {}
+   |                                        ^^^^^^
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/ty-variance-issue-124423.rs:8:34
+   |
+LL | fn elided(_: &impl Copy + 'a) -> _ { x }
+   |                                  ^ not allowed in type signatures
+
+error[E0599]: no function or associated item named `u32` found for struct `Box<_, _>` in the current scope
+  --> $DIR/ty-variance-issue-124423.rs:41:55
+   |
+LL | fn x<'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+   |                                                       ^^^ function or associated item not found in `Box<_, _>`
+   |
+note: if you're trying to build a new `Box<_, _>` consider using one of the following associated functions:
+      Box::<T>::new
+      Box::<T>::new_uninit
+      Box::<T>::new_zeroed
+      Box::<T>::try_new
+      and 22 others
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+
+error: aborting due to 30 previous errors
+
+Some errors have detailed explanations: E0121, E0224, E0261, E0412, E0599.
+For more information about an error, try `rustc --explain E0121`.
diff --git a/tests/ui/parallel-rustc/ty-variance-issue-127971.rs b/tests/ui/parallel-rustc/ty-variance-issue-127971.rs
new file mode 100644
index 00000000000..a17916843e7
--- /dev/null
+++ b/tests/ui/parallel-rustc/ty-variance-issue-127971.rs
@@ -0,0 +1,25 @@
+// Test for #127971, which causes an ice bug: only `variances_of` returns `&[ty::Variance]`
+//
+//@ compile-flags: -Z threads=16
+//@ compare-output-by-lines
+
+use std::fmt::Debug;
+
+fn elided(_: &impl Copy + 'a) -> _ { x }
+//~^ ERROR ambiguous `+` in a type
+//~| ERROR use of undeclared lifetime name `'a`
+//~| ERROR the placeholder `_` is not allowed within types on item signatures for return types
+
+fn foo<'a>(_: &impl Copy + 'a) -> impl 'b + 'a { x }
+//~^ ERROR ambiguous `+` in a type
+//~| ERROR at least one trait must be specified
+//~| ERROR use of undeclared lifetime name `'b`
+
+fn x<'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+//~^ ERROR ambiguous `+` in a type
+//~| ERROR use of undeclared lifetime name `'a`
+//~| ERROR use of undeclared lifetime name `'a`
+//~| ERROR at least one trait is required for an object type
+//~| ERROR no function or associated item named `u32` found for struct `Box<_, _>` in the current scope
+
+fn main() {}
diff --git a/tests/ui/parallel-rustc/ty-variance-issue-127971.stderr b/tests/ui/parallel-rustc/ty-variance-issue-127971.stderr
new file mode 100644
index 00000000000..9929d3ee22c
--- /dev/null
+++ b/tests/ui/parallel-rustc/ty-variance-issue-127971.stderr
@@ -0,0 +1,113 @@
+error: ambiguous `+` in a type
+  --> $DIR/ty-variance-issue-127971.rs:8:15
+   |
+LL | fn elided(_: &impl Copy + 'a) -> _ { x }
+   |               ^^^^^^^^^^^^^^
+   |
+help: try adding parentheses
+   |
+LL | fn elided(_: &(impl Copy + 'a)) -> _ { x }
+   |               +              +
+
+error: ambiguous `+` in a type
+  --> $DIR/ty-variance-issue-127971.rs:13:16
+   |
+LL | fn foo<'a>(_: &impl Copy + 'a) -> impl 'b + 'a { x }
+   |                ^^^^^^^^^^^^^^
+   |
+help: try adding parentheses
+   |
+LL | fn foo<'a>(_: &(impl Copy + 'a)) -> impl 'b + 'a { x }
+   |                +              +
+
+error: ambiguous `+` in a type
+  --> $DIR/ty-variance-issue-127971.rs:18:17
+   |
+LL | fn x<'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+   |                 ^^^^^^^^^^^^^^
+   |
+help: try adding parentheses
+   |
+LL | fn x<'b>(_: &'a (impl Copy + 'a)) -> Box<dyn 'b> { Box::u32(x) }
+   |                 +              +
+
+error: at least one trait must be specified
+  --> $DIR/ty-variance-issue-127971.rs:13:35
+   |
+LL | fn foo<'a>(_: &impl Copy + 'a) -> impl 'b + 'a { x }
+   |                                   ^^^^^^^^^^^^
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/ty-variance-issue-127971.rs:8:27
+   |
+LL | fn elided(_: &impl Copy + 'a) -> _ { x }
+   |                           ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL | fn elided<'a>(_: &impl Copy + 'a) -> _ { x }
+   |          ++++
+
+error[E0261]: use of undeclared lifetime name `'b`
+  --> $DIR/ty-variance-issue-127971.rs:13:40
+   |
+LL | fn foo<'a>(_: &impl Copy + 'a) -> impl 'b + 'a { x }
+   |                                        ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'b` here
+   |
+LL | fn foo<'b, 'a>(_: &impl Copy + 'a) -> impl 'b + 'a { x }
+   |        +++
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/ty-variance-issue-127971.rs:18:14
+   |
+LL | fn x<'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+   |              ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL | fn x<'a, 'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+   |      +++
+
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/ty-variance-issue-127971.rs:18:29
+   |
+LL | fn x<'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+   |                             ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL | fn x<'a, 'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+   |      +++
+
+error[E0224]: at least one trait is required for an object type
+  --> $DIR/ty-variance-issue-127971.rs:18:40
+   |
+LL | fn x<'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+   |                                        ^^^^^^
+
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
+  --> $DIR/ty-variance-issue-127971.rs:8:34
+   |
+LL | fn elided(_: &impl Copy + 'a) -> _ { x }
+   |                                  ^ not allowed in type signatures
+
+error[E0599]: no function or associated item named `u32` found for struct `Box<_, _>` in the current scope
+  --> $DIR/ty-variance-issue-127971.rs:18:55
+   |
+LL | fn x<'b>(_: &'a impl Copy + 'a) -> Box<dyn 'b> { Box::u32(x) }
+   |                                                       ^^^ function or associated item not found in `Box<_, _>`
+   |
+note: if you're trying to build a new `Box<_, _>` consider using one of the following associated functions:
+      Box::<T>::new
+      Box::<T>::new_uninit
+      Box::<T>::new_zeroed
+      Box::<T>::try_new
+      and 22 others
+  --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
+
+error: aborting due to 11 previous errors
+
+Some errors have detailed explanations: E0121, E0224, E0261, E0599.
+For more information about an error, try `rustc --explain E0121`.
diff --git a/tests/ui/parallel-rustc/undefined-function-issue-120760.rs b/tests/ui/parallel-rustc/undefined-function-issue-120760.rs
new file mode 100644
index 00000000000..2665c30945b
--- /dev/null
+++ b/tests/ui/parallel-rustc/undefined-function-issue-120760.rs
@@ -0,0 +1,71 @@
+// Test for #120760, which causes an ice bug: no index for a field
+//
+//@ compile-flags: -Z threads=45
+//@ edition: 2021
+//@ compare-output-by-lines
+
+type BoxFuture<T> = std::pin::Pin<Box<dyn std::future::Future<Output = T>>>;
+
+fn main() {
+    let _ = f();
+}
+
+async fn f() {
+    run("dependency").await; //~ ERROR cannot find function `run` in this scope
+}
+
+struct InMemoryStorage;
+
+pub struct User<'dep> {
+    pub name: &'a str, //~ ERROR use of undeclared lifetime name `'a`
+}
+
+impl<'a> StorageRequest<InMemoryStorage> for SaveUser<'a> {
+    fn execute(&self) -> BoxFuture<Result<(), String>> {
+        todo!()
+    }
+}
+
+trait Storage {
+    type Error;
+}
+
+impl Storage for InMemoryStorage {
+    type Error = String;
+}
+
+trait StorageRequestReturnType {
+    type Output;
+}
+
+trait StorageRequest<S: Storage>: StorageRequestReturnType {
+    fn execute(
+        &self,
+    ) -> BoxFuture<Result<<SaveUser as StorageRequestReturnType>::Output, <S as Storage>::Error>>;
+}
+
+pub struct SaveUser<'a> {
+    pub name: &'a str,
+}
+
+impl<'a> StorageRequestReturnType for SaveUser<'a> {
+    type Output = ();
+}
+
+impl<'dep> User<'dep> {
+    async fn save<S>(self)
+    where
+        S: Storage,
+        for<'a> SaveUser<'a>: StorageRequest<S>,
+    {
+        let _ = run("dependency").await; //~ ERROR cannot find function `run` in this scope
+    }
+}
+
+async fn execute<S>(dep: &str)
+where
+    S: Storage,
+    for<'a> SaveUser<'a>: StorageRequest<S>,
+{
+    User { dep }.save().await; //~ ERROR struct `User<'_>` has no field named `dep`
+}
diff --git a/tests/ui/parallel-rustc/undefined-function-issue-120760.stderr b/tests/ui/parallel-rustc/undefined-function-issue-120760.stderr
new file mode 100644
index 00000000000..87af5372219
--- /dev/null
+++ b/tests/ui/parallel-rustc/undefined-function-issue-120760.stderr
@@ -0,0 +1,35 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/undefined-function-issue-120760.rs:20:16
+   |
+LL |     pub name: &'a str,
+   |                ^^ undeclared lifetime
+   |
+help: consider introducing lifetime `'a` here
+   |
+LL | pub struct User<'a, 'dep> {
+   |                 +++
+
+error[E0425]: cannot find function `run` in this scope
+  --> $DIR/undefined-function-issue-120760.rs:14:5
+   |
+LL |     run("dependency").await;
+   |     ^^^ not found in this scope
+
+error[E0425]: cannot find function `run` in this scope
+  --> $DIR/undefined-function-issue-120760.rs:61:17
+   |
+LL |         let _ = run("dependency").await;
+   |                 ^^^ not found in this scope
+
+error[E0560]: struct `User<'_>` has no field named `dep`
+  --> $DIR/undefined-function-issue-120760.rs:70:12
+   |
+LL |     User { dep }.save().await;
+   |            ^^^ `User<'_>` does not have this field
+   |
+   = note: available fields are: `name`
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0261, E0425, E0560.
+For more information about an error, try `rustc --explain E0261`.
diff --git a/tests/ui/parallel-rustc/unexpected-type-issue-120601.rs b/tests/ui/parallel-rustc/unexpected-type-issue-120601.rs
new file mode 100644
index 00000000000..2e215aa301a
--- /dev/null
+++ b/tests/ui/parallel-rustc/unexpected-type-issue-120601.rs
@@ -0,0 +1,28 @@
+// Test for #120601, which causes an ice bug cause of unexpected type
+//
+//@ compile-flags: -Z threads=40
+//@ compare-output-by-lines
+
+struct T;
+struct Tuple(i32);
+
+async fn foo() -> Result<(), ()> {
+    Unstable2(())
+}
+//~^^^ ERROR `async fn` is not permitted in Rust 2015
+//~^^^ ERROR cannot find function, tuple struct or tuple variant `Unstable2` in this scope
+
+async fn tuple() -> Tuple {
+    Tuple(1i32)
+}
+//~^^^ ERROR `async fn` is not permitted in Rust 2015
+
+async fn match_() {
+    match tuple() {
+        Tuple(_) => {}
+    }
+}
+//~^^^^^ ERROR `async fn` is not permitted in Rust 2015
+//~^^^^ ERROR  mismatched types
+
+fn main() {}
diff --git a/tests/ui/parallel-rustc/unexpected-type-issue-120601.stderr b/tests/ui/parallel-rustc/unexpected-type-issue-120601.stderr
new file mode 100644
index 00000000000..ed563bb0c4e
--- /dev/null
+++ b/tests/ui/parallel-rustc/unexpected-type-issue-120601.stderr
@@ -0,0 +1,52 @@
+error[E0670]: `async fn` is not permitted in Rust 2015
+  --> $DIR/unexpected-type-issue-120601.rs:9:1
+   |
+LL | async fn foo() -> Result<(), ()> {
+   | ^^^^^ to use `async fn`, switch to Rust 2018 or later
+   |
+   = help: pass `--edition 2024` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+  --> $DIR/unexpected-type-issue-120601.rs:15:1
+   |
+LL | async fn tuple() -> Tuple {
+   | ^^^^^ to use `async fn`, switch to Rust 2018 or later
+   |
+   = help: pass `--edition 2024` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+  --> $DIR/unexpected-type-issue-120601.rs:20:1
+   |
+LL | async fn match_() {
+   | ^^^^^ to use `async fn`, switch to Rust 2018 or later
+   |
+   = help: pass `--edition 2024` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0425]: cannot find function, tuple struct or tuple variant `Unstable2` in this scope
+  --> $DIR/unexpected-type-issue-120601.rs:10:5
+   |
+LL |     Unstable2(())
+   |     ^^^^^^^^^ not found in this scope
+
+error[E0308]: mismatched types
+  --> $DIR/unexpected-type-issue-120601.rs:22:9
+   |
+LL |     match tuple() {
+   |           ------- this expression has type `impl Future<Output = Tuple>`
+LL |         Tuple(_) => {}
+   |         ^^^^^^^^ expected future, found `Tuple`
+   |
+   = note: expected opaque type `impl Future<Output = Tuple>`
+                   found struct `Tuple`
+help: consider `await`ing on the `Future`
+   |
+LL |     match tuple().await {
+   |                  ++++++
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0308, E0425, E0670.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/parser/bad-lit-suffixes.rs b/tests/ui/parser/bad-lit-suffixes.rs
index 0a01bb84f01..91b32fd4539 100644
--- a/tests/ui/parser/bad-lit-suffixes.rs
+++ b/tests/ui/parser/bad-lit-suffixes.rs
@@ -38,6 +38,7 @@ fn g() {}
 
 #[link(name = "string"suffix)]
 //~^ ERROR suffixes on string literals are invalid
+//~| ERROR malformed `link` attribute input
 extern "C" {}
 
 #[rustc_layout_scalar_valid_range_start(0suffix)]
diff --git a/tests/ui/parser/bad-lit-suffixes.stderr b/tests/ui/parser/bad-lit-suffixes.stderr
index e1a8a6834f4..217cc74b8eb 100644
--- a/tests/ui/parser/bad-lit-suffixes.stderr
+++ b/tests/ui/parser/bad-lit-suffixes.stderr
@@ -10,12 +10,6 @@ error: suffixes on string literals are invalid
 LL |     "C"suffix
    |     ^^^^^^^^^ invalid suffix `suffix`
 
-error: suffixes on string literals are invalid
-  --> $DIR/bad-lit-suffixes.rs:39:15
-   |
-LL | #[link(name = "string"suffix)]
-   |               ^^^^^^^^^^^^^^ invalid suffix `suffix`
-
 warning: `extern` declarations without an explicit ABI are deprecated
   --> $DIR/bad-lit-suffixes.rs:3:1
    |
@@ -160,8 +154,39 @@ LL - #[must_use = "string"suffix]
 LL + #[must_use]
    |
 
+error: suffixes on string literals are invalid
+  --> $DIR/bad-lit-suffixes.rs:39:15
+   |
+LL | #[link(name = "string"suffix)]
+   |               ^^^^^^^^^^^^^^ invalid suffix `suffix`
+
+error[E0539]: malformed `link` attribute input
+  --> $DIR/bad-lit-suffixes.rs:39:1
+   |
+LL | #[link(name = "string"suffix)]
+   | ^^^^^^^---------------------^^
+   |        |
+   |        expected this to be of the form `name = "..."`
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(name = "string"suffix)]
+LL + #[link(name = "...")]
+   |
+LL - #[link(name = "string"suffix)]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link(name = "string"suffix)]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link(name = "string"suffix)]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
+
 error: invalid suffix `suffix` for number literal
-  --> $DIR/bad-lit-suffixes.rs:43:41
+  --> $DIR/bad-lit-suffixes.rs:44:41
    |
 LL | #[rustc_layout_scalar_valid_range_start(0suffix)]
    |                                         ^^^^^^^ invalid suffix `suffix`
@@ -169,7 +194,7 @@ LL | #[rustc_layout_scalar_valid_range_start(0suffix)]
    = help: the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
 
 error[E0539]: malformed `rustc_layout_scalar_valid_range_start` attribute input
-  --> $DIR/bad-lit-suffixes.rs:43:1
+  --> $DIR/bad-lit-suffixes.rs:44:1
    |
 LL | #[rustc_layout_scalar_valid_range_start(0suffix)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------^^
@@ -177,6 +202,6 @@ LL | #[rustc_layout_scalar_valid_range_start(0suffix)]
    | |                                       expected an integer literal here
    | help: must be of the form: `#[rustc_layout_scalar_valid_range_start(start)]`
 
-error: aborting due to 22 previous errors; 2 warnings emitted
+error: aborting due to 23 previous errors; 2 warnings emitted
 
 For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/parser/misspelled-keywords/ref.stderr b/tests/ui/parser/misspelled-keywords/ref.stderr
index 21b99d6e663..dd33fdb21ba 100644
--- a/tests/ui/parser/misspelled-keywords/ref.stderr
+++ b/tests/ui/parser/misspelled-keywords/ref.stderr
@@ -15,6 +15,7 @@ error[E0023]: this pattern has 2 fields, but the corresponding tuple variant has
    |
 LL |         Some(refe list) => println!("{list:?}"),
    |              ^^^^ ^^^^ expected 1 field, found 2
+   |
   --> $SRC_DIR/core/src/option.rs:LL:COL
    |
    = note: tuple variant has 1 field
diff --git a/tests/ui/parser/recover/recover-pat-exprs.stderr b/tests/ui/parser/recover/recover-pat-exprs.stderr
index 33000022b8f..a99f7e16fca 100644
--- a/tests/ui/parser/recover/recover-pat-exprs.stderr
+++ b/tests/ui/parser/recover/recover-pat-exprs.stderr
@@ -690,6 +690,7 @@ error: expected one of `)`, `,`, `@`, `if`, or `|`, found `*`
    |
 LL |     let b = matches!(x, (x * x | x.f()) | x[0]);
    |                            ^ expected one of `)`, `,`, `@`, `if`, or `|`
+   |
   --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
    |
    = note: while parsing argument for this `pat` macro fragment
diff --git a/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr b/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr
index 21d09ec44c4..6d430184628 100644
--- a/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr
+++ b/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr
@@ -6,6 +6,7 @@ LL | const EMPTY: Vec<()> = Vec::new();
 ...
 LL |         EMPTY => {}
    |         ^^^^^ constant of non-structural type
+   |
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
    |
    = note: `Vec<()>` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
diff --git a/tests/ui/pattern/issue-115599.stderr b/tests/ui/pattern/issue-115599.stderr
index 69d10728ccd..ed465ea0bba 100644
--- a/tests/ui/pattern/issue-115599.stderr
+++ b/tests/ui/pattern/issue-115599.stderr
@@ -6,6 +6,7 @@ LL | const CONST_STRING: String = String::new();
 ...
 LL |     if let CONST_STRING = empty_str {}
    |            ^^^^^^^^^^^^ constant of non-structural type
+   |
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
    |
    = note: `Vec<u8>` must be annotated with `#[derive(PartialEq)]` to be usable in patterns
diff --git a/tests/ui/privacy/suggest-box-new.stderr b/tests/ui/privacy/suggest-box-new.stderr
index 6c47b52c9de..2b48e9046bf 100644
--- a/tests/ui/privacy/suggest-box-new.stderr
+++ b/tests/ui/privacy/suggest-box-new.stderr
@@ -3,10 +3,10 @@ error[E0423]: expected function, tuple struct or tuple variant, found struct `st
    |
 LL |     let _ = std::collections::HashMap();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
   --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
    |
    = note: `std::collections::HashMap` defined here
-   |
 help: you might have meant to use an associated function to build this type
    |
 LL |     let _ = std::collections::HashMap::new();
diff --git a/tests/ui/proc-macro/parent-source-spans.stderr b/tests/ui/proc-macro/parent-source-spans.stderr
index a3b27fd7bcc..db1eed5e458 100644
--- a/tests/ui/proc-macro/parent-source-spans.stderr
+++ b/tests/ui/proc-macro/parent-source-spans.stderr
@@ -144,6 +144,7 @@ LL |     parent_source_spans!($($tokens)*);
 ...
 LL |     one!("hello", "world");
    |     ---------------------- in this macro invocation
+   |
   --> $SRC_DIR/core/src/result.rs:LL:COL
    |
    = note: similarly named tuple variant `Ok` defined here
@@ -158,6 +159,7 @@ LL |     parent_source_spans!($($tokens)*);
 ...
 LL |     two!("yay", "rust");
    |     ------------------- in this macro invocation
+   |
   --> $SRC_DIR/core/src/result.rs:LL:COL
    |
    = note: similarly named tuple variant `Ok` defined here
@@ -172,6 +174,7 @@ LL |     parent_source_spans!($($tokens)*);
 ...
 LL |     three!("hip", "hop");
    |     -------------------- in this macro invocation
+   |
   --> $SRC_DIR/core/src/result.rs:LL:COL
    |
    = note: similarly named tuple variant `Ok` defined here
diff --git a/tests/ui/proc-macro/resolve-error.stderr b/tests/ui/proc-macro/resolve-error.stderr
index 963298311ef..45b71a3e7b3 100644
--- a/tests/ui/proc-macro/resolve-error.stderr
+++ b/tests/ui/proc-macro/resolve-error.stderr
@@ -76,6 +76,7 @@ error: cannot find derive macro `Dlone` in this scope
    |
 LL | #[derive(Dlone)]
    |          ^^^^^ help: a derive macro with a similar name exists: `Clone`
+   |
   --> $SRC_DIR/core/src/clone.rs:LL:COL
    |
    = note: similarly named derive macro `Clone` defined here
@@ -85,6 +86,7 @@ error: cannot find derive macro `Dlone` in this scope
    |
 LL | #[derive(Dlone)]
    |          ^^^^^ help: a derive macro with a similar name exists: `Clone`
+   |
   --> $SRC_DIR/core/src/clone.rs:LL:COL
    |
    = note: similarly named derive macro `Clone` defined here
diff --git a/tests/ui/resolve/issue-102946.rs b/tests/ui/resolve/issue-102946.rs
index c6feca6f32f..8d90e61bb5d 100644
--- a/tests/ui/resolve/issue-102946.rs
+++ b/tests/ui/resolve/issue-102946.rs
@@ -1,7 +1,6 @@
 impl Error for str::Utf8Error {
     //~^ ERROR cannot find trait `Error` in this scope
     //~| ERROR ambiguous associated type
-    fn description(&self)  {}
 }
 
 fn main() {}
diff --git a/tests/ui/resolve/levenshtein.stderr b/tests/ui/resolve/levenshtein.stderr
index cf478210132..7fc5710c35e 100644
--- a/tests/ui/resolve/levenshtein.stderr
+++ b/tests/ui/resolve/levenshtein.stderr
@@ -18,6 +18,7 @@ error[E0412]: cannot find type `Opiton` in this scope
    |
 LL | type B = Opiton<u8>; // Misspelled type name from the prelude.
    |          ^^^^^^ help: an enum with a similar name exists: `Option`
+   |
   --> $SRC_DIR/core/src/option.rs:LL:COL
    |
    = note: similarly named enum `Option` defined here
diff --git a/tests/ui/resolve/path-attr-in-const-block.rs b/tests/ui/resolve/path-attr-in-const-block.rs
index 076511d26d6..0ca356b1ddf 100644
--- a/tests/ui/resolve/path-attr-in-const-block.rs
+++ b/tests/ui/resolve/path-attr-in-const-block.rs
@@ -5,5 +5,6 @@ fn main() {
     const {
         #![path = foo!()]
         //~^ ERROR: cannot find macro `foo` in this scope
+        //~| ERROR: attribute value must be a literal
     }
 }
diff --git a/tests/ui/resolve/path-attr-in-const-block.stderr b/tests/ui/resolve/path-attr-in-const-block.stderr
index 8f9e58157c8..19d2745577b 100644
--- a/tests/ui/resolve/path-attr-in-const-block.stderr
+++ b/tests/ui/resolve/path-attr-in-const-block.stderr
@@ -4,5 +4,11 @@ error: cannot find macro `foo` in this scope
 LL |         #![path = foo!()]
    |                   ^^^
 
-error: aborting due to 1 previous error
+error: attribute value must be a literal
+  --> $DIR/path-attr-in-const-block.rs:6:19
+   |
+LL |         #![path = foo!()]
+   |                   ^^^^^^
+
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/rfcs/rfc-2091-track-caller/file-is-nul-terminated.rs b/tests/ui/rfcs/rfc-2091-track-caller/file-is-nul-terminated.rs
index 65e61a21f1a..7902f40b09b 100644
--- a/tests/ui/rfcs/rfc-2091-track-caller/file-is-nul-terminated.rs
+++ b/tests/ui/rfcs/rfc-2091-track-caller/file-is-nul-terminated.rs
@@ -5,12 +5,12 @@
 const fn assert_file_has_trailing_zero() {
     let caller = core::panic::Location::caller();
     let file_str = caller.file();
-    let file_with_nul = caller.file_with_nul();
-    if file_str.len() != file_with_nul.count_bytes() {
+    let file_cstr = caller.file_as_c_str();
+    if file_str.len() != file_cstr.count_bytes() {
         panic!("mismatched lengths");
     }
     let trailing_byte: core::ffi::c_char = unsafe {
-        *file_with_nul.as_ptr().offset(file_with_nul.count_bytes() as _)
+        *file_cstr.as_ptr().offset(file_cstr.count_bytes() as _)
     };
     if trailing_byte != 0 {
         panic!("trailing byte was nonzero")
diff --git a/tests/ui/sanitize-attr/invalid-sanitize.rs b/tests/ui/sanitize-attr/invalid-sanitize.rs
index 49dc01c8daa..957ce780ad0 100644
--- a/tests/ui/sanitize-attr/invalid-sanitize.rs
+++ b/tests/ui/sanitize-attr/invalid-sanitize.rs
@@ -1,8 +1,7 @@
 #![feature(sanitize)]
 
-#[sanitize(brontosaurus = "off")] //~ ERROR invalid argument
-fn main() {
-}
+#[sanitize(brontosaurus = "off")] //~ ERROR malformed `sanitize` attribute input
+fn main() {}
 
 #[sanitize(address = "off")] //~ ERROR multiple `sanitize` attributes
 #[sanitize(address = "off")]
@@ -12,11 +11,11 @@ fn multiple_consistent() {}
 #[sanitize(address = "off")]
 fn multiple_inconsistent() {}
 
-#[sanitize(address = "bogus")] //~ ERROR invalid argument for `sanitize`
+#[sanitize(address = "bogus")] //~ ERROR malformed `sanitize` attribute input
 fn wrong_value() {}
 
 #[sanitize = "off"] //~ ERROR malformed `sanitize` attribute input
-fn name_value () {}
+fn name_value() {}
 
 #[sanitize] //~ ERROR malformed `sanitize` attribute input
 fn just_word() {}
diff --git a/tests/ui/sanitize-attr/invalid-sanitize.stderr b/tests/ui/sanitize-attr/invalid-sanitize.stderr
index 4bf81770b89..ec0a93be142 100644
--- a/tests/ui/sanitize-attr/invalid-sanitize.stderr
+++ b/tests/ui/sanitize-attr/invalid-sanitize.stderr
@@ -1,82 +1,115 @@
-error: malformed `sanitize` attribute input
-  --> $DIR/invalid-sanitize.rs:18:1
+error[E0539]: malformed `sanitize` attribute input
+  --> $DIR/invalid-sanitize.rs:3:1
    |
-LL | #[sanitize = "off"]
-   | ^^^^^^^^^^^^^^^^^^^
+LL | #[sanitize(brontosaurus = "off")]
+   | ^^^^^^^^^^^------------^^^^^^^^^^
+   |            |
+   |            valid arguments are "address", "cfi", "kcfi", "memory", "memtag", "shadow_call_stack", "thread" or "hwaddress"
    |
-help: the following are the possible correct uses
+help: try changing it to one of the following valid forms of the attribute
    |
-LL - #[sanitize = "off"]
+LL - #[sanitize(brontosaurus = "off")]
 LL + #[sanitize(address = "on|off")]
    |
-LL - #[sanitize = "off"]
+LL - #[sanitize(brontosaurus = "off")]
 LL + #[sanitize(cfi = "on|off")]
    |
-LL - #[sanitize = "off"]
+LL - #[sanitize(brontosaurus = "off")]
 LL + #[sanitize(hwaddress = "on|off")]
    |
-LL - #[sanitize = "off"]
+LL - #[sanitize(brontosaurus = "off")]
 LL + #[sanitize(kcfi = "on|off")]
    |
    = and 5 other candidates
 
-error: malformed `sanitize` attribute input
-  --> $DIR/invalid-sanitize.rs:21:1
-   |
-LL | #[sanitize]
-   | ^^^^^^^^^^^
-   |
-help: the following are the possible correct uses
-   |
-LL | #[sanitize(address = "on|off")]
-   |           ++++++++++++++++++++
-LL | #[sanitize(cfi = "on|off")]
-   |           ++++++++++++++++
-LL | #[sanitize(hwaddress = "on|off")]
-   |           ++++++++++++++++++++++
-LL | #[sanitize(kcfi = "on|off")]
-   |           +++++++++++++++++
-   = and 5 other candidates
-
 error: multiple `sanitize` attributes
-  --> $DIR/invalid-sanitize.rs:7:1
+  --> $DIR/invalid-sanitize.rs:6:1
    |
 LL | #[sanitize(address = "off")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/invalid-sanitize.rs:8:1
+  --> $DIR/invalid-sanitize.rs:7:1
    |
 LL | #[sanitize(address = "off")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: multiple `sanitize` attributes
-  --> $DIR/invalid-sanitize.rs:11:1
+  --> $DIR/invalid-sanitize.rs:10:1
    |
 LL | #[sanitize(address = "on")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
    |
 note: attribute also specified here
-  --> $DIR/invalid-sanitize.rs:12:1
+  --> $DIR/invalid-sanitize.rs:11:1
    |
 LL | #[sanitize(address = "off")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: invalid argument for `sanitize`
-  --> $DIR/invalid-sanitize.rs:3:1
+error[E0539]: malformed `sanitize` attribute input
+  --> $DIR/invalid-sanitize.rs:14:1
    |
-LL | #[sanitize(brontosaurus = "off")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[sanitize(address = "bogus")]
+   | ^^^^^^^^^^^^^^^^^^^^^-------^^
+   |                      |
+   |                      valid arguments are "on" or "off"
+   |
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[sanitize(address = "bogus")]
+LL + #[sanitize(address = "on|off")]
+   |
+LL - #[sanitize(address = "bogus")]
+LL + #[sanitize(cfi = "on|off")]
+   |
+LL - #[sanitize(address = "bogus")]
+LL + #[sanitize(hwaddress = "on|off")]
+   |
+LL - #[sanitize(address = "bogus")]
+LL + #[sanitize(kcfi = "on|off")]
    |
-   = note: expected one of: `address`, `kernel_address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow_call_stack`, or `thread`
+   = and 5 other candidates
 
-error: invalid argument for `sanitize`
-  --> $DIR/invalid-sanitize.rs:15:1
+error[E0539]: malformed `sanitize` attribute input
+  --> $DIR/invalid-sanitize.rs:17:1
    |
-LL | #[sanitize(address = "bogus")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[sanitize = "off"]
+   | ^^^^^^^^^^^^^^^^^^^ expected this to be a list
+   |
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[sanitize = "off"]
+LL + #[sanitize(address = "on|off")]
+   |
+LL - #[sanitize = "off"]
+LL + #[sanitize(cfi = "on|off")]
+   |
+LL - #[sanitize = "off"]
+LL + #[sanitize(hwaddress = "on|off")]
+   |
+LL - #[sanitize = "off"]
+LL + #[sanitize(kcfi = "on|off")]
+   |
+   = and 5 other candidates
+
+error[E0539]: malformed `sanitize` attribute input
+  --> $DIR/invalid-sanitize.rs:20:1
    |
-   = note: expected one of: `address`, `kernel_address`, `cfi`, `hwaddress`, `kcfi`, `memory`, `memtag`, `shadow_call_stack`, or `thread`
+LL | #[sanitize]
+   | ^^^^^^^^^^^ expected this to be a list
+   |
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL | #[sanitize(address = "on|off")]
+   |           ++++++++++++++++++++
+LL | #[sanitize(cfi = "on|off")]
+   |           ++++++++++++++++
+LL | #[sanitize(hwaddress = "on|off")]
+   |           ++++++++++++++++++++++
+LL | #[sanitize(kcfi = "on|off")]
+   |           +++++++++++++++++
+   = and 5 other candidates
 
 error: aborting due to 6 previous errors
 
+For more information about this error, try `rustc --explain E0539`.
diff --git a/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr
index 7108fa1a290..1a5c87114d4 100644
--- a/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr
+++ b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr
@@ -1,8 +1,8 @@
 warning: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/ignore-non-reference-lifetimes.rs:6:30
+  --> $DIR/ignore-non-reference-lifetimes.rs:6:41
    |
 LL |     fn a<'a>(self: Self, a: &'a str) -> &str {
-   |                              ^^         ---- the same lifetime is elided here
+   |                              --         ^^^^ the same lifetime is elided here
    |                              |
    |                              the lifetime is named here
    |
@@ -14,10 +14,10 @@ LL |     fn a<'a>(self: Self, a: &'a str) -> &'a str {
    |                                          ++
 
 warning: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/ignore-non-reference-lifetimes.rs:10:33
+  --> $DIR/ignore-non-reference-lifetimes.rs:10:44
    |
 LL |     fn b<'a>(self: Foo<'b>, a: &'a str) -> &str {
-   |                                 ^^         ---- the same lifetime is elided here
+   |                                 --         ^^^^ the same lifetime is elided here
    |                                 |
    |                                 the lifetime is named here
    |
diff --git a/tests/ui/self/self_lifetime-async.stderr b/tests/ui/self/self_lifetime-async.stderr
index 43dc96abdc2..78cc610fd04 100644
--- a/tests/ui/self/self_lifetime-async.stderr
+++ b/tests/ui/self/self_lifetime-async.stderr
@@ -1,8 +1,8 @@
 warning: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/self_lifetime-async.rs:6:29
+  --> $DIR/self_lifetime-async.rs:6:44
    |
 LL |     async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 }
-   |                             ^^             --- the same lifetime is elided here
+   |                             --             ^^^ the same lifetime is elided here
    |                             |
    |                             the lifetime is named here
    |
@@ -14,10 +14,10 @@ LL |     async fn foo<'b>(self: &'b Foo<'a>) -> &'b () { self.0 }
    |                                             ++
 
 warning: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/self_lifetime-async.rs:12:42
+  --> $DIR/self_lifetime-async.rs:12:52
    |
 LL |     async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg }
-   |                                          ^^        --- the same lifetime is elided here
+   |                                          --        ^^^ the same lifetime is elided here
    |                                          |
    |                                          the lifetime is named here
    |
diff --git a/tests/ui/self/self_lifetime.stderr b/tests/ui/self/self_lifetime.stderr
index 4f9b2fcd2ad..84f63454633 100644
--- a/tests/ui/self/self_lifetime.stderr
+++ b/tests/ui/self/self_lifetime.stderr
@@ -1,8 +1,8 @@
 warning: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/self_lifetime.rs:7:23
+  --> $DIR/self_lifetime.rs:7:38
    |
 LL |     fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 }
-   |                       ^^             --- the same lifetime is elided here
+   |                       --             ^^^ the same lifetime is elided here
    |                       |
    |                       the lifetime is named here
    |
@@ -14,10 +14,10 @@ LL |     fn foo<'b>(self: &'b Foo<'a>) -> &'b () { self.0 }
    |                                       ++
 
 warning: eliding a lifetime that's named elsewhere is confusing
-  --> $DIR/self_lifetime.rs:13:36
+  --> $DIR/self_lifetime.rs:13:46
    |
 LL |     fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg }
-   |                                    ^^        --- the same lifetime is elided here
+   |                                    --        ^^^ the same lifetime is elided here
    |                                    |
    |                                    the lifetime is named here
    |
diff --git a/tests/ui/suggestions/attribute-typos.stderr b/tests/ui/suggestions/attribute-typos.stderr
index a1a01c0abd6..1816a27dcdc 100644
--- a/tests/ui/suggestions/attribute-typos.stderr
+++ b/tests/ui/suggestions/attribute-typos.stderr
@@ -15,6 +15,7 @@ error: cannot find attribute `tests` in this scope
    |
 LL | #[tests]
    |   ^^^^^ help: an attribute macro with a similar name exists: `test`
+   |
   --> $SRC_DIR/core/src/macros/mod.rs:LL:COL
    |
    = note: similarly named attribute macro `test` defined here
diff --git a/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr b/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr
index 0cd6267b3b3..c81ac34aaf4 100644
--- a/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr
+++ b/tests/ui/suggestions/do-not-attempt-to-add-suggestions-with-no-changes.stderr
@@ -3,6 +3,7 @@ error[E0573]: expected type, found module `result`
    |
 LL | impl result {
    |      ^^^^^^ help: an enum with a similar name exists: `Result`
+   |
   --> $SRC_DIR/core/src/result.rs:LL:COL
    |
    = note: similarly named enum `Result` defined here
diff --git a/tests/ui/suggestions/enum-method-probe.stderr b/tests/ui/suggestions/enum-method-probe.stderr
index 5aa0fc44c7b..7d97495af82 100644
--- a/tests/ui/suggestions/enum-method-probe.stderr
+++ b/tests/ui/suggestions/enum-method-probe.stderr
@@ -99,10 +99,10 @@ error[E0624]: method `len` is private
    |
 LL |     res.len();
    |         ^^^ private method
+   |
   --> $SRC_DIR/core/src/option.rs:LL:COL
    |
    = note: private method defined here
-   |
 note: the method `len` exists on the type `Vec<{integer}>`
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 help: consider using `Option::expect` to unwrap the `Vec<{integer}>` value, panicking if the value is an `Option::None`
diff --git a/tests/ui/suggestions/import-trait-for-method-call.stderr b/tests/ui/suggestions/import-trait-for-method-call.stderr
index 58b07fe7a42..177ab76cd1f 100644
--- a/tests/ui/suggestions/import-trait-for-method-call.stderr
+++ b/tests/ui/suggestions/import-trait-for-method-call.stderr
@@ -3,6 +3,7 @@ error[E0599]: no method named `finish` found for struct `DefaultHasher` in the c
    |
 LL |     h.finish()
    |       ^^^^^^ method not found in `DefaultHasher`
+   |
   --> $SRC_DIR/core/src/hash/mod.rs:LL:COL
    |
    = note: the method is available for `DefaultHasher` here
diff --git a/tests/ui/suggestions/multi-suggestion.ascii.stderr b/tests/ui/suggestions/multi-suggestion.ascii.stderr
index f2a146fbd52..1744162e6ce 100644
--- a/tests/ui/suggestions/multi-suggestion.ascii.stderr
+++ b/tests/ui/suggestions/multi-suggestion.ascii.stderr
@@ -3,10 +3,10 @@ error[E0423]: expected function, tuple struct or tuple variant, found struct `st
    |
 LL |     let _ = std::collections::HashMap();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
   --> $SRC_DIR/std/src/collections/hash/map.rs:LL:COL
    |
    = note: `std::collections::HashMap` defined here
-   |
 help: you might have meant to use an associated function to build this type
    |
 LL |     let _ = std::collections::HashMap::new();
diff --git a/tests/ui/suggestions/multi-suggestion.unicode.stderr b/tests/ui/suggestions/multi-suggestion.unicode.stderr
index 69df481579b..4835c263f19 100644
--- a/tests/ui/suggestions/multi-suggestion.unicode.stderr
+++ b/tests/ui/suggestions/multi-suggestion.unicode.stderr
@@ -3,10 +3,10 @@ error[E0423]: expected function, tuple struct or tuple variant, found struct `st

 LL │     let _ = std::collections::HashMap();
    │             ━━━━━━━━━━━━━━━━━━━━━━━━━━━
+   ╰╴
    ╭▸ $SRC_DIR/std/src/collections/hash/map.rs:LL:COL

    ╰ note: `std::collections::HashMap` defined here
-   ╰╴
 help: you might have meant to use an associated function to build this type
    ╭╴
 LL │     let _ = std::collections::HashMap::new();
@@ -34,7 +34,7 @@ LL │         wtf: Some(Box(U {
 note: constructor is not visible here due to private fields
    ╭▸ $SRC_DIR/alloc/src/boxed.rs:LL:COL

-   ╰ note: private field
+   ├ note: private field

    ╰ note: private field
 help: you might have meant to use an associated function to build this type
diff --git a/tests/ui/suggestions/suggest-tryinto-edition-change.stderr b/tests/ui/suggestions/suggest-tryinto-edition-change.stderr
index 0008b4fb5ed..8ab8a1716b1 100644
--- a/tests/ui/suggestions/suggest-tryinto-edition-change.stderr
+++ b/tests/ui/suggestions/suggest-tryinto-edition-change.stderr
@@ -44,6 +44,7 @@ error[E0599]: no method named `try_into` found for type `i32` in the current sco
    |
 LL |     let _i: i16 = 0_i32.try_into().unwrap();
    |                         ^^^^^^^^
+   |
   --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
    |
    = note: the method is available for `i32` here
diff --git a/tests/ui/suggestions/use-parentheses-to-call-closure-issue-145404.fixed b/tests/ui/suggestions/use-parentheses-to-call-closure-issue-145404.fixed
new file mode 100644
index 00000000000..2835743fca2
--- /dev/null
+++ b/tests/ui/suggestions/use-parentheses-to-call-closure-issue-145404.fixed
@@ -0,0 +1,13 @@
+//@ run-rustfix
+
+use std::fmt::Display;
+
+struct S;
+
+impl S {
+    fn call(&self, _: impl Display) {}
+}
+
+fn main() {
+    S.call((|| "hello")()); //~ ERROR [E0277]
+}
diff --git a/tests/ui/suggestions/use-parentheses-to-call-closure-issue-145404.rs b/tests/ui/suggestions/use-parentheses-to-call-closure-issue-145404.rs
new file mode 100644
index 00000000000..848629a6700
--- /dev/null
+++ b/tests/ui/suggestions/use-parentheses-to-call-closure-issue-145404.rs
@@ -0,0 +1,13 @@
+//@ run-rustfix
+
+use std::fmt::Display;
+
+struct S;
+
+impl S {
+    fn call(&self, _: impl Display) {}
+}
+
+fn main() {
+    S.call(|| "hello"); //~ ERROR [E0277]
+}
diff --git a/tests/ui/suggestions/use-parentheses-to-call-closure-issue-145404.stderr b/tests/ui/suggestions/use-parentheses-to-call-closure-issue-145404.stderr
new file mode 100644
index 00000000000..cb6df5af7fb
--- /dev/null
+++ b/tests/ui/suggestions/use-parentheses-to-call-closure-issue-145404.stderr
@@ -0,0 +1,23 @@
+error[E0277]: `{closure@$DIR/use-parentheses-to-call-closure-issue-145404.rs:12:12: 12:14}` doesn't implement `std::fmt::Display`
+  --> $DIR/use-parentheses-to-call-closure-issue-145404.rs:12:12
+   |
+LL |     S.call(|| "hello");
+   |       ---- ^^^^^^^^^^ unsatisfied trait bound
+   |       |
+   |       required by a bound introduced by this call
+   |
+   = help: the trait `std::fmt::Display` is not implemented for closure `{closure@$DIR/use-parentheses-to-call-closure-issue-145404.rs:12:12: 12:14}`
+note: required by a bound in `S::call`
+  --> $DIR/use-parentheses-to-call-closure-issue-145404.rs:8:28
+   |
+LL |     fn call(&self, _: impl Display) {}
+   |                            ^^^^^^^ required by this bound in `S::call`
+help: use parentheses to call this closure
+   |
+LL -     S.call(|| "hello");
+LL +     S.call((|| "hello")());
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
index 2288bd1129c..40936ce1ec3 100644
--- a/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
+++ b/tests/ui/traits/associated_type_bound/assoc_type_bound_with_struct.stderr
@@ -3,10 +3,10 @@ error[E0404]: expected trait, found struct `String`
    |
 LL | struct Foo<T> where T: Bar, <T as Bar>::Baz: String {
    |                                              ^^^^^^ not a trait
+   |
   --> $SRC_DIR/alloc/src/string.rs:LL:COL
    |
    = note: similarly named trait `ToString` defined here
-   |
 help: constrain the associated type to `String`
    |
 LL - struct Foo<T> where T: Bar, <T as Bar>::Baz: String {
@@ -22,10 +22,10 @@ error[E0404]: expected trait, found struct `String`
    |
 LL | struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: String {
    |                                                      ^^^^^^ not a trait
+   |
   --> $SRC_DIR/alloc/src/string.rs:LL:COL
    |
    = note: similarly named trait `ToString` defined here
-   |
 help: constrain the associated type to `String`
    |
 LL - struct Qux<'a, T> where T: Bar, <&'a T as Bar>::Baz: String {
@@ -41,10 +41,10 @@ error[E0404]: expected trait, found struct `String`
    |
 LL | fn foo<T: Bar>(_: T) where <T as Bar>::Baz: String {
    |                                             ^^^^^^ not a trait
+   |
   --> $SRC_DIR/alloc/src/string.rs:LL:COL
    |
    = note: similarly named trait `ToString` defined here
-   |
 help: constrain the associated type to `String`
    |
 LL - fn foo<T: Bar>(_: T) where <T as Bar>::Baz: String {
@@ -60,10 +60,10 @@ error[E0404]: expected trait, found struct `String`
    |
 LL | fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String {
    |                                                         ^^^^^^ not a trait
+   |
   --> $SRC_DIR/alloc/src/string.rs:LL:COL
    |
    = note: similarly named trait `ToString` defined here
-   |
 help: constrain the associated type to `String`
    |
 LL - fn qux<'a, T: Bar>(_: &'a T) where <&'a T as Bar>::Baz: String {
@@ -85,6 +85,7 @@ error[E0404]: expected trait, found struct `String`
    |
 LL | fn issue_95327() where <u8 as Unresolved>::Assoc: String {}
    |                                                   ^^^^^^ help: a trait with a similar name exists: `ToString`
+   |
   --> $SRC_DIR/alloc/src/string.rs:LL:COL
    |
    = note: similarly named trait `ToString` defined here
diff --git a/tests/ui/traits/const-traits/constructor-const-fn.rs b/tests/ui/traits/const-traits/constructor-const-fn.rs
new file mode 100644
index 00000000000..4a7bf531df2
--- /dev/null
+++ b/tests/ui/traits/const-traits/constructor-const-fn.rs
@@ -0,0 +1,15 @@
+//@ check-pass
+//@ compile-flags: -Znext-solver
+#![feature(const_trait_impl)]
+const fn impls_fn<F: ~const Fn(u32) -> Foo>(_: &F) {}
+
+struct Foo(u32);
+
+const fn foo() {
+    // This previously triggered an incorrect assert
+    // when checking whether the constructor of `Foo`
+    // is const.
+    impls_fn(&Foo)
+}
+
+fn main() {}
diff --git a/tests/ui/traits/const-traits/reservation-impl-ice.rs b/tests/ui/traits/const-traits/reservation-impl-ice.rs
new file mode 100644
index 00000000000..efaea1cc6b2
--- /dev/null
+++ b/tests/ui/traits/const-traits/reservation-impl-ice.rs
@@ -0,0 +1,13 @@
+//@ compile-flags: -Znext-solver
+#![feature(const_from, never_type, const_trait_impl)]
+
+const fn impls_from<T: ~const From<!>>() {}
+
+const fn foo() {
+    // This previously ICE'd when encountering the reservation impl
+    // from the standard library.
+    impls_from::<()>();
+    //~^ ERROR the trait bound `(): From<!>` is not satisfied
+}
+
+fn main() {}
diff --git a/tests/ui/traits/const-traits/reservation-impl-ice.stderr b/tests/ui/traits/const-traits/reservation-impl-ice.stderr
new file mode 100644
index 00000000000..a3fdcbac69e
--- /dev/null
+++ b/tests/ui/traits/const-traits/reservation-impl-ice.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the trait bound `(): From<!>` is not satisfied
+  --> $DIR/reservation-impl-ice.rs:9:18
+   |
+LL |     impls_from::<()>();
+   |                  ^^ the trait `From<!>` is not implemented for `()`
+   |
+   = help: the following other types implement trait `From<T>`:
+             `(T, T)` implements `From<[T; 2]>`
+             `(T, T, T)` implements `From<[T; 3]>`
+             `(T, T, T, T)` implements `From<[T; 4]>`
+             `(T, T, T, T, T)` implements `From<[T; 5]>`
+             `(T, T, T, T, T, T)` implements `From<[T; 6]>`
+             `(T, T, T, T, T, T, T)` implements `From<[T; 7]>`
+             `(T, T, T, T, T, T, T, T)` implements `From<[T; 8]>`
+             `(T, T, T, T, T, T, T, T, T)` implements `From<[T; 9]>`
+           and 4 others
+note: required by a bound in `impls_from`
+  --> $DIR/reservation-impl-ice.rs:4:24
+   |
+LL | const fn impls_from<T: ~const From<!>>() {}
+   |                        ^^^^^^^^^^^^^^ required by this bound in `impls_from`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.next.stderr b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.next.stderr
index 3b478889996..e75be1e8137 100644
--- a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.next.stderr
+++ b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.next.stderr
@@ -1,10 +1,10 @@
-error[E0283]: type annotations needed: cannot satisfy `impl Trait<'x> + Trait<'y>: Trait<'y>`
-  --> $DIR/ambiguity-due-to-uniquification-2.rs:16:23
+error[E0283]: type annotations needed: cannot satisfy `impl Trait<'_> + Trait<'_>: Trait<'_>`
+  --> $DIR/ambiguity-due-to-uniquification-2.rs:16:5
    |
 LL |     impls_trait::<'y, _>(foo::<'x, 'y>());
-   |                       ^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: cannot satisfy `impl Trait<'x> + Trait<'y>: Trait<'y>`
+   = note: cannot satisfy `impl Trait<'_> + Trait<'_>: Trait<'_>`
    = help: the trait `Trait<'t>` is implemented for `()`
 note: required by a bound in `impls_trait`
   --> $DIR/ambiguity-due-to-uniquification-2.rs:13:23
diff --git a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.rs b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.rs
index 2a9a8b80cc0..30df70396f4 100644
--- a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.rs
+++ b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-2.rs
@@ -14,7 +14,7 @@ fn impls_trait<'x, T: Trait<'x>>(_: T) {}
 
 fn bar<'x, 'y>() {
     impls_trait::<'y, _>(foo::<'x, 'y>());
-    //[next]~^ ERROR type annotations needed: cannot satisfy `impl Trait<'x> + Trait<'y>: Trait<'y>`
+    //[next]~^ ERROR type annotations needed: cannot satisfy `impl Trait<'_> + Trait<'_>: Trait<'_>`
 }
 
 fn main() {}
diff --git a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-3.next.stderr b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-3.next.stderr
index e25f892b365..7fa89054931 100644
--- a/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-3.next.stderr
+++ b/tests/ui/traits/next-solver/assembly/ambiguity-due-to-uniquification-3.next.stderr
@@ -1,12 +1,10 @@
-error[E0283]: type annotations needed: cannot satisfy `(dyn Object<&(), &()> + 'static): Trait<&()>`
-  --> $DIR/ambiguity-due-to-uniquification-3.rs:28:17
+error[E0283]: type annotations needed: cannot satisfy `dyn Object<&(), &()>: Trait<&()>`
+  --> $DIR/ambiguity-due-to-uniquification-3.rs:28:5
    |
 LL |     impls_trait(obj, t);
-   |     ----------- ^^^
-   |     |
-   |     required by a bound introduced by this call
+   |     ^^^^^^^^^^^^^^^^^^^
    |
-   = note: cannot satisfy `(dyn Object<&(), &()> + 'static): Trait<&()>`
+   = note: cannot satisfy `dyn Object<&(), &()>: Trait<&()>`
    = help: the trait `Trait<T>` is implemented for `()`
 note: required by a bound in `impls_trait`
   --> $DIR/ambiguity-due-to-uniquification-3.rs:24:19
diff --git a/tests/ui/traits/next-solver/opaques/different-bound-vars.current.stderr b/tests/ui/traits/next-solver/opaques/different-bound-vars.current.stderr
new file mode 100644
index 00000000000..32e92e46a88
--- /dev/null
+++ b/tests/ui/traits/next-solver/opaques/different-bound-vars.current.stderr
@@ -0,0 +1,14 @@
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/different-bound-vars.rs:13:37
+   |
+LL |         let _: for<'b> fn(&'b ()) = foo::<U, T>(false);
+   |                                     ^^^^^^^^^^^^^^^^^^ expected `for<'a> fn(&'a ())`, got `for<'b> fn(&'b ())`
+   |
+note: previous use here
+  --> $DIR/different-bound-vars.rs:12:37
+   |
+LL |         let _: for<'a> fn(&'a ()) = foo::<T, U>(false);
+   |                                     ^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/traits/next-solver/opaques/different-bound-vars.rs b/tests/ui/traits/next-solver/opaques/different-bound-vars.rs
new file mode 100644
index 00000000000..5801a5edeb4
--- /dev/null
+++ b/tests/ui/traits/next-solver/opaques/different-bound-vars.rs
@@ -0,0 +1,20 @@
+// Check whether we support defining uses with different bound vars.
+// This needs to handle both mismatches for the same opaque type storage
+// entry, but also between different entries.
+
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+//@[next] check-pass
+
+fn foo<T, U>(b: bool) -> impl Sized {
+    if b {
+        let _: for<'a> fn(&'a ()) = foo::<T, U>(false);
+        let _: for<'b> fn(&'b ()) = foo::<U, T>(false);
+        //[current]~^ ERROR concrete type differs from previous defining opaque type use
+    }
+
+    (|&()| ()) as for<'c> fn(&'c ())
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.is_send.stderr b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.is_send.stderr
index 6d2bbd8b08b..a188629a475 100644
--- a/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.is_send.stderr
+++ b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.is_send.stderr
@@ -1,16 +1,9 @@
-error[E0283]: type annotations needed: cannot satisfy `Foo: Send`
-  --> $DIR/dont-type_of-tait-in-defining-scope.rs:16:18
+error[E0282]: type annotations needed
+  --> $DIR/dont-type_of-tait-in-defining-scope.rs:15:12
    |
-LL |     needs_send::<Foo>();
-   |                  ^^^
-   |
-   = note: cannot satisfy `Foo: Send`
-note: required by a bound in `needs_send`
-  --> $DIR/dont-type_of-tait-in-defining-scope.rs:12:18
-   |
-LL | fn needs_send<T: Send>() {}
-   |                  ^^^^ required by this bound in `needs_send`
+LL | fn test(_: Foo) {
+   |            ^^^ cannot infer type
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0283`.
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.not_send.stderr b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.not_send.stderr
index 6d2bbd8b08b..a188629a475 100644
--- a/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.not_send.stderr
+++ b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.not_send.stderr
@@ -1,16 +1,9 @@
-error[E0283]: type annotations needed: cannot satisfy `Foo: Send`
-  --> $DIR/dont-type_of-tait-in-defining-scope.rs:16:18
+error[E0282]: type annotations needed
+  --> $DIR/dont-type_of-tait-in-defining-scope.rs:15:12
    |
-LL |     needs_send::<Foo>();
-   |                  ^^^
-   |
-   = note: cannot satisfy `Foo: Send`
-note: required by a bound in `needs_send`
-  --> $DIR/dont-type_of-tait-in-defining-scope.rs:12:18
-   |
-LL | fn needs_send<T: Send>() {}
-   |                  ^^^^ required by this bound in `needs_send`
+LL | fn test(_: Foo) {
+   |            ^^^ cannot infer type
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0283`.
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.rs b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.rs
index fddf892e1ef..8ff99d32f06 100644
--- a/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.rs
+++ b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.rs
@@ -13,8 +13,8 @@ fn needs_send<T: Send>() {}
 
 #[define_opaque(Foo)]
 fn test(_: Foo) {
-    needs_send::<Foo>();
     //~^ ERROR type annotations needed
+    needs_send::<Foo>();
 }
 
 #[define_opaque(Foo)]
diff --git a/tests/ui/traits/next-solver/opaques/non-defining-use-hir-typeck.rs b/tests/ui/traits/next-solver/opaques/non-defining-use-hir-typeck.rs
new file mode 100644
index 00000000000..a55be5fde9e
--- /dev/null
+++ b/tests/ui/traits/next-solver/opaques/non-defining-use-hir-typeck.rs
@@ -0,0 +1,28 @@
+//@ ignore-compare-mode-next-solver
+//@ compile-flags: -Znext-solver
+//@ check-pass
+#![feature(type_alias_impl_trait)]
+
+// Make sure that we support non-defining uses in HIR typeck.
+// Regression test for trait-system-refactor-initiative#135.
+
+fn non_defining_recurse<T>(b: bool) -> impl Sized {
+    if b {
+        // This results in an opaque type use `opaque<()> = ?unconstrained`
+        // during HIR typeck.
+        non_defining_recurse::<()>(false);
+    }
+}
+
+trait Eq<T, U> {}
+impl<T> Eq<T, T> for () {}
+fn is_eq<T: Eq<U, V>, U, V>() {}
+type Tait<T> = impl Sized;
+#[define_opaque(Tait)]
+fn non_defining_explicit<T>() {
+    is_eq::<(), Tait<_>, u32>(); // constrains opaque type args via hidden type
+    is_eq::<(), Tait<u64>, _>(); // constraints hidden type via args
+    is_eq::<(), Tait<T>, T>(); // actually defines
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/opaques/universal-args-non-defining.rs b/tests/ui/traits/next-solver/opaques/universal-args-non-defining.rs
new file mode 100644
index 00000000000..5e7e9738616
--- /dev/null
+++ b/tests/ui/traits/next-solver/opaques/universal-args-non-defining.rs
@@ -0,0 +1,16 @@
+//@ check-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+// The recursive call to `foo` results in the opaque type use `opaque<U, T> = ?unconstrained`.
+// This needs to be supported and treated as a revealing use.
+
+fn foo<T, U>(b: bool) -> impl Sized {
+    if b {
+        foo::<U, T>(b);
+    }
+    1u16
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr b/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr
index 72a253c4be8..b50d1b60c43 100644
--- a/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr
+++ b/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr
@@ -1,24 +1,9 @@
-error[E0283]: type annotations needed: cannot satisfy `Foo: Trait<Bar>`
-  --> $DIR/constrain_in_projection2.rs:28:14
+error[E0282]: type annotations needed
+  --> $DIR/constrain_in_projection2.rs:28:13
    |
 LL |     let x = <Foo as Trait<Bar>>::Assoc::default();
-   |              ^^^
-   |
-note: multiple `impl`s satisfying `Foo: Trait<Bar>` found
-  --> $DIR/constrain_in_projection2.rs:18:1
-   |
-LL | impl Trait<()> for Foo {
-   | ^^^^^^^^^^^^^^^^^^^^^^
-...
-LL | impl Trait<u32> for Foo {
-   | ^^^^^^^^^^^^^^^^^^^^^^^
-   = note: associated types cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
-help: use the fully qualified path to an implementation
-   |
-LL -     let x = <Foo as Trait<Bar>>::Assoc::default();
-LL +     let x = <<Type as Trait>::Assoc as Trait<Bar>>::Assoc::default();
-   |
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0283`.
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection2.rs b/tests/ui/type-alias-impl-trait/constrain_in_projection2.rs
index 61773cf59d4..c4aa6f32eab 100644
--- a/tests/ui/type-alias-impl-trait/constrain_in_projection2.rs
+++ b/tests/ui/type-alias-impl-trait/constrain_in_projection2.rs
@@ -26,7 +26,7 @@ impl Trait<u32> for Foo {
 #[define_opaque(Bar)]
 fn bop() {
     let x = <Foo as Trait<Bar>>::Assoc::default();
-    //[next]~^ ERROR: cannot satisfy `Foo: Trait<Bar>`
+    //[next]~^ ERROR: type annotations needed
     //[current]~^^ ERROR: `Foo: Trait<Bar>` is not satisfied
     //[current]~| ERROR: `Foo: Trait<Bar>` is not satisfied
 }
diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr b/tests/ui/type-alias-impl-trait/generic_nondefining_use.current.stderr
index 71e415271ee..2a78860689b 100644
--- a/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.current.stderr
@@ -1,5 +1,5 @@
 error[E0792]: expected generic type parameter, found `u32`
-  --> $DIR/generic_nondefining_use.rs:16:21
+  --> $DIR/generic_nondefining_use.rs:20:21
    |
 LL | type OneTy<T> = impl Debug;
    |            - this generic parameter must be used with a generic type parameter
@@ -8,7 +8,7 @@ LL | fn concrete_ty() -> OneTy<u32> {
    |                     ^^^^^^^^^^
 
 error[E0792]: expected generic lifetime parameter, found `'static`
-  --> $DIR/generic_nondefining_use.rs:23:5
+  --> $DIR/generic_nondefining_use.rs:29:5
    |
 LL | type OneLifetime<'a> = impl Debug;
    |                  -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
@@ -17,7 +17,7 @@ LL |     6u32
    |     ^^^^
 
 error[E0792]: expected generic constant parameter, found `123`
-  --> $DIR/generic_nondefining_use.rs:28:24
+  --> $DIR/generic_nondefining_use.rs:35:24
    |
 LL | type OneConst<const X: usize> = impl Debug;
    |               -------------- this generic parameter must be used with a generic constant parameter
diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.next.stderr b/tests/ui/type-alias-impl-trait/generic_nondefining_use.next.stderr
new file mode 100644
index 00000000000..2b53614ee3f
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.next.stderr
@@ -0,0 +1,44 @@
+error: item does not constrain `OneTy::{opaque#0}`
+  --> $DIR/generic_nondefining_use.rs:20:4
+   |
+LL | fn concrete_ty() -> OneTy<u32> {
+   |    ^^^^^^^^^^^
+   |
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
+  --> $DIR/generic_nondefining_use.rs:11:17
+   |
+LL | type OneTy<T> = impl Debug;
+   |                 ^^^^^^^^^^
+note: this use of `OneTy<u32>` does not have unique universal generic arguments
+  --> $DIR/generic_nondefining_use.rs:23:5
+   |
+LL |     5u32
+   |     ^^^^
+
+error: non-defining use of `OneLifetime<'_>` in the defining scope
+  --> $DIR/generic_nondefining_use.rs:27:1
+   |
+LL | fn concrete_lifetime() -> OneLifetime<'static> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: item does not constrain `OneConst::{opaque#0}`
+  --> $DIR/generic_nondefining_use.rs:35:4
+   |
+LL | fn concrete_const() -> OneConst<{ 123 }> {
+   |    ^^^^^^^^^^^^^^
+   |
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
+  --> $DIR/generic_nondefining_use.rs:15:33
+   |
+LL | type OneConst<const X: usize> = impl Debug;
+   |                                 ^^^^^^^^^^
+note: this use of `OneConst<123>` does not have unique universal generic arguments
+  --> $DIR/generic_nondefining_use.rs:38:5
+   |
+LL |     7u32
+   |     ^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs b/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs
index cf38c93bd92..7250a9ac0b3 100644
--- a/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs
+++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs
@@ -1,5 +1,9 @@
 #![feature(type_alias_impl_trait)]
 
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
 use std::fmt::Debug;
 
 fn main() {}
@@ -14,18 +18,22 @@ type OneConst<const X: usize> = impl Debug;
 
 #[define_opaque(OneTy)]
 fn concrete_ty() -> OneTy<u32> {
-    //~^ ERROR: expected generic type parameter, found `u32`
+    //[current]~^ ERROR: expected generic type parameter, found `u32`
+    //[next]~^^ ERROR: item does not constrain `OneTy::{opaque#0}`
     5u32
 }
 
 #[define_opaque(OneLifetime)]
 fn concrete_lifetime() -> OneLifetime<'static> {
+    //[next]~^ ERROR: non-defining use of `OneLifetime<'_>` in the defining scope
     6u32
-    //~^ ERROR: expected generic lifetime parameter, found `'static`
+    //[current]~^ ERROR: expected generic lifetime parameter, found `'static`
+
 }
 
 #[define_opaque(OneConst)]
 fn concrete_const() -> OneConst<{ 123 }> {
-    //~^ ERROR: expected generic constant parameter, found `123`
+    //[current]~^ ERROR: expected generic constant parameter, found `123`
+    //[next]~^^ ERROR: item does not constrain `OneConst::{opaque#0}`
     7u32
 }
diff --git a/tests/ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs b/tests/ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs
index 987fad2efea..476babdfb05 100644
--- a/tests/ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs
+++ b/tests/ui/type-alias-impl-trait/issue-87455-static-lifetime-ice.rs
@@ -1,6 +1,6 @@
 //@ check-pass
 
-use std::error::Error as StdError;
+use std::error::Error;
 use std::pin::Pin;
 use std::task::{Context, Poll};
 
@@ -51,7 +51,7 @@ impl<S> Stream for SseKeepAlive<S>
 where
     S: TryStream + Send + 'static,
     S::Ok: ServerSentEvent,
-    S::Error: StdError + Send + Sync + 'static,
+    S::Error: Error + Send + Sync + 'static,
 {
     type Item = Result<SseComment<&'static str>, ()>;
     fn poll_next(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Option<Self::Item>> {
@@ -65,7 +65,7 @@ pub fn keep<S>(
 where
     S: TryStream + Send + 'static,
     S::Ok: ServerSentEvent + Send,
-    S::Error: StdError + Send + Sync + 'static,
+    S::Error: Error + Send + Sync + 'static,
 {
     SseKeepAlive { event_stream }
 }
diff --git a/tests/ui/type-alias-impl-trait/normalize-args-before-defining-use-check.rs b/tests/ui/type-alias-impl-trait/normalize-args-before-defining-use-check.rs
new file mode 100644
index 00000000000..2879b8fe94c
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/normalize-args-before-defining-use-check.rs
@@ -0,0 +1,33 @@
+#![feature(type_alias_impl_trait)]
+
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@ [next] compile-flags: -Znext-solver
+//@ check-pass
+
+// Regression test for trait-system-refactor-initiative#49.
+
+trait Mirror<'a> {
+    type Assoc;
+}
+impl<'a, T> Mirror<'a> for T {
+    type Assoc = T;
+}
+
+type HrAmbigAlias<T> = impl Sized;
+fn ret_tait<T>() -> for<'a> fn(HrAmbigAlias<<T as Mirror<'a>>::Assoc>) {
+    |_| ()
+}
+
+#[define_opaque(HrAmbigAlias)]
+fn define_hr_ambig_alias<T>() {
+    let _: fn(T) = ret_tait::<T>();
+}
+
+type InUserType<T> = impl Sized;
+#[define_opaque(InUserType)]
+fn in_user_type<T>() {
+    let x: InUserType<<T as Mirror<'static>>::Assoc> = ();
+}
+
+fn main() {}
diff --git a/tests/ui/type/issue-7607-1.stderr b/tests/ui/type/issue-7607-1.stderr
index db4c8f25dbc..69b6d62e987 100644
--- a/tests/ui/type/issue-7607-1.stderr
+++ b/tests/ui/type/issue-7607-1.stderr
@@ -3,6 +3,7 @@ error[E0412]: cannot find type `Fo` in this scope
    |
 LL | impl Fo {
    |      ^^ help: a trait with a similar name exists: `Fn`
+   |
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
    = note: similarly named trait `Fn` defined here
diff --git a/tests/ui/typeck/issue-83693.stderr b/tests/ui/typeck/issue-83693.stderr
index 34bca426116..0359b8af93a 100644
--- a/tests/ui/typeck/issue-83693.stderr
+++ b/tests/ui/typeck/issue-83693.stderr
@@ -3,6 +3,7 @@ error[E0412]: cannot find type `F` in this scope
    |
 LL | impl F {
    |      ^ help: a trait with a similar name exists: `Fn`
+   |
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    |
    = note: similarly named trait `Fn` defined here
diff --git a/tests/ui/ufcs/ufcs-partially-resolved.stderr b/tests/ui/ufcs/ufcs-partially-resolved.stderr
index 69d6bd74a73..a854ecb0622 100644
--- a/tests/ui/ufcs/ufcs-partially-resolved.stderr
+++ b/tests/ui/ufcs/ufcs-partially-resolved.stderr
@@ -12,6 +12,7 @@ error[E0404]: expected trait, found enum `E`
    |
 LL |     let _: <u8 as E>::N;
    |                   ^ help: a trait with a similar name exists: `Eq`
+   |
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
    = note: similarly named trait `Eq` defined here
@@ -42,6 +43,7 @@ error[E0404]: expected trait, found enum `E`
    |
 LL |     <u8 as E>::N;
    |            ^ help: a trait with a similar name exists: `Eq`
+   |
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
    = note: similarly named trait `Eq` defined here
@@ -63,6 +65,7 @@ error[E0404]: expected trait, found enum `E`
    |
 LL |     let _: <u8 as E>::Y;
    |                   ^ help: a trait with a similar name exists: `Eq`
+   |
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
    = note: similarly named trait `Eq` defined here
@@ -72,6 +75,7 @@ error[E0404]: expected trait, found enum `E`
    |
 LL |     <u8 as E>::Y;
    |            ^ help: a trait with a similar name exists: `Eq`
+   |
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
    = note: similarly named trait `Eq` defined here
@@ -90,6 +94,7 @@ error[E0404]: expected trait, found enum `E`
    |
 LL |     let _: <u8 as E>::N::NN;
    |                   ^ help: a trait with a similar name exists: `Eq`
+   |
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
    = note: similarly named trait `Eq` defined here
@@ -120,6 +125,7 @@ error[E0404]: expected trait, found enum `E`
    |
 LL |     <u8 as E>::N::NN;
    |            ^ help: a trait with a similar name exists: `Eq`
+   |
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
    = note: similarly named trait `Eq` defined here
@@ -141,6 +147,7 @@ error[E0404]: expected trait, found enum `E`
    |
 LL |     let _: <u8 as E>::Y::NN;
    |                   ^ help: a trait with a similar name exists: `Eq`
+   |
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
    = note: similarly named trait `Eq` defined here
@@ -150,6 +157,7 @@ error[E0404]: expected trait, found enum `E`
    |
 LL |     <u8 as E>::Y::NN;
    |            ^ help: a trait with a similar name exists: `Eq`
+   |
   --> $SRC_DIR/core/src/cmp.rs:LL:COL
    |
    = note: similarly named trait `Eq` defined here
diff --git a/tests/ui/wasm/wasm-import-module.rs b/tests/ui/wasm/wasm-import-module.rs
index 2b3bca9a411..c38fcb1a000 100644
--- a/tests/ui/wasm/wasm-import-module.rs
+++ b/tests/ui/wasm/wasm-import-module.rs
@@ -1,12 +1,12 @@
 #![feature(link_cfg)]
 
-#[link(name = "...", wasm_import_module)] //~ ERROR: must be of the form
+#[link(name = "...", wasm_import_module)] //~ ERROR: malformed `link` attribute input
 extern "C" {}
 
-#[link(name = "...", wasm_import_module(x))] //~ ERROR: must be of the form
+#[link(name = "...", wasm_import_module(x))] //~ ERROR: malformed `link` attribute input
 extern "C" {}
 
-#[link(name = "...", wasm_import_module())] //~ ERROR: must be of the form
+#[link(name = "...", wasm_import_module())] //~ ERROR: malformed `link` attribute input
 extern "C" {}
 
 #[link(wasm_import_module = "foo", name = "bar")] //~ ERROR: `wasm_import_module` is incompatible with other arguments
diff --git a/tests/ui/wasm/wasm-import-module.stderr b/tests/ui/wasm/wasm-import-module.stderr
index 84f437941a7..f5ea449839b 100644
--- a/tests/ui/wasm/wasm-import-module.stderr
+++ b/tests/ui/wasm/wasm-import-module.stderr
@@ -1,20 +1,77 @@
-error: wasm import module must be of the form `wasm_import_module = "string"`
-  --> $DIR/wasm-import-module.rs:3:22
+error[E0539]: malformed `link` attribute input
+  --> $DIR/wasm-import-module.rs:3:1
    |
 LL | #[link(name = "...", wasm_import_module)]
-   |                      ^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^------------------^^
+   |                      |
+   |                      expected this to be of the form `wasm_import_module = "..."`
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(name = "...", wasm_import_module)]
+LL + #[link(name = "...")]
+   |
+LL - #[link(name = "...", wasm_import_module)]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link(name = "...", wasm_import_module)]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link(name = "...", wasm_import_module)]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
 
-error: wasm import module must be of the form `wasm_import_module = "string"`
-  --> $DIR/wasm-import-module.rs:6:22
+error[E0539]: malformed `link` attribute input
+  --> $DIR/wasm-import-module.rs:6:1
    |
 LL | #[link(name = "...", wasm_import_module(x))]
-   |                      ^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^---------------------^^
+   |                      |
+   |                      expected this to be of the form `wasm_import_module = "..."`
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(name = "...", wasm_import_module(x))]
+LL + #[link(name = "...")]
+   |
+LL - #[link(name = "...", wasm_import_module(x))]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link(name = "...", wasm_import_module(x))]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link(name = "...", wasm_import_module(x))]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
 
-error: wasm import module must be of the form `wasm_import_module = "string"`
-  --> $DIR/wasm-import-module.rs:9:22
+error[E0539]: malformed `link` attribute input
+  --> $DIR/wasm-import-module.rs:9:1
    |
 LL | #[link(name = "...", wasm_import_module())]
-   |                      ^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^--------------------^^
+   |                      |
+   |                      expected this to be of the form `wasm_import_module = "..."`
+   |
+   = note: for more information, visit <https://doc.rust-lang.org/reference/items/external-blocks.html#the-link-attribute>
+help: try changing it to one of the following valid forms of the attribute
+   |
+LL - #[link(name = "...", wasm_import_module())]
+LL + #[link(name = "...")]
+   |
+LL - #[link(name = "...", wasm_import_module())]
+LL + #[link(name = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+LL - #[link(name = "...", wasm_import_module())]
+LL + #[link(name = "...", kind = "dylib|static|...")]
+   |
+LL - #[link(name = "...", wasm_import_module())]
+LL + #[link(name = "...", kind = "dylib|static|...", wasm_import_module = "...", import_name_type = "decorated|noprefix|undecorated")]
+   |
+   = and 1 other candidate
 
 error: `wasm_import_module` is incompatible with other arguments in `#[link]` attributes
   --> $DIR/wasm-import-module.rs:12:8
@@ -36,3 +93,4 @@ LL | #[link(wasm_import_module = "foo", cfg(false))]
 
 error: aborting due to 6 previous errors
 
+For more information about this error, try `rustc --explain E0539`.