about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml5
-rw-r--r--Cargo.lock110
-rw-r--r--compiler/rustc_abi/src/lib.rs35
-rw-r--r--compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/back/write.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs5
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs1
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs125
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/rvalue.rs16
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs4
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs10
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs6
-rw-r--r--compiler/rustc_lint/src/ptr_nulls.rs4
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp18
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs26
-rw-r--r--compiler/rustc_mir_transform/src/inline/cycle.rs44
-rw-r--r--compiler/rustc_mir_transform/src/validate.rs18
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/trait_goals.rs6
-rw-r--r--compiler/rustc_privacy/src/lib.rs8
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs30
-rw-r--r--compiler/rustc_resolve/src/imports.rs38
-rw-r--r--compiler/rustc_resolve/src/late.rs2
-rw-r--r--compiler/rustc_resolve/src/lib.rs33
-rw-r--r--compiler/rustc_resolve/src/macros.rs2
-rw-r--r--compiler/rustc_target/src/spec/targets/amdgcn_amd_amdhsa.rs2
-rw-r--r--compiler/rustc_trait_selection/src/solve/delegate.rs22
-rw-r--r--compiler/rustc_trait_selection/src/traits/fulfill.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs20
-rw-r--r--compiler/rustc_traits/src/evaluate_obligation.rs2
-rw-r--r--library/core/src/any.rs2
-rw-r--r--library/core/src/async_iter/async_iter.rs10
-rw-r--r--library/core/src/cmp.rs5
-rw-r--r--library/core/src/fmt/mod.rs1
-rw-r--r--library/core/src/intrinsics/mod.rs20
-rw-r--r--library/core/src/iter/adapters/zip.rs74
-rw-r--r--library/core/src/iter/traits/collect.rs1
-rw-r--r--library/core/src/iter/traits/iterator.rs8
-rw-r--r--library/core/src/lib.rs6
-rw-r--r--library/core/src/mem/maybe_uninit.rs114
-rw-r--r--library/core/src/mem/mod.rs2
-rw-r--r--library/core/src/net/ip_addr.rs1
-rw-r--r--library/core/src/num/f128.rs6
-rw-r--r--library/core/src/num/f16.rs6
-rw-r--r--library/core/src/num/f32.rs6
-rw-r--r--library/core/src/num/f64.rs6
-rw-r--r--library/core/src/num/int_log10.rs4
-rw-r--r--library/core/src/num/uint_macros.rs45
-rw-r--r--library/core/src/primitive_docs.rs1
-rw-r--r--library/core/src/ptr/docs/as_uninit_slice.md20
-rw-r--r--library/core/src/ptr/mod.rs168
-rw-r--r--library/core/src/str/mod.rs1
-rw-r--r--library/core/src/ub_checks.rs18
-rw-r--r--library/coretests/tests/iter/adapters/cloned.rs3
-rw-r--r--library/coretests/tests/iter/adapters/zip.rs119
-rw-r--r--library/coretests/tests/lib.rs1
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/num/f32.rs12
-rw-r--r--library/std/src/num/f64.rs12
-rw-r--r--src/bootstrap/README.md2
-rw-r--r--src/bootstrap/bootstrap.py7
-rw-r--r--src/bootstrap/src/core/build_steps/check.rs9
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs90
-rw-r--r--src/bootstrap/src/core/build_steps/dist.rs23
-rw-r--r--src/bootstrap/src/core/build_steps/install.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs30
-rw-r--r--src/bootstrap/src/core/build_steps/tool.rs330
-rw-r--r--src/bootstrap/src/core/builder/cargo.rs55
-rw-r--r--src/bootstrap/src/core/builder/mod.rs3
-rw-r--r--src/bootstrap/src/core/builder/tests.rs45
-rw-r--r--src/bootstrap/src/lib.rs68
-rw-r--r--src/ci/github-actions/jobs.yml4
-rwxr-xr-xsrc/ci/scripts/install-mingw.sh5
-rw-r--r--src/doc/rustc-dev-guide/src/tests/directives.md8
-rw-r--r--src/doc/rustc-dev-guide/src/tests/ui.md20
-rw-r--r--src/doc/rustc/src/platform-support/xtensa.md2
-rw-r--r--src/librustdoc/clean/types.rs4
-rw-r--r--src/librustdoc/clean/utils.rs6
-rw-r--r--src/librustdoc/doctest.rs4
-rw-r--r--src/librustdoc/doctest/rust.rs2
-rw-r--r--src/librustdoc/formats/renderer.rs4
-rw-r--r--src/librustdoc/html/format.rs12
-rw-r--r--src/librustdoc/html/highlight.rs4
-rw-r--r--src/librustdoc/html/layout.rs1
-rw-r--r--src/librustdoc/html/markdown.rs4
-rw-r--r--src/librustdoc/html/render/context.rs84
-rw-r--r--src/librustdoc/html/render/mod.rs39
-rw-r--r--src/librustdoc/html/render/ordered_json.rs2
-rw-r--r--src/librustdoc/html/render/print_item.rs80
-rw-r--r--src/librustdoc/html/render/search_index.rs2
-rw-r--r--src/librustdoc/html/render/sidebar.rs2
-rw-r--r--src/librustdoc/html/render/sorted_template.rs3
-rw-r--r--src/librustdoc/html/static/js/rustdoc.d.ts7
-rw-r--r--src/librustdoc/html/static/js/search.js150
-rw-r--r--src/librustdoc/json/conversions.rs20
-rw-r--r--src/librustdoc/json/mod.rs6
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs25
-rw-r--r--src/librustdoc/passes/lint/redundant_explicit_links.rs16
-rw-r--r--src/librustdoc/passes/strip_aliased_non_local.rs10
m---------src/llvm-project0
-rw-r--r--src/tools/compiletest/src/common.rs62
-rw-r--r--src/tools/compiletest/src/directives.rs59
-rw-r--r--src/tools/compiletest/src/lib.rs19
-rw-r--r--src/tools/compiletest/src/runtest.rs7
-rw-r--r--src/tools/compiletest/src/runtest/ui.rs53
-rw-r--r--src/tools/miri/src/alloc_addresses/mod.rs2
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs4
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs2
-rw-r--r--src/tools/miri/tests/panic/mir-validation.stderr14
-rw-r--r--src/tools/miri/tests/pass-dep/libc/libc-time.rs6
-rw-r--r--src/tools/miri/tests/pass/intrinsics/type-id.rs19
-rw-r--r--src/tools/rustbook/Cargo.lock55
-rw-r--r--src/tools/rustdoc-js/tester.js71
-rw-r--r--src/tools/tidy/src/features.rs35
-rw-r--r--src/tools/tidy/src/fluent_period.rs29
-rw-r--r--src/tools/tidy/src/fluent_used.rs2
-rw-r--r--src/tools/tidy/src/lib.rs7
-rw-r--r--src/tools/tidy/src/mir_opt_tests.rs31
-rw-r--r--src/tools/tidy/src/rustdoc_templates.rs2
-rw-r--r--src/tools/tidy/src/style.rs46
-rw-r--r--src/tools/tidy/src/target_specific_tests.rs22
-rw-r--r--src/tools/tidy/src/ui_tests.rs43
-rw-r--r--src/tools/tidy/src/x_version.rs12
-rw-r--r--src/tools/unicode-table-generator/Cargo.toml2
-rw-r--r--src/tools/unicode-table-generator/src/cascading_map.rs14
-rw-r--r--src/tools/unicode-table-generator/src/case_mapping.rs2
-rw-r--r--src/tools/unicode-table-generator/src/main.rs40
-rw-r--r--src/tools/unicode-table-generator/src/raw_emitter.rs25
-rw-r--r--tests/assembly/cstring-merging.rs2
-rw-r--r--tests/assembly/sanitizer/kcfi/emit-arity-indicator.rs14
-rw-r--r--tests/assembly/wasm_exceptions.rs1
-rw-r--r--tests/codegen/enum/enum-discriminant-eq.rs223
-rw-r--r--tests/codegen/enum/enum-match.rs326
-rw-r--r--tests/codegen/repeat-operand-zero-len.rs28
-rw-r--r--tests/codegen/repeat-operand-zst-elem.rs28
-rw-r--r--tests/mir-opt/inline_double_cycle.a.Inline.panic-abort.diff48
-rw-r--r--tests/mir-opt/inline_double_cycle.a.Inline.panic-unwind.diff48
-rw-r--r--tests/mir-opt/inline_double_cycle.b.Inline.panic-abort.diff48
-rw-r--r--tests/mir-opt/inline_double_cycle.b.Inline.panic-unwind.diff48
-rw-r--r--tests/mir-opt/inline_double_cycle.rs22
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/README.md13
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/array/array.check26
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/array/array.rs20
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/array/rmake.rs28
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/array3d/array3d.check54
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/array3d/array3d.rs32
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/array3d/rmake.rs28
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/box/box.check12
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/box/box.rs18
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/box/rmake.rs28
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/const_pointer/const_pointer.check10
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/const_pointer/const_pointer.rs18
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/const_pointer/rmake.rs31
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/f32/f32.check12
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/f32/f32.rs19
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/f32/rmake.rs28
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/f64/f64.check10
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/f64/f64.rs20
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/f64/rmake.rs28
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/i128/i128.check10
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/i128/i128.rs14
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/i128/rmake.rs28
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/i16/i16.check10
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/i16/i16.rs14
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/i16/rmake.rs28
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/i32/i32.check10
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/i32/i32.rs14
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/i32/rmake.rs28
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/i8/i8.check10
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/i8/i8.rs14
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/i8/rmake.rs28
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/isize/isize.check10
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/isize/isize.rs14
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/isize/rmake.rs28
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/mut_pointer/mut_pointer.check10
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/mut_pointer/mut_pointer.rs18
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/mut_pointer/rmake.rs28
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/mut_ref/mut_ref.check10
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/mut_ref/mut_ref.rs18
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/mut_ref/rmake.rs28
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/ref/ref.check10
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/ref/ref.rs18
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/ref/rmake.rs28
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/struct/rmake.rs28
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/struct/struct.check10
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/struct/struct.rs23
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/u128/rmake.rs28
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/u128/u128.check10
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/u128/u128.rs14
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/u16/rmake.rs28
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/u16/u16.check10
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/u16/u16.rs14
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/u32/rmake.rs28
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/u32/u32.check10
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/u32/u32.rs14
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/u8/rmake.rs28
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/u8/u8.check10
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/u8/u8.rs14
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/union/rmake.rs28
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/union/union.check10
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/union/union.rs20
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/usize/rmake.rs28
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/usize/usize.check10
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/usize/usize.rs14
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/vec/rmake.rs28
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/vec/vec.check18
-rw-r--r--tests/run-make/autodiff/type-trees/type-analysis/vec/vec.rs14
-rw-r--r--tests/run-make/link-eh-frame-terminator/rmake.rs1
-rw-r--r--tests/rustdoc-js-std/alias-lev.js11
-rw-r--r--tests/rustdoc-js/non-english-identifier.js17
-rw-r--r--tests/ui/cfg/crt-static-with-target-features-works.rs24
-rw-r--r--tests/ui/cfg/crt-static-with-target-features-works.stderr8
-rw-r--r--tests/ui/contracts/contract-attributes-generics.rs6
-rw-r--r--tests/ui/contracts/contract-attributes-nest.rs4
-rw-r--r--tests/ui/contracts/contract-attributes-tail.rs4
-rw-r--r--tests/ui/contracts/contract-captures-via-closure-copy.rs2
-rw-r--r--tests/ui/contracts/contract-const-fn.rs4
-rw-r--r--tests/ui/contracts/contracts-ensures-early-fn-exit.rs6
-rw-r--r--tests/ui/contracts/internal_machinery/contract-ast-extensions-nest.rs4
-rw-r--r--tests/ui/contracts/internal_machinery/contract-ast-extensions-tail.rs4
-rw-r--r--tests/ui/contracts/internal_machinery/contract-intrinsics.rs4
-rw-r--r--tests/ui/contracts/internal_machinery/contract-lang-items.rs2
-rw-r--r--tests/ui/extern/extern-types-field-offset.rs2
-rw-r--r--tests/ui/impl-trait/in-bindings/implicit-sized.rs19
-rw-r--r--tests/ui/impl-trait/in-bindings/implicit-sized.stderr11
-rw-r--r--tests/ui/lint/invalid_null_args.rs5
-rw-r--r--tests/ui/lint/invalid_null_args.stderr58
-rw-r--r--tests/ui/lto/debuginfo-lto-alloc.rs3
-rw-r--r--tests/ui/mir/alignment/borrow_misaligned_field_projection.rs2
-rw-r--r--tests/ui/mir/alignment/misaligned_borrow.rs2
-rw-r--r--tests/ui/mir/alignment/misaligned_lhs.rs2
-rw-r--r--tests/ui/mir/alignment/misaligned_mut_borrow.rs2
-rw-r--r--tests/ui/mir/alignment/misaligned_rhs.rs2
-rw-r--r--tests/ui/mir/alignment/two_pointers.rs2
-rw-r--r--tests/ui/mir/enum/convert_non_integer_break.rs2
-rw-r--r--tests/ui/mir/enum/convert_non_integer_niche_break.rs2
-rw-r--r--tests/ui/mir/enum/negative_discr_break.rs2
-rw-r--r--tests/ui/mir/enum/niche_option_tuple_break.rs2
-rw-r--r--tests/ui/mir/enum/numbered_variants_break.rs2
-rw-r--r--tests/ui/mir/enum/option_with_bigger_niche_break.rs2
-rw-r--r--tests/ui/mir/enum/plain_no_data_break.rs2
-rw-r--r--tests/ui/mir/enum/single_with_repr_break.rs2
-rw-r--r--tests/ui/mir/enum/with_niche_int_break.rs2
-rw-r--r--tests/ui/mir/enum/wrap_break.rs2
-rw-r--r--tests/ui/mir/null/borrowed_mut_null.rs2
-rw-r--r--tests/ui/mir/null/borrowed_null.rs2
-rw-r--r--tests/ui/mir/null/borrowed_null_zst.rs2
-rw-r--r--tests/ui/mir/null/null_lhs.rs2
-rw-r--r--tests/ui/mir/null/null_rhs.rs2
-rw-r--r--tests/ui/mir/null/two_pointers.rs2
-rw-r--r--tests/ui/mir/validate/critical-edge.rs4
-rw-r--r--tests/ui/panics/panic-in-cleanup.rs2
-rw-r--r--tests/ui/panics/panic-in-ffi.rs2
-rw-r--r--tests/ui/panics/panic-in-message-fmt.rs2
-rw-r--r--tests/ui/panics/panic-main.rs12
-rw-r--r--tests/ui/precondition-checks/alignment.rs2
-rw-r--r--tests/ui/precondition-checks/ascii-char-digit_unchecked.rs2
-rw-r--r--tests/ui/precondition-checks/assert_unchecked.rs2
-rw-r--r--tests/ui/precondition-checks/char-from_u32_unchecked.rs2
-rw-r--r--tests/ui/precondition-checks/copy-nonoverlapping.rs2
-rw-r--r--tests/ui/precondition-checks/copy.rs2
-rw-r--r--tests/ui/precondition-checks/layout.rs2
-rw-r--r--tests/ui/precondition-checks/nonnull.rs2
-rw-r--r--tests/ui/precondition-checks/nonzero-from_mut_unchecked.rs2
-rw-r--r--tests/ui/precondition-checks/nonzero-new_unchecked.rs2
-rw-r--r--tests/ui/precondition-checks/read_volatile.rs8
-rw-r--r--tests/ui/precondition-checks/replace.rs2
-rw-r--r--tests/ui/precondition-checks/slice-from-raw-parts-mut.rs2
-rw-r--r--tests/ui/precondition-checks/slice-from-raw-parts.rs2
-rw-r--r--tests/ui/precondition-checks/slice-get_unchecked.rs2
-rw-r--r--tests/ui/precondition-checks/slice-get_unchecked_mut.rs2
-rw-r--r--tests/ui/precondition-checks/str-get_unchecked.rs2
-rw-r--r--tests/ui/precondition-checks/str-get_unchecked_mut.rs2
-rw-r--r--tests/ui/precondition-checks/swap-nonoverlapping.rs2
-rw-r--r--tests/ui/precondition-checks/unchecked_add.rs2
-rw-r--r--tests/ui/precondition-checks/unchecked_mul.rs2
-rw-r--r--tests/ui/precondition-checks/unchecked_shl.rs2
-rw-r--r--tests/ui/precondition-checks/unchecked_shr.rs2
-rw-r--r--tests/ui/precondition-checks/unchecked_sub.rs2
-rw-r--r--tests/ui/precondition-checks/unreachable_unchecked.rs2
-rw-r--r--tests/ui/precondition-checks/vec-from-parts.rs2
-rw-r--r--tests/ui/precondition-checks/vec-from-raw-parts.rs2
-rw-r--r--tests/ui/precondition-checks/vec-set-len.rs2
-rw-r--r--tests/ui/precondition-checks/write_volatile.rs8
-rw-r--r--tests/ui/print-request/supported-crate-types.rs5
-rw-r--r--tests/ui/privacy/private-in-public-warn.rs12
-rw-r--r--tests/ui/privacy/private-in-public-warn.stderr74
-rw-r--r--tests/ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs1
-rw-r--r--tests/ui/privacy/pub-priv-dep/pub-priv1.rs6
-rw-r--r--tests/ui/privacy/pub-priv-dep/pub-priv1.stderr30
-rw-r--r--tests/ui/sanitizer/address.rs2
-rw-r--r--tests/ui/sanitizer/badfree.rs2
-rw-r--r--tests/ui/sanitizer/new-llvm-pass-manager-thin-lto.rs2
-rw-r--r--tests/ui/sanitizer/thread.rs2
-rw-r--r--tests/ui/sanitizer/use-after-scope.rs2
-rw-r--r--tests/ui/sized-hierarchy/incomplete-inference-issue-143992.current_sized_hierarchy.stderr (renamed from tests/ui/sized-hierarchy/incomplete-inference-issue-143992.next.stderr)4
-rw-r--r--tests/ui/sized-hierarchy/incomplete-inference-issue-143992.next_sized_hierarchy.stderr17
-rw-r--r--tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs10
-rw-r--r--tests/ui/std/issue-81357-unsound-file-methods.rs2
-rw-r--r--tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr7
-rw-r--r--tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr19
-rw-r--r--tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr16
-rw-r--r--tests/ui/where-clauses/ignore-err-clauses.rs2
-rw-r--r--tests/ui/where-clauses/ignore-err-clauses.stderr29
311 files changed, 4343 insertions, 1556 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index dc8ac539a3a..e92afc14c20 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -182,11 +182,6 @@ jobs:
       - name: install MinGW
         run: src/ci/scripts/install-mingw.sh
 
-      # Workaround for spurious ci failures after mingw install
-      # see https://rust-lang.zulipchat.com/#narrow/channel/242791-t-infra/topic/Spurious.20bors.20CI.20failures/near/528915775
-      - name: ensure home dir exists
-        run: mkdir -p ~
-
       - name: install ninja
         run: src/ci/scripts/install-ninja.sh
 
diff --git a/Cargo.lock b/Cargo.lock
index 7d2fca8bb3f..1f7470e96c5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -216,7 +216,7 @@ dependencies = [
  "memchr",
  "serde",
  "serde_derive",
- "winnow 0.7.11",
+ "winnow 0.7.12",
 ]
 
 [[package]]
@@ -470,23 +470,12 @@ dependencies = [
 
 [[package]]
 name = "chrono-tz"
-version = "0.10.3"
+version = "0.10.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "efdce149c370f133a071ca8ef6ea340b7b88748ab0810097a9e2976eaa34b4f3"
+checksum = "a6139a8597ed92cf816dfb33f5dd6cf0bb93a6adc938f11039f371bc5bcd26c3"
 dependencies = [
  "chrono",
- "chrono-tz-build",
- "phf",
-]
-
-[[package]]
-name = "chrono-tz-build"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f10f8c9340e31fc120ff885fcdb54a0b48e474bbd77cab557f0c30a3e569402"
-dependencies = [
- "parse-zoneinfo",
- "phf_codegen",
+ "phf 0.12.1",
 ]
 
 [[package]]
@@ -501,9 +490,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.5.40"
+version = "4.5.41"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f"
+checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -521,9 +510,9 @@ dependencies = [
 
 [[package]]
 name = "clap_builder"
-version = "4.5.40"
+version = "4.5.41"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e"
+checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d"
 dependencies = [
  "anstream",
  "anstyle",
@@ -533,9 +522,9 @@ dependencies = [
 
 [[package]]
 name = "clap_derive"
-version = "4.5.40"
+version = "4.5.41"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce"
+checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491"
 dependencies = [
  "heck 0.5.0",
  "proc-macro2",
@@ -798,9 +787,9 @@ dependencies = [
 
 [[package]]
 name = "crc32fast"
-version = "1.4.2"
+version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
+checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
 dependencies = [
  "cfg-if",
 ]
@@ -989,9 +978,9 @@ dependencies = [
 
 [[package]]
 name = "derive_setters"
-version = "0.1.7"
+version = "0.1.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9c848e86c87e5cc305313041c5677d4d95d60baa71cf95e5f6ea2554bb629ff"
+checksum = "ae5c625eda104c228c06ecaf988d1c60e542176bd7a490e60eeda3493244c0c9"
 dependencies = [
  "darling",
  "proc-macro2",
@@ -2045,9 +2034,9 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
 
 [[package]]
 name = "libredox"
-version = "0.1.4"
+version = "0.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638"
+checksum = "4488594b9328dee448adb906d8b126d9b7deb7cf5c22161ee591610bb1be83c0"
 dependencies = [
  "bitflags",
  "libc",
@@ -2157,7 +2146,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18"
 dependencies = [
  "log",
- "phf",
+ "phf 0.11.3",
  "phf_codegen",
  "string_cache",
  "string_cache_codegen",
@@ -2196,9 +2185,9 @@ dependencies = [
 
 [[package]]
 name = "measureme"
-version = "12.0.1"
+version = "12.0.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "570a507d8948a66a97f42cbbaf8a6bb9516a51017d4ee949502ad7a10a864395"
+checksum = "6ebd1ebda747ae161a4a377bf93f87e18d46faad2331cc0c7d25b84b1d445f49"
 dependencies = [
  "log",
  "memmap2",
@@ -2633,15 +2622,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "parse-zoneinfo"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f2a05b18d44e2957b88f96ba460715e295bc1d7510468a2f3d3b44535d26c24"
-dependencies = [
- "regex",
-]
-
-[[package]]
 name = "pathdiff"
 version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2712,7 +2692,16 @@ version = "0.11.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
 dependencies = [
- "phf_shared",
+ "phf_shared 0.11.3",
+]
+
+[[package]]
+name = "phf"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7"
+dependencies = [
+ "phf_shared 0.12.1",
 ]
 
 [[package]]
@@ -2722,7 +2711,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a"
 dependencies = [
  "phf_generator",
- "phf_shared",
+ "phf_shared 0.11.3",
 ]
 
 [[package]]
@@ -2731,7 +2720,7 @@ version = "0.11.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
 dependencies = [
- "phf_shared",
+ "phf_shared 0.11.3",
  "rand 0.8.5",
 ]
 
@@ -2745,6 +2734,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "phf_shared"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06005508882fb681fd97892ecff4b7fd0fee13ef1aa569f8695dae7ab9099981"
+dependencies = [
+ "siphasher",
+]
+
+[[package]]
 name = "pin-project-lite"
 version = "0.2.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4752,15 +4750,15 @@ dependencies = [
 
 [[package]]
 name = "rustix"
-version = "1.0.7"
+version = "1.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
+checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
 dependencies = [
  "bitflags",
  "errno",
  "libc",
  "linux-raw-sys",
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
 ]
 
 [[package]]
@@ -4860,9 +4858,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.140"
+version = "1.0.141"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
+checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3"
 dependencies = [
  "itoa",
  "memchr",
@@ -5027,7 +5025,7 @@ checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f"
 dependencies = [
  "new_debug_unreachable",
  "parking_lot",
- "phf_shared",
+ "phf_shared 0.11.3",
  "precomputed-hash",
  "serde",
 ]
@@ -5039,7 +5037,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0"
 dependencies = [
  "phf_generator",
- "phf_shared",
+ "phf_shared 0.11.3",
  "proc-macro2",
  "quote",
 ]
@@ -5104,9 +5102,9 @@ dependencies = [
 
 [[package]]
 name = "sysinfo"
-version = "0.36.0"
+version = "0.36.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aab138f5c1bb35231de19049060a87977ad23e04f2303e953bc5c2947ac7dec4"
+checksum = "252800745060e7b9ffb7b2badbd8b31cfa4aa2e61af879d0a3bf2a317c20217d"
 dependencies = [
  "libc",
  "objc2-core-foundation",
@@ -5411,7 +5409,7 @@ dependencies = [
  "serde_spanned",
  "toml_datetime",
  "toml_write",
- "winnow 0.7.11",
+ "winnow 0.7.12",
 ]
 
 [[package]]
@@ -5829,9 +5827,9 @@ dependencies = [
 
 [[package]]
 name = "wasi-preview1-component-adapter-provider"
-version = "34.0.1"
+version = "34.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aafa1e6af9a954a4bcf6ef420c33355d0ce84ddc6afbcba7bb6f05126f9120ae"
+checksum = "33696c5f1ff1e083de9f36c3da471abd736362bc173e093f8b0b1ed5a387e39b"
 
 [[package]]
 name = "wasm-bindgen"
@@ -6475,9 +6473,9 @@ dependencies = [
 
 [[package]]
 name = "winnow"
-version = "0.7.11"
+version = "0.7.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd"
+checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95"
 dependencies = [
  "memchr",
 ]
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index de4b5a46c81..5bd73502d98 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -43,7 +43,7 @@ use std::fmt;
 #[cfg(feature = "nightly")]
 use std::iter::Step;
 use std::num::{NonZeroUsize, ParseIntError};
-use std::ops::{Add, AddAssign, Deref, Mul, RangeInclusive, Sub};
+use std::ops::{Add, AddAssign, Deref, Mul, RangeFull, RangeInclusive, Sub};
 use std::str::FromStr;
 
 use bitflags::bitflags;
@@ -1391,12 +1391,45 @@ impl WrappingRange {
     }
 
     /// Returns `true` if `size` completely fills the range.
+    ///
+    /// Note that this is *not* the same as `self == WrappingRange::full(size)`.
+    /// Niche calculations can produce full ranges which are not the canonical one;
+    /// for example `Option<NonZero<u16>>` gets `valid_range: (..=0) | (1..)`.
     #[inline]
     fn is_full_for(&self, size: Size) -> bool {
         let max_value = size.unsigned_int_max();
         debug_assert!(self.start <= max_value && self.end <= max_value);
         self.start == (self.end.wrapping_add(1) & max_value)
     }
+
+    /// Checks whether this range is considered non-wrapping when the values are
+    /// interpreted as *unsigned* numbers of width `size`.
+    ///
+    /// Returns `Ok(true)` if there's no wrap-around, `Ok(false)` if there is,
+    /// and `Err(..)` if the range is full so it depends how you think about it.
+    #[inline]
+    pub fn no_unsigned_wraparound(&self, size: Size) -> Result<bool, RangeFull> {
+        if self.is_full_for(size) { Err(..) } else { Ok(self.start <= self.end) }
+    }
+
+    /// Checks whether this range is considered non-wrapping when the values are
+    /// interpreted as *signed* numbers of width `size`.
+    ///
+    /// This is heavily dependent on the `size`, as `100..=200` does wrap when
+    /// interpreted as `i8`, but doesn't when interpreted as `i16`.
+    ///
+    /// Returns `Ok(true)` if there's no wrap-around, `Ok(false)` if there is,
+    /// and `Err(..)` if the range is full so it depends how you think about it.
+    #[inline]
+    pub fn no_signed_wraparound(&self, size: Size) -> Result<bool, RangeFull> {
+        if self.is_full_for(size) {
+            Err(..)
+        } else {
+            let start: i128 = size.sign_extend(self.start);
+            let end: i128 = size.sign_extend(self.end);
+            Ok(start <= end)
+        }
+    }
 }
 
 impl fmt::Debug for WrappingRange {
diff --git a/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs
index dfde4595590..8e82013e94a 100644
--- a/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs
+++ b/compiler/rustc_codegen_llvm/src/back/owned_target_machine.rs
@@ -39,6 +39,7 @@ impl OwnedTargetMachine {
         debug_info_compression: &CStr,
         use_emulated_tls: bool,
         args_cstr_buff: &[u8],
+        use_wasm_eh: bool,
     ) -> Result<Self, LlvmError<'static>> {
         assert!(args_cstr_buff.len() > 0);
         assert!(
@@ -72,6 +73,7 @@ impl OwnedTargetMachine {
                 use_emulated_tls,
                 args_cstr_buff.as_ptr() as *const c_char,
                 args_cstr_buff.len(),
+                use_wasm_eh,
             )
         };
 
diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs
index 68279008c03..6f8fba2a30d 100644
--- a/compiler/rustc_codegen_llvm/src/back/write.rs
+++ b/compiler/rustc_codegen_llvm/src/back/write.rs
@@ -15,6 +15,7 @@ use rustc_codegen_ssa::back::write::{
     BitcodeSection, CodegenContext, EmitObj, ModuleConfig, TargetMachineFactoryConfig,
     TargetMachineFactoryFn,
 };
+use rustc_codegen_ssa::base::wants_wasm_eh;
 use rustc_codegen_ssa::traits::*;
 use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, ModuleKind};
 use rustc_data_structures::profiling::SelfProfilerRef;
@@ -285,6 +286,8 @@ pub(crate) fn target_machine_factory(
     let file_name_display_preference =
         sess.filename_display_preference(RemapPathScopeComponents::DEBUGINFO);
 
+    let use_wasm_eh = wants_wasm_eh(sess);
+
     Arc::new(move |config: TargetMachineFactoryConfig| {
         let path_to_cstring_helper = |path: Option<PathBuf>| -> CString {
             let path = path.unwrap_or_default();
@@ -321,6 +324,7 @@ pub(crate) fn target_machine_factory(
             &debuginfo_compression,
             use_emulated_tls,
             &args_cstr_buff,
+            use_wasm_eh,
         )
     })
 }
diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs
index 6a23becaa96..34bed2a1d2a 100644
--- a/compiler/rustc_codegen_llvm/src/context.rs
+++ b/compiler/rustc_codegen_llvm/src/context.rs
@@ -207,6 +207,11 @@ pub(crate) unsafe fn create_module<'ll>(
             // LLVM 21 updated the default layout on nvptx: https://github.com/llvm/llvm-project/pull/124961
             target_data_layout = target_data_layout.replace("e-p6:32:32-i64", "e-i64");
         }
+        if sess.target.arch == "amdgpu" {
+            // LLVM 21 adds the address width for address space 8.
+            // See https://github.com/llvm/llvm-project/pull/139419
+            target_data_layout = target_data_layout.replace("p8:128:128:128:48", "p8:128:128")
+        }
     }
 
     // Ensure the data-layout values hardcoded remain the defaults.
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 0b1e632cbc4..80a0e5c5acc 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -2425,6 +2425,7 @@ unsafe extern "C" {
         UseEmulatedTls: bool,
         ArgsCstrBuff: *const c_char,
         ArgsCstrBuffLen: usize,
+        UseWasmEH: bool,
     ) -> *mut TargetMachine;
 
     pub(crate) fn LLVMRustDisposeTargetMachine(T: *mut TargetMachine);
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index b0d191528a8..6a3fdb6ede1 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -486,6 +486,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
                 // value and the variant index match, since that's all `Niche` can encode.
 
                 let relative_max = niche_variants.end().as_u32() - niche_variants.start().as_u32();
+                let niche_start_const = bx.cx().const_uint_big(tag_llty, niche_start);
 
                 // We have a subrange `niche_start..=niche_end` inside `range`.
                 // If the value of the tag is inside this subrange, it's a
@@ -511,35 +512,88 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
                     // } else {
                     //     untagged_variant
                     // }
-                    let niche_start = bx.cx().const_uint_big(tag_llty, niche_start);
-                    let is_niche = bx.icmp(IntPredicate::IntEQ, tag, niche_start);
+                    let is_niche = bx.icmp(IntPredicate::IntEQ, tag, niche_start_const);
                     let tagged_discr =
                         bx.cx().const_uint(cast_to, niche_variants.start().as_u32() as u64);
                     (is_niche, tagged_discr, 0)
                 } else {
-                    // The special cases don't apply, so we'll have to go with
-                    // the general algorithm.
-                    let relative_discr = bx.sub(tag, bx.cx().const_uint_big(tag_llty, niche_start));
+                    // With multiple niched variants we'll have to actually compute
+                    // the variant index from the stored tag.
+                    //
+                    // However, there's still one small optimization we can often do for
+                    // determining *whether* a tag value is a natural value or a niched
+                    // variant. The general algorithm involves a subtraction that often
+                    // wraps in practice, making it tricky to analyse. However, in cases
+                    // where there are few enough possible values of the tag that it doesn't
+                    // need to wrap around, we can instead just look for the contiguous
+                    // tag values on the end of the range with a single comparison.
+                    //
+                    // For example, take the type `enum Demo { A, B, Untagged(bool) }`.
+                    // The `bool` is {0, 1}, and the two other variants are given the
+                    // tags {2, 3} respectively. That means the `tag_range` is
+                    // `[0, 3]`, which doesn't wrap as unsigned (nor as signed), so
+                    // we can test for the niched variants with just `>= 2`.
+                    //
+                    // That means we're looking either for the niche values *above*
+                    // the natural values of the untagged variant:
+                    //
+                    //             niche_start                  niche_end
+                    //                  |                           |
+                    //                  v                           v
+                    // MIN -------------+---------------------------+---------- MAX
+                    //         ^        |         is niche          |
+                    //         |        +---------------------------+
+                    //         |                                    |
+                    //   tag_range.start                      tag_range.end
+                    //
+                    // Or *below* the natural values:
+                    //
+                    //    niche_start              niche_end
+                    //         |                       |
+                    //         v                       v
+                    // MIN ----+-----------------------+---------------------- MAX
+                    //         |       is niche        |           ^
+                    //         +-----------------------+           |
+                    //         |                                   |
+                    //   tag_range.start                      tag_range.end
+                    //
+                    // With those two options and having the flexibility to choose
+                    // between a signed or unsigned comparison on the tag, that
+                    // covers most realistic scenarios. The tests have a (contrived)
+                    // example of a 1-byte enum with over 128 niched variants which
+                    // wraps both as signed as unsigned, though, and for something
+                    // like that we're stuck with the general algorithm.
+
+                    let tag_range = tag_scalar.valid_range(&dl);
+                    let tag_size = tag_scalar.size(&dl);
+                    let niche_end = u128::from(relative_max).wrapping_add(niche_start);
+                    let niche_end = tag_size.truncate(niche_end);
+
+                    let relative_discr = bx.sub(tag, niche_start_const);
                     let cast_tag = bx.intcast(relative_discr, cast_to, false);
-                    let is_niche = bx.icmp(
-                        IntPredicate::IntULE,
-                        relative_discr,
-                        bx.cx().const_uint(tag_llty, relative_max as u64),
-                    );
-
-                    // Thanks to parameter attributes and load metadata, LLVM already knows
-                    // the general valid range of the tag. It's possible, though, for there
-                    // to be an impossible value *in the middle*, which those ranges don't
-                    // communicate, so it's worth an `assume` to let the optimizer know.
-                    if niche_variants.contains(&untagged_variant)
-                        && bx.cx().sess().opts.optimize != OptLevel::No
-                    {
-                        let impossible =
-                            u64::from(untagged_variant.as_u32() - niche_variants.start().as_u32());
-                        let impossible = bx.cx().const_uint(tag_llty, impossible);
-                        let ne = bx.icmp(IntPredicate::IntNE, relative_discr, impossible);
-                        bx.assume(ne);
-                    }
+                    let is_niche = if tag_range.no_unsigned_wraparound(tag_size) == Ok(true) {
+                        if niche_start == tag_range.start {
+                            let niche_end_const = bx.cx().const_uint_big(tag_llty, niche_end);
+                            bx.icmp(IntPredicate::IntULE, tag, niche_end_const)
+                        } else {
+                            assert_eq!(niche_end, tag_range.end);
+                            bx.icmp(IntPredicate::IntUGE, tag, niche_start_const)
+                        }
+                    } else if tag_range.no_signed_wraparound(tag_size) == Ok(true) {
+                        if niche_start == tag_range.start {
+                            let niche_end_const = bx.cx().const_uint_big(tag_llty, niche_end);
+                            bx.icmp(IntPredicate::IntSLE, tag, niche_end_const)
+                        } else {
+                            assert_eq!(niche_end, tag_range.end);
+                            bx.icmp(IntPredicate::IntSGE, tag, niche_start_const)
+                        }
+                    } else {
+                        bx.icmp(
+                            IntPredicate::IntULE,
+                            relative_discr,
+                            bx.cx().const_uint(tag_llty, relative_max as u64),
+                        )
+                    };
 
                     (is_niche, cast_tag, niche_variants.start().as_u32() as u128)
                 };
@@ -550,11 +604,24 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
                     bx.add(tagged_discr, bx.cx().const_uint_big(cast_to, delta))
                 };
 
-                let discr = bx.select(
-                    is_niche,
-                    tagged_discr,
-                    bx.cx().const_uint(cast_to, untagged_variant.as_u32() as u64),
-                );
+                let untagged_variant_const =
+                    bx.cx().const_uint(cast_to, u64::from(untagged_variant.as_u32()));
+
+                // Thanks to parameter attributes and load metadata, LLVM already knows
+                // the general valid range of the tag. It's possible, though, for there
+                // to be an impossible value *in the middle*, which those ranges don't
+                // communicate, so it's worth an `assume` to let the optimizer know.
+                // Most importantly, this means when optimizing a variant test like
+                // `SELECT(is_niche, complex, CONST) == CONST` it's ok to simplify that
+                // to `!is_niche` because the `complex` part can't possibly match.
+                if niche_variants.contains(&untagged_variant)
+                    && bx.cx().sess().opts.optimize != OptLevel::No
+                {
+                    let ne = bx.icmp(IntPredicate::IntNE, tagged_discr, untagged_variant_const);
+                    bx.assume(ne);
+                }
+
+                let discr = bx.select(is_niche, tagged_discr, untagged_variant_const);
 
                 // In principle we could insert assumes on the possible range of `discr`, but
                 // currently in LLVM this isn't worth it because the original `tag` will
diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
index 2587e89417a..e872f8434e5 100644
--- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs
@@ -630,7 +630,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 OperandRef { val: OperandValue::Immediate(static_), layout }
             }
             mir::Rvalue::Use(ref operand) => self.codegen_operand(bx, operand),
-            mir::Rvalue::Repeat(..) => bug!("{rvalue:?} in codegen_rvalue_operand"),
+            mir::Rvalue::Repeat(ref elem, len_const) => {
+                // All arrays have `BackendRepr::Memory`, so only the ZST cases
+                // end up here. Anything else forces the destination local to be
+                // `Memory`, and thus ends up handled in `codegen_rvalue` instead.
+                let operand = self.codegen_operand(bx, elem);
+                let array_ty = Ty::new_array_with_const_len(bx.tcx(), operand.layout.ty, len_const);
+                let array_ty = self.monomorphize(array_ty);
+                let array_layout = bx.layout_of(array_ty);
+                assert!(array_layout.is_zst());
+                OperandRef { val: OperandValue::ZeroSized, layout: array_layout }
+            }
             mir::Rvalue::Aggregate(ref kind, ref fields) => {
                 let (variant_index, active_field_index) = match **kind {
                     mir::AggregateKind::Adt(_, variant_index, _, _, active_field_index) => {
@@ -1000,12 +1010,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             mir::Rvalue::NullaryOp(..) |
             mir::Rvalue::ThreadLocalRef(_) |
             mir::Rvalue::Use(..) |
+            mir::Rvalue::Repeat(..) | // (*)
             mir::Rvalue::Aggregate(..) | // (*)
             mir::Rvalue::WrapUnsafeBinder(..) => // (*)
                 true,
-            // Arrays are always aggregates, so it's not worth checking anything here.
-            // (If it's really `[(); N]` or `[T; 0]` and we use the place path, fine.)
-            mir::Rvalue::Repeat(..) => false,
         }
 
         // (*) this is only true if the type is suitable
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 53df99993f0..def4ec13e87 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -149,14 +149,14 @@ fn parse_rust_feature_flag<'a>(
         if let Some(base_feature) = feature.strip_prefix('+') {
             // Skip features that are not target features, but rustc features.
             if RUSTC_SPECIFIC_FEATURES.contains(&base_feature) {
-                return;
+                continue;
             }
 
             callback(base_feature, sess.target.implied_target_features(base_feature), true)
         } else if let Some(base_feature) = feature.strip_prefix('-') {
             // Skip features that are not target features, but rustc features.
             if RUSTC_SPECIFIC_FEATURES.contains(&base_feature) {
-                return;
+                continue;
             }
 
             // If `f1` implies `f2`, then `!f2` implies `!f1` -- this is standard logical
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index 47228de5213..20c8e983cea 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -67,8 +67,8 @@ pub enum AllocKind {
     LiveData,
     /// A function allocation (that fn ptrs point to).
     Function,
-    /// A (symbolic) vtable allocation.
-    VTable,
+    /// A "virtual" allocation, used for vtables and TypeId.
+    Virtual,
     /// A dead allocation.
     Dead,
 }
@@ -950,11 +950,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
             let (size, align) = global_alloc.size_and_align(*self.tcx, self.typing_env);
             let mutbl = global_alloc.mutability(*self.tcx, self.typing_env);
             let kind = match global_alloc {
-                GlobalAlloc::TypeId { .. }
-                | GlobalAlloc::Static { .. }
-                | GlobalAlloc::Memory { .. } => AllocKind::LiveData,
+                GlobalAlloc::Static { .. } | GlobalAlloc::Memory { .. } => AllocKind::LiveData,
                 GlobalAlloc::Function { .. } => bug!("We already checked function pointers above"),
-                GlobalAlloc::VTable { .. } => AllocKind::VTable,
+                GlobalAlloc::VTable { .. } | GlobalAlloc::TypeId { .. } => AllocKind::Virtual,
             };
             return AllocInfo::new(size, align, kind, mutbl);
         }
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index a128f8d31a1..96c7ba6ed27 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -1421,7 +1421,7 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
     ///
     /// See `emit` and `delay_as_bug` for details.
     #[track_caller]
-    pub fn emit_unless(mut self, delay: bool) -> G::EmitResult {
+    pub fn emit_unless_delay(mut self, delay: bool) -> G::EmitResult {
         if delay {
             self.downgrade_to_delayed_bug();
         }
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index 87db80f2423..e24426f9fed 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -1173,7 +1173,7 @@ fn check_region_bounds_on_impl_item<'tcx>(
             bounds_span,
             where_span,
         })
-        .emit_unless(delay);
+        .emit_unless_delay(delay);
 
     Err(reported)
 }
@@ -1481,7 +1481,7 @@ fn compare_self_type<'tcx>(
             } else {
                 err.note_trait_signature(trait_m.name(), trait_m.signature(tcx));
             }
-            return Err(err.emit_unless(delay));
+            return Err(err.emit_unless_delay(delay));
         }
 
         (true, false) => {
@@ -1502,7 +1502,7 @@ fn compare_self_type<'tcx>(
                 err.note_trait_signature(trait_m.name(), trait_m.signature(tcx));
             }
 
-            return Err(err.emit_unless(delay));
+            return Err(err.emit_unless_delay(delay));
         }
     }
 
@@ -1662,7 +1662,7 @@ fn compare_number_of_generics<'tcx>(
                 err.span_label(*span, "`impl Trait` introduces an implicit type parameter");
             }
 
-            let reported = err.emit_unless(delay);
+            let reported = err.emit_unless_delay(delay);
             err_occurred = Some(reported);
         }
     }
@@ -1745,7 +1745,7 @@ fn compare_number_of_method_arguments<'tcx>(
             ),
         );
 
-        return Err(err.emit_unless(delay));
+        return Err(err.emit_unless_delay(delay));
     }
 
     Ok(())
@@ -1872,7 +1872,7 @@ fn compare_synthetic_generics<'tcx>(
                     );
                 };
             }
-            error_found = Some(err.emit_unless(delay));
+            error_found = Some(err.emit_unless_delay(delay));
         }
     }
     if let Some(reported) = error_found { Err(reported) } else { Ok(()) }
@@ -1974,7 +1974,7 @@ fn compare_generic_param_kinds<'tcx>(
             err.span_label(impl_header_span, "");
             err.span_label(param_impl_span, make_param_message("found", param_impl));
 
-            let reported = err.emit_unless(delay);
+            let reported = err.emit_unless_delay(delay);
             return Err(reported);
         }
     }
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 77e63e38c8c..eb3492f5de6 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -2495,7 +2495,7 @@ fn deny_non_region_late_bound(
             format!("late-bound {what} parameter not allowed on {where_}"),
         );
 
-        let guar = diag.emit_unless(!tcx.features().non_lifetime_binders() || !first);
+        let guar = diag.emit_unless_delay(!tcx.features().non_lifetime_binders() || !first);
 
         first = false;
         *arg = ResolvedArg::Error(guar);
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
index 8c7c3750865..fc519c194bb 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs
@@ -570,7 +570,7 @@ pub(crate) fn check_generic_arg_count(
                     gen_args,
                     def_id,
                 ))
-                .emit_unless(all_params_are_binded)
+                .emit_unless_delay(all_params_are_binded)
         });
 
         Err(reported)
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 78794cd8eb6..d7687998358 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -2495,6 +2495,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                     ty::List::empty(),
                     PredicateFilter::All,
                 );
+                self.add_sizedness_bounds(
+                    &mut bounds,
+                    self_ty,
+                    hir_bounds,
+                    None,
+                    None,
+                    hir_ty.span,
+                );
                 self.register_trait_ascription_bounds(bounds, hir_ty.hir_id, hir_ty.span);
                 self_ty
             }
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index b2a229ad651..6d67535da5f 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1775,7 +1775,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                     );
                 }
 
-                let reported = err.emit_unless(unsized_return);
+                let reported = err.emit_unless_delay(unsized_return);
 
                 self.final_ty = Some(Ty::new_error(fcx.tcx, reported));
             }
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 067ee0f0eb0..08e8164078c 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -1549,7 +1549,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // If the assignment expression itself is ill-formed, don't
         // bother emitting another error
-        err.emit_unless(lhs_ty.references_error() || rhs_ty.references_error())
+        err.emit_unless_delay(lhs_ty.references_error() || rhs_ty.references_error())
     }
 
     pub(super) fn check_expr_let(
@@ -3865,7 +3865,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         self.dcx()
                             .create_err(NoVariantNamed { span: ident.span, ident, ty: container })
                             .with_span_label(field.span, "variant not found")
-                            .emit_unless(container.references_error());
+                            .emit_unless_delay(container.references_error());
                         break;
                     };
                     let Some(&subfield) = fields.next() else {
@@ -3897,7 +3897,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 enum_span: field.span,
                                 field_span: subident.span,
                             })
-                            .emit_unless(container.references_error());
+                            .emit_unless_delay(container.references_error());
                         break;
                     };
 
diff --git a/compiler/rustc_lint/src/ptr_nulls.rs b/compiler/rustc_lint/src/ptr_nulls.rs
index 826bce2c315..b2fa0fba76d 100644
--- a/compiler/rustc_lint/src/ptr_nulls.rs
+++ b/compiler/rustc_lint/src/ptr_nulls.rs
@@ -160,12 +160,10 @@ impl<'tcx> LateLintPass<'tcx> for PtrNullChecks {
                 let (arg_indices, are_zsts_allowed): (&[_], _) = match diag_name {
                     sym::ptr_read
                     | sym::ptr_read_unaligned
-                    | sym::ptr_read_volatile
                     | sym::ptr_replace
                     | sym::ptr_write
                     | sym::ptr_write_bytes
-                    | sym::ptr_write_unaligned
-                    | sym::ptr_write_volatile => (&[0], true),
+                    | sym::ptr_write_unaligned => (&[0], true),
                     sym::slice_from_raw_parts | sym::slice_from_raw_parts_mut => (&[0], false),
                     sym::ptr_copy
                     | sym::ptr_copy_nonoverlapping
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index cc33764e485..a2e4d7306cb 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -396,7 +396,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
     bool EmitStackSizeSection, bool RelaxELFRelocations, bool UseInitArray,
     const char *SplitDwarfFile, const char *OutputObjFile,
     const char *DebugInfoCompression, bool UseEmulatedTls,
-    const char *ArgsCstrBuff, size_t ArgsCstrBuffLen) {
+    const char *ArgsCstrBuff, size_t ArgsCstrBuffLen, bool UseWasmEH) {
 
   auto OptLevel = fromRust(RustOptLevel);
   auto RM = fromRust(RustReloc);
@@ -462,6 +462,9 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
     Options.ThreadModel = ThreadModel::Single;
   }
 
+  if (UseWasmEH)
+    Options.ExceptionModel = ExceptionHandling::Wasm;
+
   Options.EmitStackSizeSection = EmitStackSizeSection;
 
   if (ArgsCstrBuff != nullptr) {
@@ -700,6 +703,10 @@ struct LLVMRustSanitizerOptions {
 #ifdef ENZYME
 extern "C" void registerEnzymeAndPassPipeline(llvm::PassBuilder &PB,
                                               /* augmentPassBuilder */ bool);
+
+extern "C" {
+extern llvm::cl::opt<std::string> EnzymeFunctionToAnalyze;
+}
 #endif
 
 extern "C" LLVMRustResult LLVMRustOptimize(
@@ -1069,6 +1076,15 @@ extern "C" LLVMRustResult LLVMRustOptimize(
       return LLVMRustResult::Failure;
     }
 
+    // Check if PrintTAFn was used and add type analysis pass if needed
+    if (!EnzymeFunctionToAnalyze.empty()) {
+      if (auto Err = PB.parsePassPipeline(MPM, "print-type-analysis")) {
+        std::string ErrMsg = toString(std::move(Err));
+        LLVMRustSetLastError(ErrMsg.c_str());
+        return LLVMRustResult::Failure;
+      }
+    }
+
     if (PrintAfterEnzyme) {
       // Handle the Rust flag `-Zautodiff=PrintModAfter`.
       std::string Banner = "Module after EnzymeNewPM";
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 2eb530f328d..9ee64df0ad0 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -1210,30 +1210,6 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
                     }
 
                     for (assoc_item_def_id, term) in assoc_items {
-                        // Skip printing `<{coroutine@} as Coroutine<_>>::Return` from async blocks,
-                        // unless we can find out what coroutine return type it comes from.
-                        let term = if let Some(ty) = term.skip_binder().as_type()
-                            && let ty::Alias(ty::Projection, proj) = ty.kind()
-                            && let Some(assoc) = tcx.opt_associated_item(proj.def_id)
-                            && assoc
-                                .trait_container(tcx)
-                                .is_some_and(|def_id| tcx.is_lang_item(def_id, LangItem::Coroutine))
-                            && assoc.opt_name() == Some(rustc_span::sym::Return)
-                        {
-                            if let ty::Coroutine(_, args) = args.type_at(0).kind() {
-                                let return_ty = args.as_coroutine().return_ty();
-                                if !return_ty.is_ty_var() {
-                                    return_ty.into()
-                                } else {
-                                    continue;
-                                }
-                            } else {
-                                continue;
-                            }
-                        } else {
-                            term.skip_binder()
-                        };
-
                         if first {
                             p!("<");
                             first = false;
@@ -1243,7 +1219,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
 
                         p!(write("{} = ", tcx.associated_item(assoc_item_def_id).name()));
 
-                        match term.kind() {
+                        match term.skip_binder().kind() {
                             TermKind::Ty(ty) => p!(print(ty)),
                             TermKind::Const(c) => p!(print(c)),
                         };
diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs
index 93a81f0dca5..7f9234d1dc8 100644
--- a/compiler/rustc_mir_transform/src/inline/cycle.rs
+++ b/compiler/rustc_mir_transform/src/inline/cycle.rs
@@ -64,15 +64,15 @@ fn process<'tcx>(
     typing_env: ty::TypingEnv<'tcx>,
     caller: ty::Instance<'tcx>,
     target: LocalDefId,
-    seen: &mut FxHashSet<ty::Instance<'tcx>>,
+    seen: &mut FxHashMap<ty::Instance<'tcx>, bool>,
     involved: &mut FxHashSet<LocalDefId>,
     recursion_limiter: &mut FxHashMap<DefId, usize>,
     recursion_limit: Limit,
 ) -> bool {
     trace!(%caller);
-    let mut cycle_found = false;
+    let mut reaches_root = false;
 
-    for &(callee, args) in tcx.mir_inliner_callees(caller.def) {
+    for &(callee_def_id, args) in tcx.mir_inliner_callees(caller.def) {
         let Ok(args) = caller.try_instantiate_mir_and_normalize_erasing_regions(
             tcx,
             typing_env,
@@ -81,14 +81,17 @@ fn process<'tcx>(
             trace!(?caller, ?typing_env, ?args, "cannot normalize, skipping");
             continue;
         };
-        let Ok(Some(callee)) = ty::Instance::try_resolve(tcx, typing_env, callee, args) else {
-            trace!(?callee, "cannot resolve, skipping");
+        let Ok(Some(callee)) = ty::Instance::try_resolve(tcx, typing_env, callee_def_id, args)
+        else {
+            trace!(?callee_def_id, "cannot resolve, skipping");
             continue;
         };
 
         // Found a path.
         if callee.def_id() == target.to_def_id() {
-            cycle_found = true;
+            reaches_root = true;
+            seen.insert(callee, true);
+            continue;
         }
 
         if tcx.is_constructor(callee.def_id()) {
@@ -101,10 +104,17 @@ fn process<'tcx>(
             continue;
         }
 
-        if seen.insert(callee) {
+        let callee_reaches_root = if let Some(&c) = seen.get(&callee) {
+            // Even if we have seen this callee before, and thus don't need
+            // to recurse into it, we still need to propagate whether it reaches
+            // the root so that we can mark all the involved callers, in case we
+            // end up reaching that same recursive callee through some *other* cycle.
+            c
+        } else {
+            seen.insert(callee, false);
             let recursion = recursion_limiter.entry(callee.def_id()).or_default();
             trace!(?callee, recursion = *recursion);
-            let found_recursion = if recursion_limit.value_within_limit(*recursion) {
+            let callee_reaches_root = if recursion_limit.value_within_limit(*recursion) {
                 *recursion += 1;
                 ensure_sufficient_stack(|| {
                     process(
@@ -122,17 +132,19 @@ fn process<'tcx>(
                 // Pessimistically assume that there could be recursion.
                 true
             };
-            if found_recursion {
-                if let Some(callee) = callee.def_id().as_local() {
-                    // Calling `optimized_mir` of a non-local definition cannot cycle.
-                    involved.insert(callee);
-                }
-                cycle_found = true;
+            seen.insert(callee, callee_reaches_root);
+            callee_reaches_root
+        };
+        if callee_reaches_root {
+            if let Some(callee_def_id) = callee.def_id().as_local() {
+                // Calling `optimized_mir` of a non-local definition cannot cycle.
+                involved.insert(callee_def_id);
             }
+            reaches_root = true;
         }
     }
 
-    cycle_found
+    reaches_root
 }
 
 #[instrument(level = "debug", skip(tcx), ret)]
@@ -166,7 +178,7 @@ pub(crate) fn mir_callgraph_cyclic<'tcx>(
         typing_env,
         root_instance,
         root,
-        &mut FxHashSet::default(),
+        &mut FxHashMap::default(),
         &mut involved,
         &mut FxHashMap::default(),
         recursion_limit,
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index cbb9bbfd12f..659ca4df159 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -119,14 +119,16 @@ impl<'a, 'tcx> CfgChecker<'a, 'tcx> {
     #[track_caller]
     fn fail(&self, location: Location, msg: impl AsRef<str>) {
         // We might see broken MIR when other errors have already occurred.
-        assert!(
-            self.tcx.dcx().has_errors().is_some(),
-            "broken MIR in {:?} ({}) at {:?}:\n{}",
-            self.body.source.instance,
-            self.when,
-            location,
-            msg.as_ref(),
-        );
+        if self.tcx.dcx().has_errors().is_none() {
+            span_bug!(
+                self.body.source_info(location).span,
+                "broken MIR in {:?} ({}) at {:?}:\n{}",
+                self.body.source.instance,
+                self.when,
+                location,
+                msg.as_ref(),
+            );
+        }
     }
 
     fn check_edge(&mut self, location: Location, bb: BasicBlock, edge_kind: EdgeKind) {
diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
index 098dc9dbaf0..650b85d99d2 100644
--- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
@@ -1219,10 +1219,8 @@ where
             // the type (even if after unification and processing nested goals
             // it does not hold) will disqualify the built-in auto impl.
             //
-            // This differs from the current stable behavior and fixes #84857.
-            // Due to breakage found via crater, we currently instead lint
-            // patterns which can be used to exploit this unsoundness on stable,
-            // see #93367 for more details.
+            // We've originally had a more permissive check here which resulted
+            // in unsoundness, see #84857.
             ty::Bool
             | ty::Char
             | ty::Int(_)
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 80c13e44d7d..9dd80bc9964 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -1624,6 +1624,10 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
                 self.check(def_id, item_visibility, effective_vis).generics().predicates();
 
                 for assoc_item in tcx.associated_items(id.owner_id).in_definition_order() {
+                    if assoc_item.is_impl_trait_in_trait() {
+                        continue;
+                    }
+
                     self.check_assoc_item(assoc_item, item_visibility, effective_vis);
 
                     if assoc_item.is_type() {
@@ -1736,6 +1740,10 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'_, 'tcx> {
                 check.ty().trait_ref();
 
                 for assoc_item in tcx.associated_items(id.owner_id).in_definition_order() {
+                    if assoc_item.is_impl_trait_in_trait() {
+                        continue;
+                    }
+
                     let impl_item_vis = if !of_trait {
                         min(tcx.local_visibility(assoc_item.def_id.expect_local()), impl_vis, tcx)
                     } else {
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index c3bfd759f4c..737577baa7a 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -49,7 +49,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         ns: Namespace,
         binding: NameBinding<'ra>,
     ) {
-        if let Err(old_binding) = self.try_define(parent, ident, ns, binding, false) {
+        let key = self.new_disambiguated_key(ident, ns);
+        if let Err(old_binding) = self.try_define(parent, key, binding, false) {
             self.report_conflict(parent, ident, ns, old_binding, binding);
         }
     }
@@ -441,18 +442,16 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
 
         self.r.indeterminate_imports.push(import);
         match import.kind {
+            // Don't add unresolved underscore imports to modules
+            ImportKind::Single { target: Ident { name: kw::Underscore, .. }, .. } => {}
             ImportKind::Single { target, type_ns_only, .. } => {
-                // Don't add underscore imports to `single_imports`
-                // because they cannot define any usable names.
-                if target.name != kw::Underscore {
-                    self.r.per_ns(|this, ns| {
-                        if !type_ns_only || ns == TypeNS {
-                            let key = BindingKey::new(target, ns);
-                            let mut resolution = this.resolution(current_module, key).borrow_mut();
-                            resolution.single_imports.insert(import);
-                        }
-                    });
-                }
+                self.r.per_ns(|this, ns| {
+                    if !type_ns_only || ns == TypeNS {
+                        let key = BindingKey::new(target, ns);
+                        let mut resolution = this.resolution(current_module, key).borrow_mut();
+                        resolution.single_imports.insert(import);
+                    }
+                });
             }
             // We don't add prelude imports to the globs since they only affect lexical scopes,
             // which are not relevant to import resolution.
@@ -1409,12 +1408,9 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
             let parent = self.parent_scope.module;
             let expansion = self.parent_scope.expansion;
             self.r.define(parent, ident, ns, self.res(def_id), vis, item.span, expansion);
-        } else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob)
-            && ident.name != kw::Underscore
-        {
-            // Don't add underscore names, they cannot be looked up anyway.
+        } else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob) {
             let impl_def_id = self.r.tcx.local_parent(local_def_id);
-            let key = BindingKey::new(ident, ns);
+            let key = BindingKey::new(ident.normalize_to_macros_2_0(), ns);
             self.r.impl_binding_keys.entry(impl_def_id).or_default().insert(key);
         }
 
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index b4c15ed1ca7..0a4c25b0eb0 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -25,7 +25,7 @@ use rustc_span::{Ident, Span, Symbol, kw, sym};
 use smallvec::SmallVec;
 use tracing::debug;
 
-use crate::Namespace::{self, *};
+use crate::Namespace::*;
 use crate::diagnostics::{DiagMode, Suggestion, import_candidates};
 use crate::errors::{
     CannotBeReexportedCratePublic, CannotBeReexportedCratePublicNS, CannotBeReexportedPrivate,
@@ -338,20 +338,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
     pub(crate) fn try_define(
         &mut self,
         module: Module<'ra>,
-        ident: Ident,
-        ns: Namespace,
+        key: BindingKey,
         binding: NameBinding<'ra>,
         warn_ambiguity: bool,
     ) -> Result<(), NameBinding<'ra>> {
         let res = binding.res();
-        self.check_reserved_macro_name(ident, res);
+        self.check_reserved_macro_name(key.ident, res);
         self.set_binding_parent_module(binding, module);
-        // Even if underscore names cannot be looked up, we still need to add them to modules,
-        // because they can be fetched by glob imports from those modules, and bring traits
-        // into scope both directly and through glob imports.
-        let key = BindingKey::new_disambiguated(ident, ns, || {
-            (module.0.0.lazy_resolutions.borrow().len() + 1).try_into().unwrap()
-        });
         self.update_resolution(module, key, warn_ambiguity, |this, resolution| {
             if let Some(old_binding) = resolution.best_binding() {
                 if res == Res::Err && old_binding.res() != Res::Err {
@@ -390,7 +383,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                     (old_glob @ true, false) | (old_glob @ false, true) => {
                         let (glob_binding, non_glob_binding) =
                             if old_glob { (old_binding, binding) } else { (binding, old_binding) };
-                        if ns == MacroNS
+                        if key.ns == MacroNS
                             && non_glob_binding.expansion != LocalExpnId::ROOT
                             && glob_binding.res() != non_glob_binding.res()
                         {
@@ -496,10 +489,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             };
             if self.is_accessible_from(binding.vis, scope) {
                 let imported_binding = self.import(binding, *import);
+                let key = BindingKey { ident, ..key };
                 let _ = self.try_define(
                     import.parent_scope.module,
-                    ident,
-                    key.ns,
+                    key,
                     imported_binding,
                     warn_ambiguity,
                 );
@@ -521,15 +514,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             let dummy_binding = self.dummy_binding;
             let dummy_binding = self.import(dummy_binding, import);
             self.per_ns(|this, ns| {
-                let module = import.parent_scope.module;
-                let _ = this.try_define(module, target, ns, dummy_binding, false);
-                // Don't remove underscores from `single_imports`, they were never added.
-                if target.name != kw::Underscore {
-                    let key = BindingKey::new(target, ns);
-                    this.update_resolution(module, key, false, |_, resolution| {
-                        resolution.single_imports.swap_remove(&import);
-                    })
-                }
+                let key = BindingKey::new(target, ns);
+                let _ = this.try_define(import.parent_scope.module, key, dummy_binding, false);
+                this.update_resolution(import.parent_scope.module, key, false, |_, resolution| {
+                    resolution.single_imports.swap_remove(&import);
+                })
             });
             self.record_use(target, dummy_binding, Used::Other);
         } else if import.imported_module.get().is_none() {
@@ -906,7 +895,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                         PendingBinding::Ready(Some(imported_binding))
                     }
                     Err(Determinacy::Determined) => {
-                        // Don't remove underscores from `single_imports`, they were never added.
+                        // Don't update the resolution for underscores, because it was never added.
                         if target.name != kw::Underscore {
                             let key = BindingKey::new(target, ns);
                             this.update_resolution(parent, key, false, |_, resolution| {
@@ -1521,8 +1510,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                     .is_some_and(|binding| binding.warn_ambiguity_recursive());
                 let _ = self.try_define(
                     import.parent_scope.module,
-                    key.ident,
-                    key.ns,
+                    key,
                     imported_binding,
                     warn_ambiguity,
                 );
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 93cec8daa5a..a3a770502de 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -2913,7 +2913,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                     self.r
                         .dcx()
                         .create_err(errors::UnderscoreLifetimeIsReserved { span: param.ident.span })
-                        .emit_unless(is_raw_underscore_lifetime);
+                        .emit_unless_delay(is_raw_underscore_lifetime);
                     // Record lifetime res, so lowering knows there is something fishy.
                     self.record_lifetime_param(param.id, LifetimeRes::Error);
                     continue;
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 948b67a3798..0d41a822e8a 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -532,26 +532,15 @@ struct BindingKey {
     /// identifier.
     ident: Ident,
     ns: Namespace,
-    /// When we add an underscore binding (with ident `_`) to some module, this field has
-    /// a non-zero value that uniquely identifies this binding in that module.
-    /// For non-underscore bindings this field is zero.
-    /// When a key is constructed for name lookup (as opposed to name definition), this field is
-    /// also zero, even for underscore names, so for underscores the lookup will never succeed.
+    /// 0 if ident is not `_`, otherwise a value that's unique to the specific
+    /// `_` in the expanded AST that introduced this binding.
     disambiguator: u32,
 }
 
 impl BindingKey {
     fn new(ident: Ident, ns: Namespace) -> Self {
-        BindingKey { ident: ident.normalize_to_macros_2_0(), ns, disambiguator: 0 }
-    }
-
-    fn new_disambiguated(
-        ident: Ident,
-        ns: Namespace,
-        disambiguator: impl FnOnce() -> u32,
-    ) -> BindingKey {
-        let disambiguator = if ident.name == kw::Underscore { disambiguator() } else { 0 };
-        BindingKey { ident: ident.normalize_to_macros_2_0(), ns, disambiguator }
+        let ident = ident.normalize_to_macros_2_0();
+        BindingKey { ident, ns, disambiguator: 0 }
     }
 }
 
@@ -1098,6 +1087,8 @@ pub struct Resolver<'ra, 'tcx> {
     extern_module_map: RefCell<FxIndexMap<DefId, Module<'ra>>>,
     binding_parent_modules: FxHashMap<NameBinding<'ra>, Module<'ra>>,
 
+    underscore_disambiguator: u32,
+
     /// Maps glob imports to the names of items actually imported.
     glob_map: FxIndexMap<LocalDefId, FxIndexSet<Symbol>>,
     glob_error: Option<ErrorGuaranteed>,
@@ -1509,6 +1500,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             extern_crate_map: Default::default(),
             module_children: Default::default(),
             trait_map: NodeMap::default(),
+            underscore_disambiguator: 0,
             empty_module,
             local_module_map,
             extern_module_map: Default::default(),
@@ -1889,6 +1881,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         import_ids
     }
 
+    fn new_disambiguated_key(&mut self, ident: Ident, ns: Namespace) -> BindingKey {
+        let ident = ident.normalize_to_macros_2_0();
+        let disambiguator = if ident.name == kw::Underscore {
+            self.underscore_disambiguator += 1;
+            self.underscore_disambiguator
+        } else {
+            0
+        };
+        BindingKey { ident, ns, disambiguator }
+    }
+
     fn resolutions(&mut self, module: Module<'ra>) -> &'ra Resolutions<'ra> {
         if module.populate_on_access.get() {
             module.populate_on_access.set(false);
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 0e8904a7dea..77ef7f56c09 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -530,7 +530,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
         target_trait.for_each_child(self, |this, ident, ns, _binding| {
             // FIXME: Adjust hygiene for idents from globs, like for glob imports.
             if let Some(overriding_keys) = this.impl_binding_keys.get(&impl_def_id)
-                && overriding_keys.contains(&BindingKey::new(ident, ns))
+                && overriding_keys.contains(&BindingKey::new(ident.normalize_to_macros_2_0(), ns))
             {
                 // The name is overridden, do not produce it from the glob delegation.
             } else {
diff --git a/compiler/rustc_target/src/spec/targets/amdgcn_amd_amdhsa.rs b/compiler/rustc_target/src/spec/targets/amdgcn_amd_amdhsa.rs
index f20782cabb8..0d6c6194e26 100644
--- a/compiler/rustc_target/src/spec/targets/amdgcn_amd_amdhsa.rs
+++ b/compiler/rustc_target/src/spec/targets/amdgcn_amd_amdhsa.rs
@@ -3,7 +3,7 @@ use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, Target, TargetMetadata,
 pub(crate) fn target() -> Target {
     Target {
         arch: "amdgpu".into(),
-        data_layout: "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9".into(),
+        data_layout: "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-p7:160:256:256:32-p8:128:128:128:48-p9:192:256:256:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5-G1-ni:7:8:9".into(),
         llvm_target: "amdgcn-amd-amdhsa".into(),
         metadata: TargetMetadata {
             description: Some("AMD GPU".into()),
diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs
index 17429e15cce..7426504e139 100644
--- a/compiler/rustc_trait_selection/src/solve/delegate.rs
+++ b/compiler/rustc_trait_selection/src/solve/delegate.rs
@@ -12,11 +12,11 @@ use rustc_infer::traits::solve::Goal;
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::solve::Certainty;
 use rustc_middle::ty::{
-    self, SizedTraitKind, Ty, TyCtxt, TypeFlags, TypeFoldable, TypeVisitableExt as _, TypingMode,
+    self, Ty, TyCtxt, TypeFlags, TypeFoldable, TypeVisitableExt as _, TypingMode,
 };
 use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
 
-use crate::traits::{EvaluateConstErr, ObligationCause, specialization_graph};
+use crate::traits::{EvaluateConstErr, ObligationCause, sizedness_fast_path, specialization_graph};
 
 #[repr(transparent)]
 pub struct SolverDelegate<'tcx>(InferCtxt<'tcx>);
@@ -76,19 +76,11 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
 
             if trait_pred.polarity() == ty::PredicatePolarity::Positive {
                 match self.0.tcx.as_lang_item(trait_pred.def_id()) {
-                    Some(LangItem::Sized)
-                        if self
-                            .resolve_vars_if_possible(trait_pred.self_ty().skip_binder())
-                            .has_trivial_sizedness(self.0.tcx, SizedTraitKind::Sized) =>
-                    {
-                        return Some(Certainty::Yes);
-                    }
-                    Some(LangItem::MetaSized)
-                        if self
-                            .resolve_vars_if_possible(trait_pred.self_ty().skip_binder())
-                            .has_trivial_sizedness(self.0.tcx, SizedTraitKind::MetaSized) =>
-                    {
-                        return Some(Certainty::Yes);
+                    Some(LangItem::Sized) | Some(LangItem::MetaSized) => {
+                        let predicate = self.resolve_vars_if_possible(goal.predicate);
+                        if sizedness_fast_path(self.tcx, predicate, goal.param_env) {
+                            return Some(Certainty::Yes);
+                        }
                     }
                     Some(LangItem::Copy | LangItem::Clone) => {
                         let self_ty =
diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs
index e35f89358e9..6b884b36080 100644
--- a/compiler/rustc_trait_selection/src/traits/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs
@@ -363,7 +363,7 @@ impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
 
         let infcx = self.selcx.infcx;
 
-        if sizedness_fast_path(infcx.tcx, obligation.predicate) {
+        if sizedness_fast_path(infcx.tcx, obligation.predicate, obligation.param_env) {
             return ProcessResult::Changed(thin_vec![]);
         }
 
diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
index 22eeb285b37..f24214145ba 100644
--- a/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
+++ b/compiler/rustc_trait_selection/src/traits/query/type_op/prove_predicate.rs
@@ -15,7 +15,7 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ProvePredicate<'tcx> {
         tcx: TyCtxt<'tcx>,
         key: &ParamEnvAnd<'tcx, Self>,
     ) -> Option<Self::QueryResponse> {
-        if sizedness_fast_path(tcx, key.value.predicate) {
+        if sizedness_fast_path(tcx, key.value.predicate, key.param_env) {
             return Some(());
         }
 
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 2b563c5b8d5..f90316f520b 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -597,7 +597,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             None => self.check_recursion_limit(&obligation, &obligation)?,
         }
 
-        if sizedness_fast_path(self.tcx(), obligation.predicate) {
+        if sizedness_fast_path(self.tcx(), obligation.predicate, obligation.param_env) {
             return Ok(EvaluatedToOk);
         }
 
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index 0c14b124e25..c3d60ec45c4 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -365,7 +365,11 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
     }
 }
 
-pub fn sizedness_fast_path<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tcx>) -> bool {
+pub fn sizedness_fast_path<'tcx>(
+    tcx: TyCtxt<'tcx>,
+    predicate: ty::Predicate<'tcx>,
+    param_env: ty::ParamEnv<'tcx>,
+) -> bool {
     // Proving `Sized`/`MetaSized`, very often on "obviously sized" types like
     // `&T`, accounts for about 60% percentage of the predicates we have to prove. No need to
     // canonicalize and all that for such cases.
@@ -390,6 +394,20 @@ pub fn sizedness_fast_path<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
             debug!("fast path -- trivial sizedness");
             return true;
         }
+
+        if matches!(trait_pred.self_ty().kind(), ty::Param(_) | ty::Placeholder(_)) {
+            for clause in param_env.caller_bounds() {
+                if let ty::ClauseKind::Trait(clause_pred) = clause.kind().skip_binder()
+                    && clause_pred.polarity == ty::PredicatePolarity::Positive
+                    && clause_pred.self_ty() == trait_pred.self_ty()
+                    && (clause_pred.def_id() == trait_pred.def_id()
+                        || (sizedness == SizedTraitKind::MetaSized
+                            && tcx.is_lang_item(clause_pred.def_id(), LangItem::Sized)))
+                {
+                    return true;
+                }
+            }
+        }
     }
 
     false
diff --git a/compiler/rustc_traits/src/evaluate_obligation.rs b/compiler/rustc_traits/src/evaluate_obligation.rs
index 7771db855d7..819b8e3231c 100644
--- a/compiler/rustc_traits/src/evaluate_obligation.rs
+++ b/compiler/rustc_traits/src/evaluate_obligation.rs
@@ -24,7 +24,7 @@ fn evaluate_obligation<'tcx>(
     debug!("evaluate_obligation: goal={:#?}", goal);
     let ParamEnvAnd { param_env, value: predicate } = goal;
 
-    if sizedness_fast_path(tcx, predicate) {
+    if sizedness_fast_path(tcx, predicate, param_env) {
         return Ok(EvaluationResult::EvaluatedToOk);
     }
 
diff --git a/library/core/src/any.rs b/library/core/src/any.rs
index 39cdf6efda0..38393379a78 100644
--- a/library/core/src/any.rs
+++ b/library/core/src/any.rs
@@ -783,7 +783,7 @@ impl TypeId {
 
         // This is a provenance-stripping memcpy.
         for (i, chunk) in self.data.iter().copied().enumerate() {
-            let chunk = chunk.expose_provenance().to_ne_bytes();
+            let chunk = chunk.addr().to_ne_bytes();
             let start = i * chunk.len();
             bytes[start..(start + chunk.len())].copy_from_slice(&chunk);
         }
diff --git a/library/core/src/async_iter/async_iter.rs b/library/core/src/async_iter/async_iter.rs
index 069c50c2531..c21c08320be 100644
--- a/library/core/src/async_iter/async_iter.rs
+++ b/library/core/src/async_iter/async_iter.rs
@@ -28,15 +28,15 @@ pub trait AsyncIterator {
     /// async iterator state:
     ///
     /// - `Poll::Pending` means that this async iterator's next value is not ready
-    /// yet. Implementations will ensure that the current task will be notified
-    /// when the next value may be ready.
+    ///   yet. Implementations will ensure that the current task will be notified
+    ///   when the next value may be ready.
     ///
     /// - `Poll::Ready(Some(val))` means that the async iterator has successfully
-    /// produced a value, `val`, and may produce further values on subsequent
-    /// `poll_next` calls.
+    ///   produced a value, `val`, and may produce further values on subsequent
+    ///   `poll_next` calls.
     ///
     /// - `Poll::Ready(None)` means that the async iterator has terminated, and
-    /// `poll_next` should not be invoked again.
+    ///   `poll_next` should not be invoked again.
     ///
     /// # Panics
     ///
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index 6419ae99113..1b9af10a6fd 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -1482,13 +1482,14 @@ pub trait PartialOrd<Rhs: PointeeSized = Self>: PartialEq<Rhs> + PointeeSized {
     }
 }
 
-fn default_chaining_impl<T: PointeeSized, U: PointeeSized>(
+fn default_chaining_impl<T, U>(
     lhs: &T,
     rhs: &U,
     p: impl FnOnce(Ordering) -> bool,
 ) -> ControlFlow<bool>
 where
-    T: PartialOrd<U>,
+    T: PartialOrd<U> + PointeeSized,
+    U: PointeeSized,
 {
     // It's important that this only call `partial_cmp` once, not call `eq` then
     // one of the relational operators.  We don't want to `bcmp`-then-`memcp` a
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index 228a331e1da..8ac29e5b076 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -854,7 +854,6 @@ impl Display for Arguments<'_> {
 /// }";
 /// assert_eq!(format!("The origin is: {origin:#?}"), expected);
 /// ```
-
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_on_unimplemented(
     on(
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index f90e6851d1f..106cc725fee 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -1379,6 +1379,7 @@ pub unsafe fn fmuladdf128(a: f128, b: f128, c: f128) -> f128;
 ///
 /// The stabilized version of this intrinsic is
 /// [`f16::floor`](../../std/primitive.f16.html#method.floor)
+#[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
 #[rustc_nounwind]
 pub const unsafe fn floorf16(x: f16) -> f16;
@@ -1386,6 +1387,7 @@ pub const unsafe fn floorf16(x: f16) -> f16;
 ///
 /// The stabilized version of this intrinsic is
 /// [`f32::floor`](../../std/primitive.f32.html#method.floor)
+#[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
 #[rustc_nounwind]
 pub const unsafe fn floorf32(x: f32) -> f32;
@@ -1393,6 +1395,7 @@ pub const unsafe fn floorf32(x: f32) -> f32;
 ///
 /// The stabilized version of this intrinsic is
 /// [`f64::floor`](../../std/primitive.f64.html#method.floor)
+#[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
 #[rustc_nounwind]
 pub const unsafe fn floorf64(x: f64) -> f64;
@@ -1400,6 +1403,7 @@ pub const unsafe fn floorf64(x: f64) -> f64;
 ///
 /// The stabilized version of this intrinsic is
 /// [`f128::floor`](../../std/primitive.f128.html#method.floor)
+#[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
 #[rustc_nounwind]
 pub const unsafe fn floorf128(x: f128) -> f128;
@@ -1408,6 +1412,7 @@ pub const unsafe fn floorf128(x: f128) -> f128;
 ///
 /// The stabilized version of this intrinsic is
 /// [`f16::ceil`](../../std/primitive.f16.html#method.ceil)
+#[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
 #[rustc_nounwind]
 pub const unsafe fn ceilf16(x: f16) -> f16;
@@ -1415,6 +1420,7 @@ pub const unsafe fn ceilf16(x: f16) -> f16;
 ///
 /// The stabilized version of this intrinsic is
 /// [`f32::ceil`](../../std/primitive.f32.html#method.ceil)
+#[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
 #[rustc_nounwind]
 pub const unsafe fn ceilf32(x: f32) -> f32;
@@ -1422,6 +1428,7 @@ pub const unsafe fn ceilf32(x: f32) -> f32;
 ///
 /// The stabilized version of this intrinsic is
 /// [`f64::ceil`](../../std/primitive.f64.html#method.ceil)
+#[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
 #[rustc_nounwind]
 pub const unsafe fn ceilf64(x: f64) -> f64;
@@ -1429,6 +1436,7 @@ pub const unsafe fn ceilf64(x: f64) -> f64;
 ///
 /// The stabilized version of this intrinsic is
 /// [`f128::ceil`](../../std/primitive.f128.html#method.ceil)
+#[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
 #[rustc_nounwind]
 pub const unsafe fn ceilf128(x: f128) -> f128;
@@ -1437,6 +1445,7 @@ pub const unsafe fn ceilf128(x: f128) -> f128;
 ///
 /// The stabilized version of this intrinsic is
 /// [`f16::trunc`](../../std/primitive.f16.html#method.trunc)
+#[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
 #[rustc_nounwind]
 pub const unsafe fn truncf16(x: f16) -> f16;
@@ -1444,6 +1453,7 @@ pub const unsafe fn truncf16(x: f16) -> f16;
 ///
 /// The stabilized version of this intrinsic is
 /// [`f32::trunc`](../../std/primitive.f32.html#method.trunc)
+#[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
 #[rustc_nounwind]
 pub const unsafe fn truncf32(x: f32) -> f32;
@@ -1451,6 +1461,7 @@ pub const unsafe fn truncf32(x: f32) -> f32;
 ///
 /// The stabilized version of this intrinsic is
 /// [`f64::trunc`](../../std/primitive.f64.html#method.trunc)
+#[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
 #[rustc_nounwind]
 pub const unsafe fn truncf64(x: f64) -> f64;
@@ -1458,6 +1469,7 @@ pub const unsafe fn truncf64(x: f64) -> f64;
 ///
 /// The stabilized version of this intrinsic is
 /// [`f128::trunc`](../../std/primitive.f128.html#method.trunc)
+#[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
 #[rustc_nounwind]
 pub const unsafe fn truncf128(x: f128) -> f128;
@@ -1467,6 +1479,7 @@ pub const unsafe fn truncf128(x: f128) -> f128;
 ///
 /// The stabilized version of this intrinsic is
 /// [`f16::round_ties_even`](../../std/primitive.f16.html#method.round_ties_even)
+#[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
 #[rustc_nounwind]
 pub const fn round_ties_even_f16(x: f16) -> f16;
@@ -1476,6 +1489,7 @@ pub const fn round_ties_even_f16(x: f16) -> f16;
 ///
 /// The stabilized version of this intrinsic is
 /// [`f32::round_ties_even`](../../std/primitive.f32.html#method.round_ties_even)
+#[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
 #[rustc_nounwind]
 pub const fn round_ties_even_f32(x: f32) -> f32;
@@ -1485,6 +1499,7 @@ pub const fn round_ties_even_f32(x: f32) -> f32;
 ///
 /// The stabilized version of this intrinsic is
 /// [`f64::round_ties_even`](../../std/primitive.f64.html#method.round_ties_even)
+#[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
 #[rustc_nounwind]
 pub const fn round_ties_even_f64(x: f64) -> f64;
@@ -1494,6 +1509,7 @@ pub const fn round_ties_even_f64(x: f64) -> f64;
 ///
 /// The stabilized version of this intrinsic is
 /// [`f128::round_ties_even`](../../std/primitive.f128.html#method.round_ties_even)
+#[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
 #[rustc_nounwind]
 pub const fn round_ties_even_f128(x: f128) -> f128;
@@ -1502,6 +1518,7 @@ pub const fn round_ties_even_f128(x: f128) -> f128;
 ///
 /// The stabilized version of this intrinsic is
 /// [`f16::round`](../../std/primitive.f16.html#method.round)
+#[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
 #[rustc_nounwind]
 pub const unsafe fn roundf16(x: f16) -> f16;
@@ -1509,6 +1526,7 @@ pub const unsafe fn roundf16(x: f16) -> f16;
 ///
 /// The stabilized version of this intrinsic is
 /// [`f32::round`](../../std/primitive.f32.html#method.round)
+#[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
 #[rustc_nounwind]
 pub const unsafe fn roundf32(x: f32) -> f32;
@@ -1516,6 +1534,7 @@ pub const unsafe fn roundf32(x: f32) -> f32;
 ///
 /// The stabilized version of this intrinsic is
 /// [`f64::round`](../../std/primitive.f64.html#method.round)
+#[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
 #[rustc_nounwind]
 pub const unsafe fn roundf64(x: f64) -> f64;
@@ -1523,6 +1542,7 @@ pub const unsafe fn roundf64(x: f64) -> f64;
 ///
 /// The stabilized version of this intrinsic is
 /// [`f128::round`](../../std/primitive.f128.html#method.round)
+#[rustc_intrinsic_const_stable_indirect]
 #[rustc_intrinsic]
 #[rustc_nounwind]
 pub const unsafe fn roundf128(x: f128) -> f128;
diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs
index 8090c98e7ed..c5e199c3082 100644
--- a/library/core/src/iter/adapters/zip.rs
+++ b/library/core/src/iter/adapters/zip.rs
@@ -18,7 +18,6 @@ pub struct Zip<A, B> {
     // index, len and a_len are only used by the specialized version of zip
     index: usize,
     len: usize,
-    a_len: usize,
 }
 impl<A: Iterator, B: Iterator> Zip<A, B> {
     pub(in crate::iter) fn new(a: A, b: B) -> Zip<A, B> {
@@ -158,7 +157,6 @@ macro_rules! zip_impl_general_defaults {
                 b,
                 index: 0, // unused
                 len: 0,   // unused
-                a_len: 0, // unused
             }
         }
 
@@ -299,9 +297,8 @@ where
     B: TrustedRandomAccess + Iterator,
 {
     fn new(a: A, b: B) -> Self {
-        let a_len = a.size();
-        let len = cmp::min(a_len, b.size());
-        Zip { a, b, index: 0, len, a_len }
+        let len = cmp::min(a.size(), b.size());
+        Zip { a, b, index: 0, len }
     }
 
     #[inline]
@@ -315,17 +312,6 @@ where
             unsafe {
                 Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i)))
             }
-        } else if A::MAY_HAVE_SIDE_EFFECT && self.index < self.a_len {
-            let i = self.index;
-            // as above, increment before executing code that may panic
-            self.index += 1;
-            self.len += 1;
-            // match the base implementation's potential side effects
-            // SAFETY: we just checked that `i` < `self.a.len()`
-            unsafe {
-                self.a.__iterator_get_unchecked(i);
-            }
-            None
         } else {
             None
         }
@@ -371,36 +357,42 @@ where
         A: DoubleEndedIterator + ExactSizeIterator,
         B: DoubleEndedIterator + ExactSizeIterator,
     {
-        if A::MAY_HAVE_SIDE_EFFECT || B::MAY_HAVE_SIDE_EFFECT {
-            let sz_a = self.a.size();
-            let sz_b = self.b.size();
-            // Adjust a, b to equal length, make sure that only the first call
-            // of `next_back` does this, otherwise we will break the restriction
-            // on calls to `self.next_back()` after calling `get_unchecked()`.
-            if sz_a != sz_b {
+        // No effects when the iterator is exhausted, to reduce the number of
+        // cases the unsafe code has to handle.
+        // See #137255 for a case where where too many epicycles lead to unsoundness.
+        if self.index < self.len {
+            let old_len = self.len;
+
+            // since get_unchecked and the side-effecting code can execute user code
+            // which can panic we decrement the counter beforehand
+            // so that the same index won't be accessed twice, as required by TrustedRandomAccess.
+            // Additionally this will ensure that the side-effects code won't run a second time.
+            self.len -= 1;
+
+            // Adjust a, b to equal length if we're iterating backwards.
+            if A::MAY_HAVE_SIDE_EFFECT || B::MAY_HAVE_SIDE_EFFECT {
+                // note if some forward-iteration already happened then these aren't the real
+                // remaining lengths of the inner iterators, so we have to relate them to
+                // Zip's internal length-tracking.
                 let sz_a = self.a.size();
-                if A::MAY_HAVE_SIDE_EFFECT && sz_a > self.len {
-                    for _ in 0..sz_a - self.len {
-                        // since next_back() may panic we increment the counters beforehand
-                        // to keep Zip's state in sync with the underlying iterator source
-                        self.a_len -= 1;
-                        self.a.next_back();
-                    }
-                    debug_assert_eq!(self.a_len, self.len);
-                }
                 let sz_b = self.b.size();
-                if B::MAY_HAVE_SIDE_EFFECT && sz_b > self.len {
-                    for _ in 0..sz_b - self.len {
-                        self.b.next_back();
+                // This condition can and must only be true on the first `next_back` call,
+                // otherwise we will break the restriction on calls to `self.next_back()`
+                // after calling `get_unchecked()`.
+                if sz_a != sz_b && (old_len == sz_a || old_len == sz_b) {
+                    if A::MAY_HAVE_SIDE_EFFECT && sz_a > old_len {
+                        for _ in 0..sz_a - old_len {
+                            self.a.next_back();
+                        }
                     }
+                    if B::MAY_HAVE_SIDE_EFFECT && sz_b > old_len {
+                        for _ in 0..sz_b - old_len {
+                            self.b.next_back();
+                        }
+                    }
+                    debug_assert_eq!(self.a.size(), self.b.size());
                 }
             }
-        }
-        if self.index < self.len {
-            // since get_unchecked executes code which can panic we increment the counters beforehand
-            // so that the same index won't be accessed twice, as required by TrustedRandomAccess
-            self.len -= 1;
-            self.a_len -= 1;
             let i = self.len;
             // SAFETY: `i` is smaller than the previous value of `self.len`,
             // which is also smaller than or equal to `self.a.len()` and `self.b.len()`
diff --git a/library/core/src/iter/traits/collect.rs b/library/core/src/iter/traits/collect.rs
index 3bc9cff8072..ab276500679 100644
--- a/library/core/src/iter/traits/collect.rs
+++ b/library/core/src/iter/traits/collect.rs
@@ -436,7 +436,6 @@ pub trait Extend<A> {
     /// **For implementors:** For a collection to unsafely rely on this method's safety precondition (that is,
     /// invoke UB if they are violated), it must implement `extend_reserve` correctly. In other words,
     /// callers may assume that if they `extend_reserve`ed enough space they can call this method.
-
     // This method is for internal usage only. It is only on the trait because of specialization's limitations.
     #[unstable(feature = "extend_one_unchecked", issue = "none")]
     #[doc(hidden)]
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index f296792b1dc..10f9d464f7d 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -3414,10 +3414,10 @@ pub trait Iterator {
     /// ```
     #[stable(feature = "iter_copied", since = "1.36.0")]
     #[rustc_diagnostic_item = "iter_copied"]
-    fn copied<'a, T: 'a>(self) -> Copied<Self>
+    fn copied<'a, T>(self) -> Copied<Self>
     where
+        T: Copy + 'a,
         Self: Sized + Iterator<Item = &'a T>,
-        T: Copy,
     {
         Copied::new(self)
     }
@@ -3462,10 +3462,10 @@ pub trait Iterator {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_diagnostic_item = "iter_cloned"]
-    fn cloned<'a, T: 'a>(self) -> Cloned<Self>
+    fn cloned<'a, T>(self) -> Cloned<Self>
     where
+        T: Clone + 'a,
         Self: Sized + Iterator<Item = &'a T>,
-        T: Clone,
     {
         Cloned::new(self)
     }
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 729de5ffc8f..3c33f4b1368 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -39,9 +39,9 @@
 //!   return. You should mark your implementation using `#[panic_handler]`.
 //!
 //! * `rust_eh_personality` - is used by the failure mechanisms of the
-//!    compiler. This is often mapped to GCC's personality function, but crates
-//!    which do not trigger a panic can be assured that this function is never
-//!    called. The `lang` attribute is called `eh_personality`.
+//!   compiler. This is often mapped to GCC's personality function, but crates
+//!   which do not trigger a panic can be assured that this function is never
+//!   called. The `lang` attribute is called `eh_personality`.
 
 #![stable(feature = "core", since = "1.6.0")]
 #![doc(
diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs
index fc35e54bb0d..34d8370da7e 100644
--- a/library/core/src/mem/maybe_uninit.rs
+++ b/library/core/src/mem/maybe_uninit.rs
@@ -1005,28 +1005,6 @@ impl<T> MaybeUninit<T> {
         }
     }
 
-    /// Deprecated version of [`slice::assume_init_ref`].
-    #[unstable(feature = "maybe_uninit_slice", issue = "63569")]
-    #[deprecated(
-        note = "replaced by inherent assume_init_ref method; will eventually be removed",
-        since = "1.83.0"
-    )]
-    pub const unsafe fn slice_assume_init_ref(slice: &[Self]) -> &[T] {
-        // SAFETY: Same for both methods.
-        unsafe { slice.assume_init_ref() }
-    }
-
-    /// Deprecated version of [`slice::assume_init_mut`].
-    #[unstable(feature = "maybe_uninit_slice", issue = "63569")]
-    #[deprecated(
-        note = "replaced by inherent assume_init_mut method; will eventually be removed",
-        since = "1.83.0"
-    )]
-    pub const unsafe fn slice_assume_init_mut(slice: &mut [Self]) -> &mut [T] {
-        // SAFETY: Same for both methods.
-        unsafe { slice.assume_init_mut() }
-    }
-
     /// Gets a pointer to the first element of the array.
     #[unstable(feature = "maybe_uninit_slice", issue = "63569")]
     #[inline(always)]
@@ -1040,94 +1018,6 @@ impl<T> MaybeUninit<T> {
     pub const fn slice_as_mut_ptr(this: &mut [MaybeUninit<T>]) -> *mut T {
         this.as_mut_ptr() as *mut T
     }
-
-    /// Deprecated version of [`slice::write_copy_of_slice`].
-    #[unstable(feature = "maybe_uninit_write_slice", issue = "79995")]
-    #[deprecated(
-        note = "replaced by inherent write_copy_of_slice method; will eventually be removed",
-        since = "1.83.0"
-    )]
-    pub fn copy_from_slice<'a>(this: &'a mut [MaybeUninit<T>], src: &[T]) -> &'a mut [T]
-    where
-        T: Copy,
-    {
-        this.write_copy_of_slice(src)
-    }
-
-    /// Deprecated version of [`slice::write_clone_of_slice`].
-    #[unstable(feature = "maybe_uninit_write_slice", issue = "79995")]
-    #[deprecated(
-        note = "replaced by inherent write_clone_of_slice method; will eventually be removed",
-        since = "1.83.0"
-    )]
-    pub fn clone_from_slice<'a>(this: &'a mut [MaybeUninit<T>], src: &[T]) -> &'a mut [T]
-    where
-        T: Clone,
-    {
-        this.write_clone_of_slice(src)
-    }
-
-    /// Deprecated version of [`slice::write_filled`].
-    #[unstable(feature = "maybe_uninit_fill", issue = "117428")]
-    #[deprecated(
-        note = "replaced by inherent write_filled method; will eventually be removed",
-        since = "1.83.0"
-    )]
-    pub fn fill<'a>(this: &'a mut [MaybeUninit<T>], value: T) -> &'a mut [T]
-    where
-        T: Clone,
-    {
-        this.write_filled(value)
-    }
-
-    /// Deprecated version of [`slice::write_with`].
-    #[unstable(feature = "maybe_uninit_fill", issue = "117428")]
-    #[deprecated(
-        note = "replaced by inherent write_with method; will eventually be removed",
-        since = "1.83.0"
-    )]
-    pub fn fill_with<'a, F>(this: &'a mut [MaybeUninit<T>], mut f: F) -> &'a mut [T]
-    where
-        F: FnMut() -> T,
-    {
-        this.write_with(|_| f())
-    }
-
-    /// Deprecated version of [`slice::write_iter`].
-    #[unstable(feature = "maybe_uninit_fill", issue = "117428")]
-    #[deprecated(
-        note = "replaced by inherent write_iter method; will eventually be removed",
-        since = "1.83.0"
-    )]
-    pub fn fill_from<'a, I>(
-        this: &'a mut [MaybeUninit<T>],
-        it: I,
-    ) -> (&'a mut [T], &'a mut [MaybeUninit<T>])
-    where
-        I: IntoIterator<Item = T>,
-    {
-        this.write_iter(it)
-    }
-
-    /// Deprecated version of [`slice::as_bytes`].
-    #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
-    #[deprecated(
-        note = "replaced by inherent as_bytes method; will eventually be removed",
-        since = "1.83.0"
-    )]
-    pub fn slice_as_bytes(this: &[MaybeUninit<T>]) -> &[MaybeUninit<u8>] {
-        this.as_bytes()
-    }
-
-    /// Deprecated version of [`slice::as_bytes_mut`].
-    #[unstable(feature = "maybe_uninit_as_bytes", issue = "93092")]
-    #[deprecated(
-        note = "replaced by inherent as_bytes_mut method; will eventually be removed",
-        since = "1.83.0"
-    )]
-    pub fn slice_as_bytes_mut(this: &mut [MaybeUninit<T>]) -> &mut [MaybeUninit<u8>] {
-        this.as_bytes_mut()
-    }
 }
 
 impl<T> [MaybeUninit<T>] {
@@ -1304,7 +1194,7 @@ impl<T> [MaybeUninit<T>] {
     /// Fills a slice with elements returned by calling a closure for each index.
     ///
     /// This method uses a closure to create new values. If you'd rather `Clone` a given value, use
-    /// [`MaybeUninit::fill`]. If you want to use the `Default` trait to generate values, you can
+    /// [slice::write_filled]. If you want to use the `Default` trait to generate values, you can
     /// pass [`|_| Default::default()`][Default::default] as the argument.
     ///
     /// # Panics
@@ -1463,7 +1353,7 @@ impl<T> [MaybeUninit<T>] {
     /// use std::mem::MaybeUninit;
     ///
     /// let mut uninit = [MaybeUninit::<u16>::uninit(), MaybeUninit::<u16>::uninit()];
-    /// let uninit_bytes = MaybeUninit::slice_as_bytes_mut(&mut uninit);
+    /// let uninit_bytes = uninit.as_bytes_mut();
     /// uninit_bytes.write_copy_of_slice(&[0x12, 0x34, 0x56, 0x78]);
     /// let vals = unsafe { uninit.assume_init_ref() };
     /// if cfg!(target_endian = "little") {
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 1bd12d818cf..2198d098c4b 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -36,7 +36,7 @@ pub use crate::intrinsics::transmute;
 /// * If you want to leak memory, see [`Box::leak`].
 /// * If you want to obtain a raw pointer to the memory, see [`Box::into_raw`].
 /// * If you want to dispose of a value properly, running its destructor, see
-/// [`mem::drop`].
+///   [`mem::drop`].
 ///
 /// # Safety
 ///
diff --git a/library/core/src/net/ip_addr.rs b/library/core/src/net/ip_addr.rs
index aaa68e8d7d1..49a7ae5de5c 100644
--- a/library/core/src/net/ip_addr.rs
+++ b/library/core/src/net/ip_addr.rs
@@ -787,7 +787,6 @@ impl Ipv4Addr {
     /// [IANA IPv4 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
     /// [unspecified address]: Ipv4Addr::UNSPECIFIED
     /// [broadcast address]: Ipv4Addr::BROADCAST
-
     ///
     /// # Examples
     ///
diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs
index 4c09c930c79..69e6c100e76 100644
--- a/library/core/src/num/f128.rs
+++ b/library/core/src/num/f128.rs
@@ -1448,7 +1448,6 @@ impl f128 {
     #[rustc_allow_incoherent_impl]
     #[unstable(feature = "f128", issue = "116909")]
     #[rustc_const_unstable(feature = "f128", issue = "116909")]
-    // #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub const fn floor(self) -> f128 {
         // SAFETY: intrinsic with no preconditions
@@ -1478,7 +1477,6 @@ impl f128 {
     #[rustc_allow_incoherent_impl]
     #[unstable(feature = "f128", issue = "116909")]
     #[rustc_const_unstable(feature = "f128", issue = "116909")]
-    // #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub const fn ceil(self) -> f128 {
         // SAFETY: intrinsic with no preconditions
@@ -1514,7 +1512,6 @@ impl f128 {
     #[rustc_allow_incoherent_impl]
     #[unstable(feature = "f128", issue = "116909")]
     #[rustc_const_unstable(feature = "f128", issue = "116909")]
-    // #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub const fn round(self) -> f128 {
         // SAFETY: intrinsic with no preconditions
@@ -1548,7 +1545,6 @@ impl f128 {
     #[rustc_allow_incoherent_impl]
     #[unstable(feature = "f128", issue = "116909")]
     #[rustc_const_unstable(feature = "f128", issue = "116909")]
-    // #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub const fn round_ties_even(self) -> f128 {
         intrinsics::round_ties_even_f128(self)
@@ -1580,7 +1576,6 @@ impl f128 {
     #[rustc_allow_incoherent_impl]
     #[unstable(feature = "f128", issue = "116909")]
     #[rustc_const_unstable(feature = "f128", issue = "116909")]
-    // #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub const fn trunc(self) -> f128 {
         // SAFETY: intrinsic with no preconditions
@@ -1611,7 +1606,6 @@ impl f128 {
     #[rustc_allow_incoherent_impl]
     #[unstable(feature = "f128", issue = "116909")]
     #[rustc_const_unstable(feature = "f128", issue = "116909")]
-    // #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub const fn fract(self) -> f128 {
         self - self.trunc()
diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs
index 1d98a485c4f..b66cef03d20 100644
--- a/library/core/src/num/f16.rs
+++ b/library/core/src/num/f16.rs
@@ -1424,7 +1424,6 @@ impl f16 {
     #[rustc_allow_incoherent_impl]
     #[unstable(feature = "f16", issue = "116909")]
     #[rustc_const_unstable(feature = "f16", issue = "116909")]
-    // #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub const fn floor(self) -> f16 {
         // SAFETY: intrinsic with no preconditions
@@ -1454,7 +1453,6 @@ impl f16 {
     #[rustc_allow_incoherent_impl]
     #[unstable(feature = "f16", issue = "116909")]
     #[rustc_const_unstable(feature = "f16", issue = "116909")]
-    // #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub const fn ceil(self) -> f16 {
         // SAFETY: intrinsic with no preconditions
@@ -1490,7 +1488,6 @@ impl f16 {
     #[rustc_allow_incoherent_impl]
     #[unstable(feature = "f16", issue = "116909")]
     #[rustc_const_unstable(feature = "f16", issue = "116909")]
-    // #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub const fn round(self) -> f16 {
         // SAFETY: intrinsic with no preconditions
@@ -1524,7 +1521,6 @@ impl f16 {
     #[rustc_allow_incoherent_impl]
     #[unstable(feature = "f16", issue = "116909")]
     #[rustc_const_unstable(feature = "f16", issue = "116909")]
-    // #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub const fn round_ties_even(self) -> f16 {
         intrinsics::round_ties_even_f16(self)
@@ -1556,7 +1552,6 @@ impl f16 {
     #[rustc_allow_incoherent_impl]
     #[unstable(feature = "f16", issue = "116909")]
     #[rustc_const_unstable(feature = "f16", issue = "116909")]
-    // #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub const fn trunc(self) -> f16 {
         // SAFETY: intrinsic with no preconditions
@@ -1587,7 +1582,6 @@ impl f16 {
     #[rustc_allow_incoherent_impl]
     #[unstable(feature = "f16", issue = "116909")]
     #[rustc_const_unstable(feature = "f16", issue = "116909")]
-    // #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub const fn fract(self) -> f16 {
         self - self.trunc()
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index b460c7d0205..f8344da79ad 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -1591,7 +1591,6 @@ pub mod math {
     /// [`f32::floor`]: ../../../std/primitive.f32.html#method.floor
     #[inline]
     #[unstable(feature = "core_float_math", issue = "137578")]
-    #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub const fn floor(x: f32) -> f32 {
         // SAFETY: intrinsic with no preconditions
@@ -1622,7 +1621,6 @@ pub mod math {
     #[doc(alias = "ceiling")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[unstable(feature = "core_float_math", issue = "137578")]
-    #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
     pub const fn ceil(x: f32) -> f32 {
         // SAFETY: intrinsic with no preconditions
         unsafe { intrinsics::ceilf32(x) }
@@ -1657,7 +1655,6 @@ pub mod math {
     #[inline]
     #[unstable(feature = "core_float_math", issue = "137578")]
     #[must_use = "method returns a new number and does not mutate the original value"]
-    #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
     pub const fn round(x: f32) -> f32 {
         // SAFETY: intrinsic with no preconditions
         unsafe { intrinsics::roundf32(x) }
@@ -1691,7 +1688,6 @@ pub mod math {
     #[inline]
     #[unstable(feature = "core_float_math", issue = "137578")]
     #[must_use = "method returns a new number and does not mutate the original value"]
-    #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
     pub const fn round_ties_even(x: f32) -> f32 {
         intrinsics::round_ties_even_f32(x)
     }
@@ -1722,7 +1718,6 @@ pub mod math {
     #[doc(alias = "truncate")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[unstable(feature = "core_float_math", issue = "137578")]
-    #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
     pub const fn trunc(x: f32) -> f32 {
         // SAFETY: intrinsic with no preconditions
         unsafe { intrinsics::truncf32(x) }
@@ -1752,7 +1747,6 @@ pub mod math {
     /// [`f32::fract`]: ../../../std/primitive.f32.html#method.fract
     #[inline]
     #[unstable(feature = "core_float_math", issue = "137578")]
-    #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub const fn fract(x: f32) -> f32 {
         x - trunc(x)
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index 3cd079b84eb..93da63c896e 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -1589,7 +1589,6 @@ pub mod math {
     /// [`f64::floor`]: ../../../std/primitive.f64.html#method.floor
     #[inline]
     #[unstable(feature = "core_float_math", issue = "137578")]
-    #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub const fn floor(x: f64) -> f64 {
         // SAFETY: intrinsic with no preconditions
@@ -1619,7 +1618,6 @@ pub mod math {
     #[inline]
     #[doc(alias = "ceiling")]
     #[unstable(feature = "core_float_math", issue = "137578")]
-    #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub const fn ceil(x: f64) -> f64 {
         // SAFETY: intrinsic with no preconditions
@@ -1654,7 +1652,6 @@ pub mod math {
     /// [`f64::round`]: ../../../std/primitive.f64.html#method.round
     #[inline]
     #[unstable(feature = "core_float_math", issue = "137578")]
-    #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub const fn round(x: f64) -> f64 {
         // SAFETY: intrinsic with no preconditions
@@ -1688,7 +1685,6 @@ pub mod math {
     /// [`f64::round_ties_even`]: ../../../std/primitive.f64.html#method.round_ties_even
     #[inline]
     #[unstable(feature = "core_float_math", issue = "137578")]
-    #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub const fn round_ties_even(x: f64) -> f64 {
         intrinsics::round_ties_even_f64(x)
@@ -1719,7 +1715,6 @@ pub mod math {
     #[inline]
     #[doc(alias = "truncate")]
     #[unstable(feature = "core_float_math", issue = "137578")]
-    #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub const fn trunc(x: f64) -> f64 {
         // SAFETY: intrinsic with no preconditions
@@ -1750,7 +1745,6 @@ pub mod math {
     /// [`f64::fract`]: ../../../std/primitive.f64.html#method.fract
     #[inline]
     #[unstable(feature = "core_float_math", issue = "137578")]
-    #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
     #[must_use = "method returns a new number and does not mutate the original value"]
     pub const fn fract(x: f64) -> f64 {
         x - trunc(x)
diff --git a/library/core/src/num/int_log10.rs b/library/core/src/num/int_log10.rs
index 28a3f5d880a..649a736b6e7 100644
--- a/library/core/src/num/int_log10.rs
+++ b/library/core/src/num/int_log10.rs
@@ -1,5 +1,5 @@
-/// These functions compute the integer logarithm of their type, assuming
-/// that someone has already checked that the value is strictly positive.
+//! These functions compute the integer logarithm of their type, assuming
+//! that someone has already checked that the value is strictly positive.
 
 // 0 < val <= u8::MAX
 #[inline]
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index ab6823249c3..584cd60fbe5 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -556,7 +556,7 @@ macro_rules! uint_impl {
         pub const fn strict_add(self, rhs: Self) -> Self {
             let (a, b) = self.overflowing_add(rhs);
             if b { overflow_panic::add() } else { a }
-         }
+        }
 
         /// Unchecked integer addition. Computes `self + rhs`, assuming overflow
         /// cannot occur.
@@ -653,7 +653,7 @@ macro_rules! uint_impl {
         pub const fn strict_add_signed(self, rhs: $SignedT) -> Self {
             let (a, b) = self.overflowing_add_signed(rhs);
             if b { overflow_panic::add() } else { a }
-         }
+        }
 
         /// Checked integer subtraction. Computes `self - rhs`, returning
         /// `None` if overflow occurred.
@@ -713,7 +713,7 @@ macro_rules! uint_impl {
         pub const fn strict_sub(self, rhs: Self) -> Self {
             let (a, b) = self.overflowing_sub(rhs);
             if b { overflow_panic::sub() } else { a }
-         }
+        }
 
         /// Unchecked integer subtraction. Computes `self - rhs`, assuming overflow
         /// cannot occur.
@@ -805,6 +805,43 @@ macro_rules! uint_impl {
             }
         }
 
+        /// Strict subtraction with a signed integer. Computes `self - rhs`,
+        /// panicking if overflow occurred.
+        ///
+        /// # Panics
+        ///
+        /// ## Overflow behavior
+        ///
+        /// This function will always panic on overflow, regardless of whether overflow checks are enabled.
+        ///
+        /// # Examples
+        ///
+        /// ```
+        /// #![feature(strict_overflow_ops)]
+        #[doc = concat!("assert_eq!(3", stringify!($SelfT), ".strict_sub_signed(2), 1);")]
+        /// ```
+        ///
+        /// The following panic because of overflow:
+        ///
+        /// ```should_panic
+        /// #![feature(strict_overflow_ops)]
+        #[doc = concat!("let _ = 1", stringify!($SelfT), ".strict_sub_signed(2);")]
+        /// ```
+        ///
+        /// ```should_panic
+        /// #![feature(strict_overflow_ops)]
+        #[doc = concat!("let _ = (", stringify!($SelfT), "::MAX).strict_sub_signed(-1);")]
+        /// ```
+        #[unstable(feature = "strict_overflow_ops", issue = "118260")]
+        #[must_use = "this returns the result of the operation, \
+                      without modifying the original"]
+        #[inline]
+        #[track_caller]
+        pub const fn strict_sub_signed(self, rhs: $SignedT) -> Self {
+            let (a, b) = self.overflowing_sub_signed(rhs);
+            if b { overflow_panic::sub() } else { a }
+        }
+
         #[doc = concat!(
             "Checked integer subtraction. Computes `self - rhs` and checks if the result fits into an [`",
             stringify!($SignedT), "`], returning `None` if overflow occurred."
@@ -913,7 +950,7 @@ macro_rules! uint_impl {
         pub const fn strict_mul(self, rhs: Self) -> Self {
             let (a, b) = self.overflowing_mul(rhs);
             if b { overflow_panic::mul() } else { a }
-         }
+        }
 
         /// Unchecked integer multiplication. Computes `self * rhs`, assuming overflow
         /// cannot occur.
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 5bd80149a1d..9a1ba7d1728 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -1363,7 +1363,6 @@ mod prim_f16 {}
 /// x = a + b + c + d; // As written
 /// x = (a + c) + (b + d); // Reordered to shorten critical path and enable vectorization
 /// ```
-
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_f32 {}
 
diff --git a/library/core/src/ptr/docs/as_uninit_slice.md b/library/core/src/ptr/docs/as_uninit_slice.md
index c80c0405883..1113f4748c2 100644
--- a/library/core/src/ptr/docs/as_uninit_slice.md
+++ b/library/core/src/ptr/docs/as_uninit_slice.md
@@ -10,24 +10,24 @@ When calling this method, you have to ensure that *either* the pointer is null *
 all of the following is true:
 
 * The pointer must be [valid] for reads for `ptr.len() * size_of::<T>()` many bytes,
-and it must be properly aligned. This means in particular:
+  and it must be properly aligned. This means in particular:
 
 * The entire memory range of this slice must be contained within a single [allocation]!
-Slices can never span across multiple allocations.
+  Slices can never span across multiple allocations.
 
 * The pointer must be aligned even for zero-length slices. One
-reason for this is that enum layout optimizations may rely on references
-(including slices of any length) being aligned and non-null to distinguish
-them from other data. You can obtain a pointer that is usable as `data`
-for zero-length slices using [`NonNull::dangling()`].
+  reason for this is that enum layout optimizations may rely on references
+  (including slices of any length) being aligned and non-null to distinguish
+  them from other data. You can obtain a pointer that is usable as `data`
+  for zero-length slices using [`NonNull::dangling()`].
 
 * The total size `ptr.len() * size_of::<T>()` of the slice must be no larger than `isize::MAX`.
-See the safety documentation of [`pointer::offset`].
+  See the safety documentation of [`pointer::offset`].
 
 * You must enforce Rust's aliasing rules, since the returned lifetime `'a` is
-arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
-In particular, while this reference exists, the memory the pointer points to must
-not get mutated (except inside `UnsafeCell`).
+  arbitrarily chosen and does not necessarily reflect the actual lifetime of the data.
+  In particular, while this reference exists, the memory the pointer points to must
+  not get mutated (except inside `UnsafeCell`).
 
 This applies even if the result of this method is unused!
 
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index fe8c6f83034..dbe3999b4a4 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -28,7 +28,8 @@
 //!   undefined behavior to perform two concurrent accesses to the same location from different
 //!   threads unless both accesses only read from memory. Notice that this explicitly
 //!   includes [`read_volatile`] and [`write_volatile`]: Volatile accesses cannot
-//!   be used for inter-thread synchronization.
+//!   be used for inter-thread synchronization, regardless of whether they are acting on
+//!   Rust memory or not.
 //! * The result of casting a reference to a pointer is valid for as long as the
 //!   underlying allocation is live and no reference (just raw pointers) is used to
 //!   access the same memory. That is, reference and pointer accesses cannot be
@@ -114,6 +115,10 @@
 //! fully contiguous (i.e., has no "holes"), there is no guarantee that this
 //! will not change in the future.
 //!
+//! Allocations must behave like "normal" memory: in particular, reads must not have
+//! side-effects, and writes must become visible to other threads using the usual synchronization
+//! primitives.
+//!
 //! For any allocation with `base` address, `size`, and a set of
 //! `addresses`, the following are guaranteed:
 //! - For all addresses `a` in `addresses`, `a` is in the range `base .. (base +
@@ -2021,54 +2026,61 @@ pub const unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
     }
 }
 
-/// Performs a volatile read of the value from `src` without moving it. This
-/// leaves the memory in `src` unchanged.
-///
-/// Volatile operations are intended to act on I/O memory, and are guaranteed
-/// to not be elided or reordered by the compiler across other volatile
-/// operations.
-///
-/// # Notes
-///
-/// Rust does not currently have a rigorously and formally defined memory model,
-/// so the precise semantics of what "volatile" means here is subject to change
-/// over time. That being said, the semantics will almost always end up pretty
-/// similar to [C11's definition of volatile][c11].
-///
-/// The compiler shouldn't change the relative order or number of volatile
-/// memory operations. However, volatile memory operations on zero-sized types
-/// (e.g., if a zero-sized type is passed to `read_volatile`) are noops
-/// and may be ignored.
-///
-/// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
+/// Performs a volatile read of the value from `src` without moving it.
+///
+/// Volatile operations are intended to act on I/O memory. As such, they are considered externally
+/// observable events (just like syscalls, but less opaque), and are guaranteed to not be elided or
+/// reordered by the compiler across other externally observable events. With this in mind, there
+/// are two cases of usage that need to be distinguished:
+///
+/// - When a volatile operation is used for memory inside an [allocation], it behaves exactly like
+///   [`read`], except for the additional guarantee that it won't be elided or reordered (see
+///   above). This implies that the operation will actually access memory and not e.g. be lowered to
+///   reusing data from a previous read. Other than that, all the usual rules for memory accesses
+///   apply (including provenance).  In particular, just like in C, whether an operation is volatile
+///   has no bearing whatsoever on questions involving concurrent accesses from multiple threads.
+///   Volatile accesses behave exactly like non-atomic accesses in that regard.
+///
+/// - Volatile operations, however, may also be used to access memory that is _outside_ of any Rust
+///   allocation. In this use-case, the pointer does *not* have to be [valid] for reads. This is
+///   typically used for CPU and peripheral registers that must be accessed via an I/O memory
+///   mapping, most commonly at fixed addresses reserved by the hardware. These often have special
+///   semantics associated to their manipulation, and cannot be used as general purpose memory.
+///   Here, any address value is possible, including 0 and [`usize::MAX`], so long as the semantics
+///   of such a read are well-defined by the target hardware. The provenance of the pointer is
+///   irrelevant, and it can be created with [`without_provenance`]. The access must not trap. It
+///   can cause side-effects, but those must not affect Rust-allocated memory in any way. This
+///   access is still not considered [atomic], and as such it cannot be used for inter-thread
+///   synchronization.
+///
+/// Note that volatile memory operations where T is a zero-sized type are noops and may be ignored.
+///
+/// [allocation]: crate::ptr#allocated-object
+/// [atomic]: crate::sync::atomic#memory-model-for-atomic-accesses
 ///
 /// # Safety
 ///
+/// Like [`read`], `read_volatile` creates a bitwise copy of `T`, regardless of whether `T` is
+/// [`Copy`]. If `T` is not [`Copy`], using both the returned value and the value at `*src` can
+/// [violate memory safety][read-ownership]. However, storing non-[`Copy`] types in volatile memory
+/// is almost certainly incorrect.
+///
 /// Behavior is undefined if any of the following conditions are violated:
 ///
-/// * `src` must be [valid] for reads.
+/// * `src` must be either [valid] for reads, or it must point to memory outside of all Rust
+///   allocations and reading from that memory must:
+///   - not trap, and
+///   - not cause any memory inside a Rust allocation to be modified.
 ///
 /// * `src` must be properly aligned.
 ///
-/// * `src` must point to a properly initialized value of type `T`.
-///
-/// Like [`read`], `read_volatile` creates a bitwise copy of `T`, regardless of
-/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the returned
-/// value and the value at `*src` can [violate memory safety][read-ownership].
-/// However, storing non-[`Copy`] types in volatile memory is almost certainly
-/// incorrect.
+/// * Reading from `src` must produce a properly initialized value of type `T`.
 ///
 /// Note that even if `T` has size `0`, the pointer must be properly aligned.
 ///
 /// [valid]: self#safety
 /// [read-ownership]: read#ownership-of-the-returned-value
 ///
-/// Just like in C, whether an operation is volatile has no bearing whatsoever
-/// on questions involving concurrent access from multiple threads. Volatile
-/// accesses behave exactly like non-atomic accesses in that regard. In particular,
-/// a race between a `read_volatile` and any write operation to the same location
-/// is undefined behavior.
-///
 /// # Examples
 ///
 /// Basic usage:
@@ -2090,50 +2102,63 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
     unsafe {
         ub_checks::assert_unsafe_precondition!(
             check_language_ub,
-            "ptr::read_volatile requires that the pointer argument is aligned and non-null",
+            "ptr::read_volatile requires that the pointer argument is aligned",
             (
                 addr: *const () = src as *const (),
                 align: usize = align_of::<T>(),
-                is_zst: bool = T::IS_ZST,
-            ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, is_zst)
+            ) => ub_checks::maybe_is_aligned(addr, align)
         );
         intrinsics::volatile_load(src)
     }
 }
 
-/// Performs a volatile write of a memory location with the given value without
-/// reading or dropping the old value.
-///
-/// Volatile operations are intended to act on I/O memory, and are guaranteed
-/// to not be elided or reordered by the compiler across other volatile
-/// operations.
-///
-/// `write_volatile` does not drop the contents of `dst`. This is safe, but it
-/// could leak allocations or resources, so care should be taken not to overwrite
-/// an object that should be dropped.
-///
-/// Additionally, it does not drop `src`. Semantically, `src` is moved into the
-/// location pointed to by `dst`.
-///
-/// # Notes
-///
-/// Rust does not currently have a rigorously and formally defined memory model,
-/// so the precise semantics of what "volatile" means here is subject to change
-/// over time. That being said, the semantics will almost always end up pretty
-/// similar to [C11's definition of volatile][c11].
-///
-/// The compiler shouldn't change the relative order or number of volatile
-/// memory operations. However, volatile memory operations on zero-sized types
-/// (e.g., if a zero-sized type is passed to `write_volatile`) are noops
-/// and may be ignored.
-///
-/// [c11]: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
+/// Performs a volatile write of a memory location with the given value without reading or dropping
+/// the old value.
+///
+/// Volatile operations are intended to act on I/O memory. As such, they are considered externally
+/// observable events (just like syscalls), and are guaranteed to not be elided or reordered by the
+/// compiler across other externally observable events. With this in mind, there are two cases of
+/// usage that need to be distinguished:
+///
+/// - When a volatile operation is used for memory inside an [allocation], it behaves exactly like
+///   [`write`][write()], except for the additional guarantee that it won't be elided or reordered
+///   (see above). This implies that the operation will actually access memory and not e.g. be
+///   lowered to a register access. Other than that, all the usual rules for memory accesses apply
+///   (including provenance). In particular, just like in C, whether an operation is volatile has no
+///   bearing whatsoever on questions involving concurrent access from multiple threads. Volatile
+///   accesses behave exactly like non-atomic accesses in that regard.
+///
+/// - Volatile operations, however, may also be used to access memory that is _outside_ of any Rust
+///   allocation. In this use-case, the pointer does *not* have to be [valid] for writes. This is
+///   typically used for CPU and peripheral registers that must be accessed via an I/O memory
+///   mapping, most commonly at fixed addresses reserved by the hardware. These often have special
+///   semantics associated to their manipulation, and cannot be used as general purpose memory.
+///   Here, any address value is possible, including 0 and [`usize::MAX`], so long as the semantics
+///   of such a write are well-defined by the target hardware. The provenance of the pointer is
+///   irrelevant, and it can be created with [`without_provenance`]. The access must not trap. It
+///   can cause side-effects, but those must not affect Rust-allocated memory in any way. This
+///   access is still not considered [atomic], and as such it cannot be used for inter-thread
+///   synchronization.
+///
+/// Note that volatile memory operations on zero-sized types (e.g., if a zero-sized type is passed
+/// to `write_volatile`) are noops and may be ignored.
+///
+/// `write_volatile` does not drop the contents of `dst`. This is safe, but it could leak
+/// allocations or resources, so care should be taken not to overwrite an object that should be
+/// dropped when operating on Rust memory. Additionally, it does not drop `src`. Semantically, `src`
+/// is moved into the location pointed to by `dst`.
+///
+/// [allocation]: crate::ptr#allocated-object
+/// [atomic]: crate::sync::atomic#memory-model-for-atomic-accesses
 ///
 /// # Safety
 ///
 /// Behavior is undefined if any of the following conditions are violated:
 ///
-/// * `dst` must be [valid] for writes.
+/// * `dst` must be either [valid] for writes, or it must point to memory outside of all Rust
+///   allocations and writing to that memory must:
+///   - not trap, and
+///   - not cause any memory inside a Rust allocation to be modified.
 ///
 /// * `dst` must be properly aligned.
 ///
@@ -2141,12 +2166,6 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
 ///
 /// [valid]: self#safety
 ///
-/// Just like in C, whether an operation is volatile has no bearing whatsoever
-/// on questions involving concurrent access from multiple threads. Volatile
-/// accesses behave exactly like non-atomic accesses in that regard. In particular,
-/// a race between a `write_volatile` and any other operation (reading or writing)
-/// on the same location is undefined behavior.
-///
 /// # Examples
 ///
 /// Basic usage:
@@ -2170,12 +2189,11 @@ pub unsafe fn write_volatile<T>(dst: *mut T, src: T) {
     unsafe {
         ub_checks::assert_unsafe_precondition!(
             check_language_ub,
-            "ptr::write_volatile requires that the pointer argument is aligned and non-null",
+            "ptr::write_volatile requires that the pointer argument is aligned",
             (
                 addr: *mut () = dst as *mut (),
                 align: usize = align_of::<T>(),
-                is_zst: bool = T::IS_ZST,
-            ) => ub_checks::maybe_is_aligned_and_not_null(addr, align, is_zst)
+            ) => ub_checks::maybe_is_aligned(addr, align)
         );
         intrinsics::volatile_store(dst, src);
     }
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index 18a516c0f60..029abf17539 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -2651,7 +2651,6 @@ impl str {
     /// you're trying to parse into.
     ///
     /// `parse` can parse into any type that implements the [`FromStr`] trait.
-
     ///
     /// # Errors
     ///
diff --git a/library/core/src/ub_checks.rs b/library/core/src/ub_checks.rs
index a7caaeb95cd..b809294cfce 100644
--- a/library/core/src/ub_checks.rs
+++ b/library/core/src/ub_checks.rs
@@ -121,12 +121,24 @@ pub(crate) const fn maybe_is_aligned_and_not_null(
     is_zst: bool,
 ) -> bool {
     // This is just for safety checks so we can const_eval_select.
+    maybe_is_aligned(ptr, align) && (is_zst || !ptr.is_null())
+}
+
+/// Checks whether `ptr` is properly aligned with respect to the given alignment.
+///
+/// In `const` this is approximate and can fail spuriously. It is primarily intended
+/// for `assert_unsafe_precondition!` with `check_language_ub`, in which case the
+/// check is anyway not executed in `const`.
+#[inline]
+#[rustc_allow_const_fn_unstable(const_eval_select)]
+pub(crate) const fn maybe_is_aligned(ptr: *const (), align: usize) -> bool {
+    // This is just for safety checks so we can const_eval_select.
     const_eval_select!(
-        @capture { ptr: *const (), align: usize, is_zst: bool } -> bool:
+        @capture { ptr: *const (), align: usize } -> bool:
         if const {
-            is_zst || !ptr.is_null()
+            true
         } else {
-            ptr.is_aligned_to(align) && (is_zst || !ptr.is_null())
+            ptr.is_aligned_to(align)
         }
     )
 }
diff --git a/library/coretests/tests/iter/adapters/cloned.rs b/library/coretests/tests/iter/adapters/cloned.rs
index 78babb7feab..0a3dd1ce46e 100644
--- a/library/coretests/tests/iter/adapters/cloned.rs
+++ b/library/coretests/tests/iter/adapters/cloned.rs
@@ -31,7 +31,8 @@ fn test_cloned_side_effects() {
             .zip(&[1]);
         for _ in iter {}
     }
-    assert_eq!(count, 2);
+    // Zip documentation provides some leeway about side-effects
+    assert!([1, 2].iter().any(|v| *v == count));
 }
 
 #[test]
diff --git a/library/coretests/tests/iter/adapters/zip.rs b/library/coretests/tests/iter/adapters/zip.rs
index 70392dca0fa..063e226a61c 100644
--- a/library/coretests/tests/iter/adapters/zip.rs
+++ b/library/coretests/tests/iter/adapters/zip.rs
@@ -107,9 +107,19 @@ fn test_zip_next_back_side_effects_exhausted() {
     iter.next();
     iter.next();
     iter.next();
-    iter.next();
+    assert_eq!(iter.next(), None);
     assert_eq!(iter.next_back(), None);
-    assert_eq!(a, vec![1, 2, 3, 4, 6, 5]);
+
+    assert!(a.starts_with(&[1, 2, 3]));
+    let a_len = a.len();
+    // Tail-side-effects of forward-iteration are "at most one" per next().
+    // And for reverse iteration we don't guarantee much either.
+    // But we can put some bounds on the possible behaviors.
+    assert!(a_len <= 6);
+    assert!(a_len >= 3);
+    a.sort();
+    assert_eq!(a, &[1, 2, 3, 4, 5, 6][..a.len()]);
+
     assert_eq!(b, vec![200, 300, 400]);
 }
 
@@ -120,7 +130,8 @@ fn test_zip_cloned_sideffectful() {
 
     for _ in xs.iter().cloned().zip(ys.iter().cloned()) {}
 
-    assert_eq!(&xs, &[1, 1, 1, 0][..]);
+    // Zip documentation permits either case.
+    assert!([&[1, 1, 1, 0], &[1, 1, 0, 0]].iter().any(|v| &xs == *v));
     assert_eq!(&ys, &[1, 1][..]);
 
     let xs = [CountClone::new(), CountClone::new()];
@@ -139,7 +150,8 @@ fn test_zip_map_sideffectful() {
 
     for _ in xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1)) {}
 
-    assert_eq!(&xs, &[1, 1, 1, 1, 1, 0]);
+    // Zip documentation permits either case.
+    assert!([&[1, 1, 1, 1, 1, 0], &[1, 1, 1, 1, 0, 0]].iter().any(|v| &xs == *v));
     assert_eq!(&ys, &[1, 1, 1, 1]);
 
     let mut xs = [0; 4];
@@ -168,7 +180,8 @@ fn test_zip_map_rev_sideffectful() {
 
     {
         let mut it = xs.iter_mut().map(|x| *x += 1).zip(ys.iter_mut().map(|y| *y += 1));
-        (&mut it).take(5).count();
+        // the current impl only trims the tails if the iterator isn't exhausted
+        (&mut it).take(3).count();
         it.next_back();
     }
     assert_eq!(&xs, &[1, 1, 1, 1, 1, 1]);
@@ -211,9 +224,18 @@ fn test_zip_nth_back_side_effects_exhausted() {
     iter.next();
     iter.next();
     iter.next();
-    iter.next();
+    assert_eq!(iter.next(), None);
     assert_eq!(iter.nth_back(0), None);
-    assert_eq!(a, vec![1, 2, 3, 4, 6, 5]);
+    assert!(a.starts_with(&[1, 2, 3]));
+    let a_len = a.len();
+    // Tail-side-effects of forward-iteration are "at most one" per next().
+    // And for reverse iteration we don't guarantee much either.
+    // But we can put some bounds on the possible behaviors.
+    assert!(a_len <= 6);
+    assert!(a_len >= 3);
+    a.sort();
+    assert_eq!(a, &[1, 2, 3, 4, 5, 6][..a.len()]);
+
     assert_eq!(b, vec![200, 300, 400]);
 }
 
@@ -238,32 +260,6 @@ fn test_zip_trusted_random_access_composition() {
 }
 
 #[test]
-#[cfg(panic = "unwind")]
-fn test_zip_trusted_random_access_next_back_drop() {
-    use std::panic::{AssertUnwindSafe, catch_unwind};
-
-    let mut counter = 0;
-
-    let it = [42].iter().map(|e| {
-        let c = counter;
-        counter += 1;
-        if c == 0 {
-            panic!("bomb");
-        }
-
-        e
-    });
-    let it2 = [(); 0].iter();
-    let mut zip = it.zip(it2);
-    catch_unwind(AssertUnwindSafe(|| {
-        zip.next_back();
-    }))
-    .unwrap_err();
-    assert!(zip.next().is_none());
-    assert_eq!(counter, 1);
-}
-
-#[test]
 fn test_double_ended_zip() {
     let xs = [1, 2, 3, 4, 5, 6];
     let ys = [1, 2, 3, 7];
@@ -276,6 +272,63 @@ fn test_double_ended_zip() {
 }
 
 #[test]
+#[cfg(panic = "unwind")]
+/// Regression test for #137255
+/// A previous implementation of Zip TrustedRandomAccess specializations tried to do a lot of work
+/// to preserve side-effects of equalizing the iterator lengths during backwards iteration.
+/// This lead to several cases of unsoundness, twice due to being left in an inconsistent state
+/// after panics.
+/// The new implementation does not try as hard, but we still need panic-safety.
+fn test_nested_zip_panic_safety() {
+    use std::panic::{AssertUnwindSafe, catch_unwind, resume_unwind};
+    use std::sync::atomic::{AtomicUsize, Ordering};
+
+    let mut panic = true;
+    // keeps track of how often element get visited, must be at most once each
+    let witness = [8, 9, 10, 11, 12].map(|i| (i, AtomicUsize::new(0)));
+    let a = witness.as_slice().iter().map(|e| {
+        e.1.fetch_add(1, Ordering::Relaxed);
+        if panic {
+            panic = false;
+            resume_unwind(Box::new(()))
+        }
+        e.0
+    });
+    // shorter than `a`, so `a` will get trimmed
+    let b = [1, 2, 3, 4].as_slice().iter().copied();
+    // shorter still, so `ab` will get trimmed.`
+    let c = [5, 6, 7].as_slice().iter().copied();
+
+    // This will panic during backwards trimming.
+    let ab = zip(a, b);
+    // This being Zip + TrustedRandomAccess means it will only call `next_back``
+    // during trimming and otherwise do calls `__iterator_get_unchecked` on `ab`.
+    let mut abc = zip(ab, c);
+
+    assert_eq!(abc.len(), 3);
+    // This will first trigger backwards trimming before it would normally obtain the
+    // actual element if it weren't for the panic.
+    // This used to corrupt the internal state of `abc`, which then lead to
+    // TrustedRandomAccess safety contract violations in calls to  `ab`,
+    // which ultimately lead to UB.
+    catch_unwind(AssertUnwindSafe(|| abc.next_back())).ok();
+    // check for sane outward behavior after the panic, which indicates a sane internal state.
+    // Technically these outcomes are not required because a panic frees us from correctness obligations.
+    assert_eq!(abc.len(), 2);
+    assert_eq!(abc.next(), Some(((8, 1), 5)));
+    assert_eq!(abc.next_back(), Some(((9, 2), 6)));
+    for (i, (_, w)) in witness.iter().enumerate() {
+        let v = w.load(Ordering::Relaxed);
+        // required by TRA contract
+        assert!(v <= 1, "expected idx {i} to be visited at most once, actual: {v}");
+    }
+    // Trimming panicked and should only run once, so this one won't be visited.
+    // Implementation detail, but not trying to run it again is what keeps
+    // things simple.
+    assert_eq!(witness[3].1.load(Ordering::Relaxed), 0);
+}
+
+#[test]
 fn test_issue_82282() {
     fn overflowed_zip(arr: &[i32]) -> impl Iterator<Item = (i32, &())> {
         static UNIT_EMPTY_ARR: [(); 0] = [];
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
index e2249bd7f6a..4cfac9ecc2a 100644
--- a/library/coretests/tests/lib.rs
+++ b/library/coretests/tests/lib.rs
@@ -19,7 +19,6 @@
 #![feature(const_deref)]
 #![feature(const_destruct)]
 #![feature(const_eval_select)]
-#![feature(const_float_round_methods)]
 #![feature(const_ops)]
 #![feature(const_ref_cell)]
 #![feature(const_trait_impl)]
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 311b2cb9323..323742a75b0 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -329,7 +329,6 @@
 #![feature(bstr_internals)]
 #![feature(char_internals)]
 #![feature(clone_to_uninit)]
-#![feature(const_float_round_methods)]
 #![feature(core_intrinsics)]
 #![feature(core_io_borrowed_buf)]
 #![feature(duration_constants)]
diff --git a/library/std/src/num/f32.rs b/library/std/src/num/f32.rs
index e79ec2ae966..2bff73add33 100644
--- a/library/std/src/num/f32.rs
+++ b/library/std/src/num/f32.rs
@@ -44,7 +44,7 @@ impl f32 {
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
+    #[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn floor(self) -> f32 {
         core::f32::math::floor(self)
@@ -67,7 +67,7 @@ impl f32 {
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
+    #[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn ceil(self) -> f32 {
         core::f32::math::ceil(self)
@@ -96,7 +96,7 @@ impl f32 {
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
+    #[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn round(self) -> f32 {
         core::f32::math::round(self)
@@ -123,7 +123,7 @@ impl f32 {
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "round_ties_even", since = "1.77.0")]
-    #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
+    #[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn round_ties_even(self) -> f32 {
         core::f32::math::round_ties_even(self)
@@ -149,7 +149,7 @@ impl f32 {
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
+    #[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn trunc(self) -> f32 {
         core::f32::math::trunc(self)
@@ -173,7 +173,7 @@ impl f32 {
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
+    #[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn fract(self) -> f32 {
         core::f32::math::fract(self)
diff --git a/library/std/src/num/f64.rs b/library/std/src/num/f64.rs
index 853417825f9..b71e319f407 100644
--- a/library/std/src/num/f64.rs
+++ b/library/std/src/num/f64.rs
@@ -44,7 +44,7 @@ impl f64 {
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
+    #[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn floor(self) -> f64 {
         core::f64::math::floor(self)
@@ -67,7 +67,7 @@ impl f64 {
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
+    #[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn ceil(self) -> f64 {
         core::f64::math::ceil(self)
@@ -96,7 +96,7 @@ impl f64 {
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
+    #[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn round(self) -> f64 {
         core::f64::math::round(self)
@@ -123,7 +123,7 @@ impl f64 {
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "round_ties_even", since = "1.77.0")]
-    #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
+    #[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn round_ties_even(self) -> f64 {
         core::f64::math::round_ties_even(self)
@@ -149,7 +149,7 @@ impl f64 {
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
+    #[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn trunc(self) -> f64 {
         core::f64::math::trunc(self)
@@ -173,7 +173,7 @@ impl f64 {
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_float_round_methods", issue = "141555")]
+    #[rustc_const_stable(feature = "const_float_round_methods", since = "CURRENT_RUSTC_VERSION")]
     #[inline]
     pub const fn fract(self) -> f64 {
         core::f64::math::fract(self)
diff --git a/src/bootstrap/README.md b/src/bootstrap/README.md
index 6ce4c6d62fa..2965174b45b 100644
--- a/src/bootstrap/README.md
+++ b/src/bootstrap/README.md
@@ -105,7 +105,7 @@ build/
       debuginfo/
       ...
 
-    # Bootstrap host tools (which are always compiled with the stage0 compiler)
+    # Host tools (which are always compiled with the stage0 compiler)
     # are stored here.
     bootstrap-tools/
 
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index d8c6be78247..40e08361a0f 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -8,6 +8,7 @@ import re
 import shutil
 import subprocess
 import sys
+import sysconfig
 import tarfile
 import tempfile
 
@@ -333,7 +334,11 @@ def default_build_triple(verbose):
         if ostype == "Android":
             kernel = "linux-android"
         else:
-            kernel = "unknown-linux-gnu"
+            python_soabi = sysconfig.get_config_var("SOABI")
+            if python_soabi is not None and "musl" in python_soabi:
+                kernel = "unknown-linux-musl"
+            else:
+                kernel = "unknown-linux-gnu"
     elif kernel == "SunOS":
         kernel = "pc-solaris"
         # On Solaris, uname -m will return a machine classification instead
diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs
index 3278b55305c..f0acb7f7141 100644
--- a/src/bootstrap/src/core/build_steps/check.rs
+++ b/src/bootstrap/src/core/build_steps/check.rs
@@ -4,7 +4,10 @@ use crate::core::build_steps::compile::{
     add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo, std_crates_for_run_make,
 };
 use crate::core::build_steps::tool;
-use crate::core::build_steps::tool::{COMPILETEST_ALLOW_FEATURES, SourceType, prepare_tool_cargo};
+use crate::core::build_steps::tool::{
+    COMPILETEST_ALLOW_FEATURES, SourceType, ToolTargetBuildMode, get_tool_target_compiler,
+    prepare_tool_cargo,
+};
 use crate::core::builder::{
     self, Alias, Builder, Kind, RunConfig, ShouldRun, Step, StepMetadata, crate_description,
 };
@@ -252,8 +255,10 @@ fn prepare_compiler_for_check(
     mode: Mode,
 ) -> Compiler {
     let host = builder.host_target;
+
     match mode {
         Mode::ToolBootstrap => builder.compiler(0, host),
+        Mode::ToolTarget => get_tool_target_compiler(builder, ToolTargetBuildMode::Build(target)),
         Mode::ToolStd => {
             if builder.config.compile_time_deps {
                 // When --compile-time-deps is passed, we can't use any rustc
@@ -350,7 +355,7 @@ impl Step for CodegenBackend {
         cargo
             .arg("--manifest-path")
             .arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
-        rustc_cargo_env(builder, &mut cargo, target, build_compiler.stage);
+        rustc_cargo_env(builder, &mut cargo, target);
 
         let _guard = builder.msg_check(format!("rustc_codegen_{backend}"), target, None);
 
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 09bb2e35bda..c7e7b0160b1 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -19,7 +19,7 @@ use serde_derive::Deserialize;
 use tracing::{instrument, span};
 
 use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags};
-use crate::core::build_steps::tool::SourceType;
+use crate::core::build_steps::tool::{SourceType, copy_lld_artifacts};
 use crate::core::build_steps::{dist, llvm};
 use crate::core::builder;
 use crate::core::builder::{
@@ -1316,15 +1316,10 @@ pub fn rustc_cargo(
         cargo.env("RUSTC_WRAPPER", ccache);
     }
 
-    rustc_cargo_env(builder, cargo, target, build_compiler.stage);
+    rustc_cargo_env(builder, cargo, target);
 }
 
-pub fn rustc_cargo_env(
-    builder: &Builder<'_>,
-    cargo: &mut Cargo,
-    target: TargetSelection,
-    build_stage: u32,
-) {
+pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
     // Set some configuration variables picked up by build scripts and
     // the compiler alike
     cargo
@@ -1379,18 +1374,24 @@ pub fn rustc_cargo_env(
         cargo.rustflag("--cfg=llvm_enzyme");
     }
 
-    // Note that this is disabled if LLVM itself is disabled or we're in a check
-    // build. If we are in a check build we still go ahead here presuming we've
-    // detected that LLVM is already built and good to go which helps prevent
-    // busting caches (e.g. like #71152).
+    // These conditionals represent a tension between three forces:
+    // - For non-check builds, we need to define some LLVM-related environment
+    //   variables, requiring LLVM to have been built.
+    // - For check builds, we want to avoid building LLVM if possible.
+    // - Check builds and non-check builds should have the same environment if
+    //   possible, to avoid unnecessary rebuilds due to cache-busting.
+    //
+    // Therefore we try to avoid building LLVM for check builds, but only if
+    // building LLVM would be expensive. If "building" LLVM is cheap
+    // (i.e. it's already built or is downloadable), we prefer to maintain a
+    // consistent environment between check and non-check builds.
     if builder.config.llvm_enabled(target) {
-        let building_is_expensive =
+        let building_llvm_is_expensive =
             crate::core::build_steps::llvm::prebuilt_llvm_config(builder, target, false)
                 .should_build();
-        // `top_stage == stage` might be false for `check --stage 1`, if we are building the stage 1 compiler
-        let can_skip_build = builder.kind == Kind::Check && builder.top_stage == build_stage;
-        let should_skip_build = building_is_expensive && can_skip_build;
-        if !should_skip_build {
+
+        let skip_llvm = (builder.kind == Kind::Check) && building_llvm_is_expensive;
+        if !skip_llvm {
             rustc_llvm_env(builder, cargo, target)
         }
     }
@@ -1407,6 +1408,9 @@ pub fn rustc_cargo_env(
 
 /// Pass down configuration from the LLVM build into the build of
 /// rustc_llvm and rustc_codegen_llvm.
+///
+/// Note that this has the side-effect of _building LLVM_, which is sometimes
+/// unwanted (e.g. for check builds).
 fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) {
     if builder.config.is_rust_llvm(target) {
         cargo.env("LLVM_RUSTLLVM", "1");
@@ -1665,7 +1669,7 @@ impl Step for CodegenBackend {
         cargo
             .arg("--manifest-path")
             .arg(builder.src.join(format!("compiler/rustc_codegen_{backend}/Cargo.toml")));
-        rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
+        rustc_cargo_env(builder, &mut cargo, target);
 
         // Ideally, we'd have a separate step for the individual codegen backends,
         // like we have in tests (test::CodegenGCC) but that would require a lot of restructuring.
@@ -2050,19 +2054,20 @@ impl Step for Assemble {
             }
         }
 
-        let maybe_install_llvm_bitcode_linker = |compiler| {
+        let maybe_install_llvm_bitcode_linker = || {
             if builder.config.llvm_bitcode_linker_enabled {
                 trace!("llvm-bitcode-linker enabled, installing");
-                let llvm_bitcode_linker =
-                    builder.ensure(crate::core::build_steps::tool::LlvmBitcodeLinker {
-                        build_compiler: compiler,
-                        target: target_compiler.host,
-                    });
+                let llvm_bitcode_linker = builder.ensure(
+                    crate::core::build_steps::tool::LlvmBitcodeLinker::from_target_compiler(
+                        builder,
+                        target_compiler,
+                    ),
+                );
 
                 // Copy the llvm-bitcode-linker to the self-contained binary directory
                 let bindir_self_contained = builder
-                    .sysroot(compiler)
-                    .join(format!("lib/rustlib/{}/bin/self-contained", compiler.host));
+                    .sysroot(target_compiler)
+                    .join(format!("lib/rustlib/{}/bin/self-contained", target_compiler.host));
                 let tool_exe = exe("llvm-bitcode-linker", target_compiler.host);
 
                 t!(fs::create_dir_all(&bindir_self_contained));
@@ -2089,9 +2094,9 @@ impl Step for Assemble {
                 builder.info(&format!("Creating a sysroot for stage{stage} compiler (use `rustup toolchain link 'name' build/host/stage{stage}`)", stage = target_compiler.stage));
             }
 
-            let mut precompiled_compiler = target_compiler;
-            precompiled_compiler.forced_compiler(true);
-            maybe_install_llvm_bitcode_linker(precompiled_compiler);
+            // FIXME: this is incomplete, we do not copy a bunch of other stuff to the downloaded
+            // sysroot...
+            maybe_install_llvm_bitcode_linker();
 
             return target_compiler;
         }
@@ -2256,10 +2261,12 @@ impl Step for Assemble {
         copy_codegen_backends_to_sysroot(builder, build_compiler, target_compiler);
 
         if builder.config.lld_enabled {
-            builder.ensure(crate::core::build_steps::tool::LldWrapper {
-                build_compiler,
-                target_compiler,
-            });
+            let lld_wrapper =
+                builder.ensure(crate::core::build_steps::tool::LldWrapper::for_use_by_compiler(
+                    builder,
+                    target_compiler,
+                ));
+            copy_lld_artifacts(builder, lld_wrapper, target_compiler);
         }
 
         if builder.config.llvm_enabled(target_compiler.host) && builder.config.llvm_tools_enabled {
@@ -2284,15 +2291,14 @@ impl Step for Assemble {
         }
 
         // In addition to `rust-lld` also install `wasm-component-ld` when
-        // LLD is enabled. This is a relatively small binary that primarily
-        // delegates to the `rust-lld` binary for linking and then runs
-        // logic to create the final binary. This is used by the
-        // `wasm32-wasip2` target of Rust.
+        // is enabled. This is used by the `wasm32-wasip2` target of Rust.
         if builder.tool_enabled("wasm-component-ld") {
-            let wasm_component = builder.ensure(crate::core::build_steps::tool::WasmComponentLd {
-                compiler: build_compiler,
-                target: target_compiler.host,
-            });
+            let wasm_component = builder.ensure(
+                crate::core::build_steps::tool::WasmComponentLd::for_use_by_compiler(
+                    builder,
+                    target_compiler,
+                ),
+            );
             builder.copy_link(
                 &wasm_component.tool_path,
                 &libdir_bin.join(wasm_component.tool_path.file_name().unwrap()),
@@ -2300,7 +2306,7 @@ impl Step for Assemble {
             );
         }
 
-        maybe_install_llvm_bitcode_linker(target_compiler);
+        maybe_install_llvm_bitcode_linker();
 
         // Ensure that `libLLVM.so` ends up in the newly build compiler directory,
         // so that it can be found when the newly built `rustc` is run.
diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs
index 8b2d65ace50..39e4fb2ac01 100644
--- a/src/bootstrap/src/core/build_steps/dist.rs
+++ b/src/bootstrap/src/core/build_steps/dist.rs
@@ -1575,7 +1575,10 @@ impl Step for Extended {
             compiler: builder.compiler(stage, target),
             backend: "cranelift".to_string(),
         });
-        add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker {compiler, target});
+        add_component!("llvm-bitcode-linker" => LlvmBitcodeLinker {
+            build_compiler: compiler,
+            target
+        });
 
         let etc = builder.src.join("src/etc/installer");
 
@@ -2341,9 +2344,13 @@ impl Step for LlvmTools {
     }
 }
 
+/// Distributes the `llvm-bitcode-linker` tool so that it can be used by a compiler whose host
+/// is `target`.
 #[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)]
 pub struct LlvmBitcodeLinker {
-    pub compiler: Compiler,
+    /// The linker will be compiled by this compiler.
+    pub build_compiler: Compiler,
+    /// The linker will by usable by rustc on this host.
     pub target: TargetSelection,
 }
 
@@ -2359,9 +2366,8 @@ impl Step for LlvmBitcodeLinker {
 
     fn make_run(run: RunConfig<'_>) {
         run.builder.ensure(LlvmBitcodeLinker {
-            compiler: run.builder.compiler_for(
-                run.builder.top_stage,
-                run.builder.config.host_target,
+            build_compiler: tool::LlvmBitcodeLinker::get_build_compiler_for_target(
+                run.builder,
                 run.target,
             ),
             target: run.target,
@@ -2369,13 +2375,10 @@ impl Step for LlvmBitcodeLinker {
     }
 
     fn run(self, builder: &Builder<'_>) -> Option<GeneratedTarball> {
-        let compiler = self.compiler;
         let target = self.target;
 
-        builder.ensure(compile::Rustc::new(compiler, target));
-
-        let llbc_linker =
-            builder.ensure(tool::LlvmBitcodeLinker { build_compiler: compiler, target });
+        let llbc_linker = builder
+            .ensure(tool::LlvmBitcodeLinker::from_build_compiler(self.build_compiler, target));
 
         let self_contained_bin_dir = format!("lib/rustlib/{}/bin/self-contained", target.triple);
 
diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs
index 4434d6658eb..4156b49a8b3 100644
--- a/src/bootstrap/src/core/build_steps/install.rs
+++ b/src/bootstrap/src/core/build_steps/install.rs
@@ -287,7 +287,7 @@ install!((self, builder, _config),
         }
     };
     LlvmBitcodeLinker, alias = "llvm-bitcode-linker", Self::should_build(_config), only_hosts: true, {
-        if let Some(tarball) = builder.ensure(dist::LlvmBitcodeLinker { compiler: self.compiler, target: self.target }) {
+        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);
         } else {
             builder.info(
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 9e7ea5c115f..7652ea1a488 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -1757,6 +1757,10 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
         cmd.arg("--host").arg(&*compiler.host.triple);
         cmd.arg("--llvm-filecheck").arg(builder.llvm_filecheck(builder.config.host_target));
 
+        if let Some(codegen_backend) = builder.config.default_codegen_backend(compiler.host) {
+            cmd.arg("--codegen-backend").arg(&codegen_backend);
+        }
+
         if builder.build.config.llvm_enzyme {
             cmd.arg("--has-enzyme");
         }
@@ -1810,7 +1814,24 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
         }
 
         let mut flags = if is_rustdoc { Vec::new() } else { vec!["-Crpath".to_string()] };
-        flags.push(format!("-Cdebuginfo={}", builder.config.rust_debuginfo_level_tests));
+        flags.push(format!(
+            "-Cdebuginfo={}",
+            if suite == "codegen" {
+                // codegen tests typically check LLVM IR and are sensitive to additional debuginfo.
+                // So do not apply `rust.debuginfo-level-tests` for codegen tests.
+                if builder.config.rust_debuginfo_level_tests
+                    != crate::core::config::DebuginfoLevel::None
+                {
+                    println!(
+                        "NOTE: ignoring `rust.debuginfo-level-tests={}` for codegen tests",
+                        builder.config.rust_debuginfo_level_tests
+                    );
+                }
+                crate::core::config::DebuginfoLevel::None
+            } else {
+                builder.config.rust_debuginfo_level_tests
+            }
+        ));
         flags.extend(builder.config.cmd.compiletest_rustc_args().iter().map(|s| s.to_string()));
 
         if suite != "mir-opt" {
@@ -2945,7 +2966,8 @@ impl Step for RemoteCopyLibs {
 
         builder.info(&format!("REMOTE copy libs to emulator ({target})"));
 
-        let remote_test_server = builder.ensure(tool::RemoteTestServer { compiler, target });
+        let remote_test_server =
+            builder.ensure(tool::RemoteTestServer { build_compiler: compiler, target });
 
         // Spawn the emulator and wait for it to come online
         let tool = builder.tool_exe(Tool::RemoteTestClient);
@@ -3386,7 +3408,7 @@ impl Step for CodegenCranelift {
             cargo
                 .arg("--manifest-path")
                 .arg(builder.src.join("compiler/rustc_codegen_cranelift/build_system/Cargo.toml"));
-            compile::rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
+            compile::rustc_cargo_env(builder, &mut cargo, target);
 
             // Avoid incremental cache issues when changing rustc
             cargo.env("CARGO_BUILD_INCREMENTAL", "false");
@@ -3518,7 +3540,7 @@ impl Step for CodegenGCC {
             cargo
                 .arg("--manifest-path")
                 .arg(builder.src.join("compiler/rustc_codegen_gcc/build_system/Cargo.toml"));
-            compile::rustc_cargo_env(builder, &mut cargo, target, compiler.stage);
+            compile::rustc_cargo_env(builder, &mut cargo, target);
             add_cg_gcc_cargo_flags(&mut cargo, &gcc);
 
             // Avoid incremental cache issues when changing rustc
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 1c994b0ccfc..f5fa33b98f3 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -42,7 +42,8 @@ pub enum ToolArtifactKind {
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 struct ToolBuild {
-    compiler: Compiler,
+    /// Compiler that will build this tool.
+    build_compiler: Compiler,
     target: TargetSelection,
     tool: &'static str,
     path: &'static str,
@@ -112,34 +113,34 @@ impl Step for ToolBuild {
         let mut tool = self.tool;
         let path = self.path;
 
-        let target_compiler = self.compiler;
-        self.compiler = if self.mode == Mode::ToolRustc {
-            get_tool_rustc_compiler(builder, self.compiler)
+        let target_compiler = self.build_compiler;
+        self.build_compiler = if self.mode == Mode::ToolRustc {
+            get_tool_rustc_compiler(builder, self.build_compiler)
         } else {
-            self.compiler
+            self.build_compiler
         };
 
         match self.mode {
             Mode::ToolRustc => {
                 // If compiler was forced, its artifacts should have been prepared earlier.
-                if !self.compiler.is_forced_compiler() {
-                    builder.std(self.compiler, self.compiler.host);
-                    builder.ensure(compile::Rustc::new(self.compiler, target));
+                if !self.build_compiler.is_forced_compiler() {
+                    builder.std(self.build_compiler, self.build_compiler.host);
+                    builder.ensure(compile::Rustc::new(self.build_compiler, target));
                 }
             }
             Mode::ToolStd => {
                 // If compiler was forced, its artifacts should have been prepared earlier.
-                if !self.compiler.is_forced_compiler() {
-                    builder.std(self.compiler, target)
+                if !self.build_compiler.is_forced_compiler() {
+                    builder.std(self.build_compiler, target);
                 }
             }
-            Mode::ToolBootstrap => {} // uses downloaded stage0 compiler libs
+            Mode::ToolBootstrap | Mode::ToolTarget => {} // uses downloaded stage0 compiler libs
             _ => panic!("unexpected Mode for tool build"),
         }
 
         let mut cargo = prepare_tool_cargo(
             builder,
-            self.compiler,
+            self.build_compiler,
             self.mode,
             target,
             Kind::Build,
@@ -161,7 +162,7 @@ impl Step for ToolBuild {
 
         // Rustc tools (miri, clippy, cargo, rustfmt, rust-analyzer)
         // could use the additional optimizations.
-        if self.mode == Mode::ToolRustc && is_lto_stage(&self.compiler) {
+        if self.mode == Mode::ToolRustc && is_lto_stage(&self.build_compiler) {
             let lto = match builder.config.rust_lto {
                 RustcLto::Off => Some("off"),
                 RustcLto::Thin => Some("thin"),
@@ -183,8 +184,9 @@ impl Step for ToolBuild {
             Kind::Build,
             self.mode,
             self.tool,
-            self.compiler.stage,
-            &self.compiler.host,
+            // A stage N tool is built with the stage N-1 compiler.
+            self.build_compiler.stage + 1,
+            &self.build_compiler.host,
             &self.target,
         );
 
@@ -207,14 +209,14 @@ impl Step for ToolBuild {
             }
             let tool_path = match self.artifact_kind {
                 ToolArtifactKind::Binary => {
-                    copy_link_tool_bin(builder, self.compiler, self.target, self.mode, tool)
+                    copy_link_tool_bin(builder, self.build_compiler, self.target, self.mode, tool)
                 }
                 ToolArtifactKind::Library => builder
-                    .cargo_out(self.compiler, self.mode, self.target)
+                    .cargo_out(self.build_compiler, self.mode, self.target)
                     .join(format!("lib{tool}.rlib")),
             };
 
-            ToolBuildResult { tool_path, build_compiler: self.compiler, target_compiler }
+            ToolBuildResult { tool_path, build_compiler: self.build_compiler, target_compiler }
         }
     }
 }
@@ -365,6 +367,47 @@ pub(crate) fn get_tool_rustc_compiler(
     builder.compiler(target_compiler.stage.saturating_sub(1), builder.config.host_target)
 }
 
+/// Determines how to build a `ToolTarget`, i.e. which compiler should be used to compile it.
+/// The compiler stage is automatically bumped if we need to cross-compile a stage 1 tool.
+pub enum ToolTargetBuildMode {
+    /// Build the tool using rustc that corresponds to the selected CLI stage.
+    Build(TargetSelection),
+    /// Build the tool so that it can be attached to the sysroot of the passed compiler.
+    /// Since we always dist stage 2+, the compiler that builds the tool in this case has to be
+    /// stage 1+.
+    Dist(Compiler),
+}
+
+/// Returns compiler that is able to compile a `ToolTarget` tool with the given `mode`.
+pub(crate) fn get_tool_target_compiler(
+    builder: &Builder<'_>,
+    mode: ToolTargetBuildMode,
+) -> Compiler {
+    let (target, build_compiler_stage) = match mode {
+        ToolTargetBuildMode::Build(target) => {
+            assert!(builder.top_stage > 0);
+            // If we want to build a stage N tool, we need to compile it with stage N-1 rustc
+            (target, builder.top_stage - 1)
+        }
+        ToolTargetBuildMode::Dist(target_compiler) => {
+            assert!(target_compiler.stage > 0);
+            // If we want to dist a stage N rustc, we want to attach stage N tool to it.
+            // And to build that tool, we need to compile it with stage N-1 rustc
+            (target_compiler.host, target_compiler.stage - 1)
+        }
+    };
+
+    let compiler = if builder.host_target == target {
+        builder.compiler(build_compiler_stage, builder.host_target)
+    } else {
+        // If we are cross-compiling a stage 1 tool, we cannot do that with a stage 0 compiler,
+        // so we auto-bump the tool's stage to 2, which means we need a stage 1 compiler.
+        builder.compiler(build_compiler_stage.max(1), builder.host_target)
+    };
+    builder.std(compiler, target);
+    compiler
+}
+
 /// Links a built tool binary with the given `name` from the build directory to the
 /// tools directory.
 fn copy_link_tool_bin(
@@ -451,7 +494,7 @@ macro_rules! bootstrap_tool {
                 let compiletest_wants_stage0 = $tool_name == "compiletest" && builder.config.compiletest_use_stage0_libtest;
 
                 builder.ensure(ToolBuild {
-                    compiler: self.compiler,
+                    build_compiler: self.compiler,
                     target: self.target,
                     tool: $tool_name,
                     mode: if is_unstable && !compiletest_wants_stage0 {
@@ -521,7 +564,6 @@ bootstrap_tool!(
     // rustdoc-gui-test has a crate dependency on compiletest, so it needs the same unstable features.
     RustdocGUITest, "src/tools/rustdoc-gui-test", "rustdoc-gui-test", is_unstable_tool = true, allow_features = COMPILETEST_ALLOW_FEATURES;
     CoverageDump, "src/tools/coverage-dump", "coverage-dump";
-    WasmComponentLd, "src/tools/wasm-component-ld", "wasm-component-ld", is_unstable_tool = true, allow_features = "min_specialization";
     UnicodeTableGenerator, "src/tools/unicode-table-generator", "unicode-table-generator";
     FeaturesStatusDump, "src/tools/features-status-dump", "features-status-dump";
     OptimizedDist, "src/tools/opt-dist", "opt-dist", submodules = &["src/tools/rustc-perf"];
@@ -560,7 +602,7 @@ impl Step for RustcPerf {
         builder.require_submodule("src/tools/rustc-perf", None);
 
         let tool = ToolBuild {
-            compiler: self.compiler,
+            build_compiler: self.compiler,
             target: self.target,
             tool: "collector",
             mode: Mode::ToolBootstrap,
@@ -576,7 +618,7 @@ impl Step for RustcPerf {
         let res = builder.ensure(tool.clone());
         // We also need to symlink the `rustc-fake` binary to the corresponding directory,
         // because `collector` expects it in the same directory.
-        copy_link_tool_bin(builder, tool.compiler, tool.target, tool.mode, "rustc-fake");
+        copy_link_tool_bin(builder, tool.build_compiler, tool.target, tool.mode, "rustc-fake");
 
         res
     }
@@ -620,7 +662,7 @@ impl Step for ErrorIndex {
 
     fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
         builder.ensure(ToolBuild {
-            compiler: self.compiler,
+            build_compiler: self.compiler,
             target: self.compiler.host,
             tool: "error_index_generator",
             mode: Mode::ToolRustc,
@@ -636,7 +678,7 @@ impl Step for ErrorIndex {
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct RemoteTestServer {
-    pub compiler: Compiler,
+    pub build_compiler: Compiler,
     pub target: TargetSelection,
 }
 
@@ -649,17 +691,20 @@ impl Step for RemoteTestServer {
 
     fn make_run(run: RunConfig<'_>) {
         run.builder.ensure(RemoteTestServer {
-            compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.host_target),
+            build_compiler: get_tool_target_compiler(
+                run.builder,
+                ToolTargetBuildMode::Build(run.target),
+            ),
             target: run.target,
         });
     }
 
     fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
         builder.ensure(ToolBuild {
-            compiler: self.compiler,
+            build_compiler: self.build_compiler,
             target: self.target,
             tool: "remote-test-server",
-            mode: Mode::ToolStd,
+            mode: Mode::ToolTarget,
             path: "src/tools/remote-test-server",
             source_type: SourceType::InTree,
             extra_features: Vec::new(),
@@ -668,6 +713,10 @@ impl Step for RemoteTestServer {
             artifact_kind: ToolArtifactKind::Binary,
         })
     }
+
+    fn metadata(&self) -> Option<StepMetadata> {
+        Some(StepMetadata::build("remote-test-server", self.target).built_by(self.build_compiler))
+    }
 }
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
@@ -757,7 +806,7 @@ impl Step for Rustdoc {
 
         let ToolBuildResult { tool_path, build_compiler, target_compiler } =
             builder.ensure(ToolBuild {
-                compiler: target_compiler,
+                build_compiler: target_compiler,
                 target,
                 // Cargo adds a number of paths to the dylib search path on windows, which results in
                 // the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool"
@@ -825,7 +874,7 @@ impl Step for Cargo {
         builder.build.require_submodule("src/tools/cargo", None);
 
         builder.ensure(ToolBuild {
-            compiler: self.compiler,
+            build_compiler: self.compiler,
             target: self.target,
             tool: "cargo",
             mode: Mode::ToolRustc,
@@ -839,17 +888,50 @@ impl Step for Cargo {
     }
 }
 
+/// Represents a built LldWrapper, the `lld-wrapper` tool itself, and a directory
+/// containing a build of LLD.
+#[derive(Clone)]
+pub struct BuiltLldWrapper {
+    tool: ToolBuildResult,
+    lld_dir: PathBuf,
+}
+
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct LldWrapper {
     pub build_compiler: Compiler,
-    pub target_compiler: Compiler,
+    pub target: TargetSelection,
+}
+
+impl LldWrapper {
+    /// Returns `LldWrapper` that should be **used** by the passed compiler.
+    pub fn for_use_by_compiler(builder: &Builder<'_>, target_compiler: Compiler) -> Self {
+        Self {
+            build_compiler: get_tool_target_compiler(
+                builder,
+                ToolTargetBuildMode::Dist(target_compiler),
+            ),
+            target: target_compiler.host,
+        }
+    }
 }
 
 impl Step for LldWrapper {
-    type Output = ToolBuildResult;
+    type Output = BuiltLldWrapper;
+
+    const ONLY_HOSTS: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.never()
+        run.path("src/tools/lld-wrapper")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(LldWrapper {
+            build_compiler: get_tool_target_compiler(
+                run.builder,
+                ToolTargetBuildMode::Build(run.target),
+            ),
+            target: run.target,
+        });
     }
 
     #[cfg_attr(
@@ -858,25 +940,16 @@ impl Step for LldWrapper {
             level = "debug",
             name = "LldWrapper::run",
             skip_all,
-            fields(build_compiler = ?self.build_compiler, target_compiler = ?self.target_compiler),
+            fields(build_compiler = ?self.build_compiler),
         ),
     )]
-    fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
-        if builder.config.dry_run() {
-            return ToolBuildResult {
-                tool_path: Default::default(),
-                build_compiler: self.build_compiler,
-                target_compiler: self.target_compiler,
-            };
-        }
-
-        let target = self.target_compiler.host;
-
-        let tool_result = builder.ensure(ToolBuild {
-            compiler: self.build_compiler,
-            target,
+    fn run(self, builder: &Builder<'_>) -> Self::Output {
+        let lld_dir = builder.ensure(llvm::Lld { target: self.target });
+        let tool = builder.ensure(ToolBuild {
+            build_compiler: self.build_compiler,
+            target: self.target,
             tool: "lld-wrapper",
-            mode: Mode::ToolStd,
+            mode: Mode::ToolTarget,
             path: "src/tools/lld-wrapper",
             source_type: SourceType::InTree,
             extra_features: Vec::new(),
@@ -884,38 +957,110 @@ impl Step for LldWrapper {
             cargo_args: Vec::new(),
             artifact_kind: ToolArtifactKind::Binary,
         });
+        BuiltLldWrapper { tool, lld_dir }
+    }
 
-        let libdir_bin = builder.sysroot_target_bindir(self.target_compiler, target);
-        t!(fs::create_dir_all(&libdir_bin));
+    fn metadata(&self) -> Option<StepMetadata> {
+        Some(StepMetadata::build("LldWrapper", self.target).built_by(self.build_compiler))
+    }
+}
 
-        let lld_install = builder.ensure(llvm::Lld { target });
-        let src_exe = exe("lld", target);
-        let dst_exe = exe("rust-lld", target);
+pub(crate) fn copy_lld_artifacts(
+    builder: &Builder<'_>,
+    lld_wrapper: BuiltLldWrapper,
+    target_compiler: Compiler,
+) {
+    let target = target_compiler.host;
 
+    let libdir_bin = builder.sysroot_target_bindir(target_compiler, target);
+    t!(fs::create_dir_all(&libdir_bin));
+
+    let src_exe = exe("lld", target);
+    let dst_exe = exe("rust-lld", target);
+
+    builder.copy_link(
+        &lld_wrapper.lld_dir.join("bin").join(src_exe),
+        &libdir_bin.join(dst_exe),
+        FileType::Executable,
+    );
+    let self_contained_lld_dir = libdir_bin.join("gcc-ld");
+    t!(fs::create_dir_all(&self_contained_lld_dir));
+
+    for name in crate::LLD_FILE_NAMES {
         builder.copy_link(
-            &lld_install.join("bin").join(src_exe),
-            &libdir_bin.join(dst_exe),
+            &lld_wrapper.tool.tool_path,
+            &self_contained_lld_dir.join(exe(name, target)),
             FileType::Executable,
         );
-        let self_contained_lld_dir = libdir_bin.join("gcc-ld");
-        t!(fs::create_dir_all(&self_contained_lld_dir));
-
-        for name in crate::LLD_FILE_NAMES {
-            builder.copy_link(
-                &tool_result.tool_path,
-                &self_contained_lld_dir.join(exe(name, target)),
-                FileType::Executable,
-            );
+    }
+}
+
+/// Builds the `wasm-component-ld` linker wrapper, which is shipped with rustc to be executed on the
+/// host platform where rustc runs.
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
+pub struct WasmComponentLd {
+    build_compiler: Compiler,
+    target: TargetSelection,
+}
+
+impl WasmComponentLd {
+    /// Returns `WasmComponentLd` that should be **used** by the passed compiler.
+    pub fn for_use_by_compiler(builder: &Builder<'_>, target_compiler: Compiler) -> Self {
+        Self {
+            build_compiler: get_tool_target_compiler(
+                builder,
+                ToolTargetBuildMode::Dist(target_compiler),
+            ),
+            target: target_compiler.host,
         }
+    }
+}
+
+impl Step for WasmComponentLd {
+    type Output = ToolBuildResult;
+
+    const ONLY_HOSTS: bool = true;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.path("src/tools/wasm-component-ld")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(WasmComponentLd {
+            build_compiler: get_tool_target_compiler(
+                run.builder,
+                ToolTargetBuildMode::Build(run.target),
+            ),
+            target: run.target,
+        });
+    }
 
-        tool_result
+    #[cfg_attr(
+        feature = "tracing",
+        instrument(
+            level = "debug",
+            name = "WasmComponentLd::run",
+            skip_all,
+            fields(build_compiler = ?self.build_compiler),
+        ),
+    )]
+    fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
+        builder.ensure(ToolBuild {
+            build_compiler: self.build_compiler,
+            target: self.target,
+            tool: "wasm-component-ld",
+            mode: Mode::ToolTarget,
+            path: "src/tools/wasm-component-ld",
+            source_type: SourceType::InTree,
+            extra_features: vec![],
+            allow_features: "",
+            cargo_args: vec![],
+            artifact_kind: ToolArtifactKind::Binary,
+        })
     }
 
     fn metadata(&self) -> Option<StepMetadata> {
-        Some(
-            StepMetadata::build("LldWrapper", self.target_compiler.host)
-                .built_by(self.build_compiler),
-        )
+        Some(StepMetadata::build("WasmComponentLd", self.target).built_by(self.build_compiler))
     }
 }
 
@@ -948,7 +1093,7 @@ impl Step for RustAnalyzer {
 
     fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
         builder.ensure(ToolBuild {
-            compiler: self.compiler,
+            build_compiler: self.compiler,
             target: self.target,
             tool: "rust-analyzer",
             mode: Mode::ToolRustc,
@@ -993,7 +1138,7 @@ impl Step for RustAnalyzerProcMacroSrv {
 
     fn run(self, builder: &Builder<'_>) -> Option<ToolBuildResult> {
         let tool_result = builder.ensure(ToolBuild {
-            compiler: self.compiler,
+            build_compiler: self.compiler,
             target: self.target,
             tool: "rust-analyzer-proc-macro-srv",
             mode: Mode::ToolRustc,
@@ -1021,8 +1166,35 @@ impl Step for RustAnalyzerProcMacroSrv {
 
 #[derive(Debug, Clone, Hash, PartialEq, Eq)]
 pub struct LlvmBitcodeLinker {
-    pub build_compiler: Compiler,
-    pub target: TargetSelection,
+    build_compiler: Compiler,
+    target: TargetSelection,
+}
+
+impl LlvmBitcodeLinker {
+    /// Returns `LlvmBitcodeLinker` that will be **compiled** by the passed compiler, for the given
+    /// `target`.
+    pub fn from_build_compiler(build_compiler: Compiler, target: TargetSelection) -> Self {
+        Self { build_compiler, target }
+    }
+
+    /// Returns `LlvmBitcodeLinker` that should be **used** by the passed compiler.
+    pub fn from_target_compiler(builder: &Builder<'_>, target_compiler: Compiler) -> Self {
+        Self {
+            build_compiler: get_tool_target_compiler(
+                builder,
+                ToolTargetBuildMode::Dist(target_compiler),
+            ),
+            target: target_compiler.host,
+        }
+    }
+
+    /// Return a compiler that is able to build this tool for the given `target`.
+    pub fn get_build_compiler_for_target(
+        builder: &Builder<'_>,
+        target: TargetSelection,
+    ) -> Compiler {
+        get_tool_target_compiler(builder, ToolTargetBuildMode::Build(target))
+    }
 }
 
 impl Step for LlvmBitcodeLinker {
@@ -1038,9 +1210,7 @@ impl Step for LlvmBitcodeLinker {
 
     fn make_run(run: RunConfig<'_>) {
         run.builder.ensure(LlvmBitcodeLinker {
-            build_compiler: run
-                .builder
-                .compiler(run.builder.top_stage, run.builder.config.host_target),
+            build_compiler: Self::get_build_compiler_for_target(run.builder, run.target),
             target: run.target,
         });
     }
@@ -1051,10 +1221,10 @@ impl Step for LlvmBitcodeLinker {
     )]
     fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
         builder.ensure(ToolBuild {
-            compiler: self.build_compiler,
+            build_compiler: self.build_compiler,
             target: self.target,
             tool: "llvm-bitcode-linker",
-            mode: Mode::ToolRustc,
+            mode: Mode::ToolTarget,
             path: "src/tools/llvm-bitcode-linker",
             source_type: SourceType::InTree,
             extra_features: vec![],
@@ -1239,7 +1409,7 @@ fn run_tool_build_step(
 
     let ToolBuildResult { tool_path, build_compiler, target_compiler } =
         builder.ensure(ToolBuild {
-            compiler,
+            build_compiler: compiler,
             target,
             tool: tool_name,
             mode: Mode::ToolRustc,
@@ -1338,7 +1508,7 @@ impl Step for TestFloatParse {
         let compiler = builder.compiler(builder.top_stage, bootstrap_host);
 
         builder.ensure(ToolBuild {
-            compiler,
+            build_compiler: compiler,
             target: bootstrap_host,
             tool: "test-float-parse",
             mode: Mode::ToolStd,
diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs
index a3b471ca56e..badd5f24dba 100644
--- a/src/bootstrap/src/core/builder/cargo.rs
+++ b/src/bootstrap/src/core/builder/cargo.rs
@@ -537,7 +537,7 @@ impl Builder<'_> {
             }
         }
 
-        let stage = if compiler.stage == 0 && self.local_rebuild {
+        let build_compiler_stage = if compiler.stage == 0 && self.local_rebuild {
             // Assume the local-rebuild rustc already has stage1 features.
             1
         } else {
@@ -545,15 +545,17 @@ impl Builder<'_> {
         };
 
         // We synthetically interpret a stage0 compiler used to build tools as a
-        // "raw" compiler in that it's the exact snapshot we download. Normally
-        // the stage0 build means it uses libraries build by the stage0
-        // compiler, but for tools we just use the precompiled libraries that
-        // we've downloaded
-        let use_snapshot = mode == Mode::ToolBootstrap;
-        assert!(!use_snapshot || stage == 0 || self.local_rebuild);
-
-        let maybe_sysroot = self.sysroot(compiler);
-        let sysroot = if use_snapshot { self.rustc_snapshot_sysroot() } else { &maybe_sysroot };
+        // "raw" compiler in that it's the exact snapshot we download. For things like
+        // ToolRustc, we would have to use the artificial stage0-sysroot compiler instead.
+        let use_snapshot =
+            mode == Mode::ToolBootstrap || (mode == Mode::ToolTarget && build_compiler_stage == 0);
+        assert!(!use_snapshot || build_compiler_stage == 0 || self.local_rebuild);
+
+        let sysroot = if use_snapshot {
+            self.rustc_snapshot_sysroot().to_path_buf()
+        } else {
+            self.sysroot(compiler)
+        };
         let libdir = self.rustc_libdir(compiler);
 
         let sysroot_str = sysroot.as_os_str().to_str().expect("sysroot should be UTF-8");
@@ -562,7 +564,7 @@ impl Builder<'_> {
         }
 
         let mut rustflags = Rustflags::new(target);
-        if stage != 0 {
+        if build_compiler_stage != 0 {
             if let Ok(s) = env::var("CARGOFLAGS_NOT_BOOTSTRAP") {
                 cargo.args(s.split_whitespace());
             }
@@ -604,7 +606,7 @@ impl Builder<'_> {
         // sysroot. Passing this cfg enables raw-dylib support instead, which makes the native
         // library unnecessary. This can be removed when windows-rs enables raw-dylib
         // unconditionally.
-        if let Mode::Rustc | Mode::ToolRustc | Mode::ToolBootstrap = mode {
+        if let Mode::Rustc | Mode::ToolRustc | Mode::ToolBootstrap | Mode::ToolTarget = mode {
             rustflags.arg("--cfg=windows_raw_dylib");
         }
 
@@ -657,7 +659,7 @@ impl Builder<'_> {
         // FIXME(rust-lang/cargo#5754) we shouldn't be using special command arguments
         // to the host invocation here, but rather Cargo should know what flags to pass rustc
         // itself.
-        if stage == 0 {
+        if build_compiler_stage == 0 {
             hostflags.arg("--cfg=bootstrap");
         }
 
@@ -666,7 +668,7 @@ impl Builder<'_> {
         // #71458.
         let mut rustdocflags = rustflags.clone();
         rustdocflags.propagate_cargo_env("RUSTDOCFLAGS");
-        if stage == 0 {
+        if build_compiler_stage == 0 {
             rustdocflags.env("RUSTDOCFLAGS_BOOTSTRAP");
         } else {
             rustdocflags.env("RUSTDOCFLAGS_NOT_BOOTSTRAP");
@@ -677,7 +679,7 @@ impl Builder<'_> {
         }
 
         match mode {
-            Mode::Std | Mode::ToolBootstrap | Mode::ToolStd => {}
+            Mode::Std | Mode::ToolBootstrap | Mode::ToolStd | Mode::ToolTarget => {}
             Mode::Rustc | Mode::Codegen | Mode::ToolRustc => {
                 // Build proc macros both for the host and the target unless proc-macros are not
                 // supported by the target.
@@ -719,7 +721,7 @@ impl Builder<'_> {
         // feature on the rustc side.
         cargo.arg("-Zbinary-dep-depinfo");
         let allow_features = match mode {
-            Mode::ToolBootstrap | Mode::ToolStd => {
+            Mode::ToolBootstrap | Mode::ToolStd | Mode::ToolTarget => {
                 // Restrict the allowed features so we don't depend on nightly
                 // accidentally.
                 //
@@ -833,7 +835,7 @@ impl Builder<'_> {
         cargo
             .env("RUSTBUILD_NATIVE_DIR", self.native_dir(target))
             .env("RUSTC_REAL", self.rustc(compiler))
-            .env("RUSTC_STAGE", stage.to_string())
+            .env("RUSTC_STAGE", build_compiler_stage.to_string())
             .env("RUSTC_SYSROOT", sysroot)
             .env("RUSTC_LIBDIR", libdir)
             .env("RUSTDOC", self.bootstrap_out.join("rustdoc"))
@@ -878,7 +880,7 @@ impl Builder<'_> {
         let debuginfo_level = match mode {
             Mode::Rustc | Mode::Codegen => self.config.rust_debuginfo_level_rustc,
             Mode::Std => self.config.rust_debuginfo_level_std,
-            Mode::ToolBootstrap | Mode::ToolStd | Mode::ToolRustc => {
+            Mode::ToolBootstrap | Mode::ToolStd | Mode::ToolRustc | Mode::ToolTarget => {
                 self.config.rust_debuginfo_level_tools
             }
         };
@@ -890,11 +892,10 @@ impl Builder<'_> {
             profile_var("DEBUG_ASSERTIONS"),
             match mode {
                 Mode::Std => self.config.std_debug_assertions,
-                Mode::Rustc => self.config.rustc_debug_assertions,
-                Mode::Codegen => self.config.rustc_debug_assertions,
-                Mode::ToolBootstrap => self.config.tools_debug_assertions,
-                Mode::ToolStd => self.config.tools_debug_assertions,
-                Mode::ToolRustc => self.config.tools_debug_assertions,
+                Mode::Rustc | Mode::Codegen => self.config.rustc_debug_assertions,
+                Mode::ToolBootstrap | Mode::ToolStd | Mode::ToolRustc | Mode::ToolTarget => {
+                    self.config.tools_debug_assertions
+                }
             }
             .to_string(),
         );
@@ -965,7 +966,11 @@ impl Builder<'_> {
                     cargo.env("CFG_VIRTUAL_RUSTC_DEV_SOURCE_BASE_DIR", map_to);
                 }
             }
-            Mode::Std | Mode::ToolBootstrap | Mode::ToolRustc | Mode::ToolStd => {
+            Mode::Std
+            | Mode::ToolBootstrap
+            | Mode::ToolRustc
+            | Mode::ToolStd
+            | Mode::ToolTarget => {
                 if let Some(ref map_to) =
                     self.build.debuginfo_map_to(GitRepo::Rustc, RemapScheme::NonCompiler)
                 {
@@ -1280,7 +1285,7 @@ impl Builder<'_> {
             };
 
             if let Some(limit) = limit
-                && (stage == 0
+                && (build_compiler_stage == 0
                     || self.config.default_codegen_backend(target).unwrap_or_default() == "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 1b75d00b30e..d73e2bce25b 100644
--- a/src/bootstrap/src/core/builder/mod.rs
+++ b/src/bootstrap/src/core/builder/mod.rs
@@ -963,6 +963,7 @@ impl<'a> Builder<'a> {
                 tool::RemoteTestServer,
                 tool::RemoteTestClient,
                 tool::RustInstaller,
+                tool::FeaturesStatusDump,
                 tool::Cargo,
                 tool::RustAnalyzer,
                 tool::RustAnalyzerProcMacroSrv,
@@ -984,6 +985,8 @@ impl<'a> Builder<'a> {
                 tool::CoverageDump,
                 tool::LlvmBitcodeLinker,
                 tool::RustcPerf,
+                tool::WasmComponentLd,
+                tool::LldWrapper
             ),
             Kind::Clippy => describe!(
                 clippy::Std,
diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index 51a90649692..e60a115b19d 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -712,7 +712,11 @@ mod snapshot {
         [build] llvm <host>
         [build] rustc 0 <host> -> rustc 1 <host>
         ");
+    }
 
+    #[test]
+    fn build_rustc_no_explicit_stage() {
+        let ctx = TestCtx::new();
         insta::assert_snapshot!(
             ctx.config("build")
                 .path("rustc")
@@ -769,11 +773,11 @@ mod snapshot {
         [build] llvm <host>
         [build] rustc 0 <host> -> rustc 1 <host>
         [build] rustc 0 <host> -> LldWrapper 1 <host>
-        [build] rustc 1 <host> -> LlvmBitcodeLinker 2 <host>
+        [build] rustc 0 <host> -> LlvmBitcodeLinker 1 <host>
         [build] rustc 1 <host> -> std 1 <host>
         [build] rustc 1 <host> -> rustc 2 <host>
         [build] rustc 1 <host> -> LldWrapper 2 <host>
-        [build] rustc 2 <host> -> LlvmBitcodeLinker 3 <host>
+        [build] rustc 1 <host> -> LlvmBitcodeLinker 2 <host>
         [build] rustc 2 <host> -> std 2 <host>
         [build] rustdoc 1 <host>
         "
@@ -793,17 +797,17 @@ mod snapshot {
         [build] llvm <host>
         [build] rustc 0 <host> -> rustc 1 <host>
         [build] rustc 0 <host> -> LldWrapper 1 <host>
-        [build] rustc 1 <host> -> LlvmBitcodeLinker 2 <host>
+        [build] rustc 0 <host> -> LlvmBitcodeLinker 1 <host>
         [build] rustc 1 <host> -> std 1 <host>
         [build] rustc 1 <host> -> rustc 2 <host>
         [build] rustc 1 <host> -> LldWrapper 2 <host>
-        [build] rustc 2 <host> -> LlvmBitcodeLinker 3 <host>
+        [build] rustc 1 <host> -> LlvmBitcodeLinker 2 <host>
         [build] rustc 1 <host> -> std 1 <target1>
         [build] rustc 2 <host> -> std 2 <target1>
         [build] llvm <target1>
         [build] rustc 1 <host> -> rustc 2 <target1>
         [build] rustc 1 <host> -> LldWrapper 2 <target1>
-        [build] rustc 2 <target1> -> LlvmBitcodeLinker 3 <target1>
+        [build] rustc 1 <host> -> LlvmBitcodeLinker 2 <target1>
         [build] rustdoc 1 <target1>
         "
         );
@@ -1062,18 +1066,28 @@ mod snapshot {
     fn dist_extended() {
         let ctx = TestCtx::new();
         insta::assert_snapshot!(
-            ctx
-                .config("dist")
-                .args(&["--set", "build.extended=true"])
-                .render_steps(), @r"
+            ctx.config("dist")
+            .args(&[
+                "--set",
+                "build.extended=true",
+                "--set",
+                "rust.llvm-bitcode-linker=true",
+                "--set",
+                "rust.lld=true",
+            ])
+            .render_steps(), @r"
         [build] rustc 0 <host> -> UnstableBookGen 1 <host>
         [build] rustc 0 <host> -> Rustbook 1 <host>
         [build] llvm <host>
         [build] rustc 0 <host> -> rustc 1 <host>
+        [build] rustc 0 <host> -> LldWrapper 1 <host>
         [build] rustc 0 <host> -> WasmComponentLd 1 <host>
+        [build] rustc 0 <host> -> LlvmBitcodeLinker 1 <host>
         [build] rustc 1 <host> -> std 1 <host>
         [build] rustc 1 <host> -> rustc 2 <host>
+        [build] rustc 1 <host> -> LldWrapper 2 <host>
         [build] rustc 1 <host> -> WasmComponentLd 2 <host>
+        [build] rustc 1 <host> -> LlvmBitcodeLinker 2 <host>
         [build] rustdoc 1 <host>
         [doc] std 2 <host> crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,std,sysroot,test,unwind]
         [build] rustc 2 <host> -> std 2 <host>
@@ -1092,7 +1106,6 @@ mod snapshot {
         [build] rustc 0 <host> -> cargo-clippy 1 <host>
         [build] rustc 0 <host> -> miri 1 <host>
         [build] rustc 0 <host> -> cargo-miri 1 <host>
-        [build] rustc 1 <host> -> LlvmBitcodeLinker 2 <host>
         ");
     }
 
@@ -1294,17 +1307,19 @@ mod snapshot {
             ctx.config("check")
                 .path("compiler")
                 .render_steps(), @r"
-        [build] llvm <host>
         [check] rustc 0 <host> -> rustc 1 <host>
         [check] rustc 0 <host> -> cranelift 1 <host>
         [check] rustc 0 <host> -> gcc 1 <host>
         ");
+    }
 
+    #[test]
+    fn check_rustc_no_explicit_stage() {
+        let ctx = TestCtx::new();
         insta::assert_snapshot!(
             ctx.config("check")
                 .path("rustc")
                 .render_steps(), @r"
-        [build] llvm <host>
         [check] rustc 0 <host> -> rustc 1 <host>
         ");
     }
@@ -1324,7 +1339,6 @@ mod snapshot {
                 .path("compiler")
                 .stage(1)
                 .render_steps(), @r"
-        [build] llvm <host>
         [check] rustc 0 <host> -> rustc 1 <host>
         [check] rustc 0 <host> -> cranelift 1 <host>
         [check] rustc 0 <host> -> gcc 1 <host>
@@ -1456,7 +1470,6 @@ mod snapshot {
                 .paths(&["library", "compiler"])
                 .args(&args)
                 .render_steps(), @r"
-        [build] llvm <host>
         [check] rustc 0 <host> -> rustc 1 <host>
         [check] rustc 0 <host> -> cranelift 1 <host>
         [check] rustc 0 <host> -> gcc 1 <host>
@@ -1470,7 +1483,6 @@ mod snapshot {
             ctx.config("check")
                 .path("miri")
                 .render_steps(), @r"
-        [build] llvm <host>
         [check] rustc 0 <host> -> rustc 1 <host>
         [check] rustc 0 <host> -> Miri 1 <host>
         ");
@@ -1491,7 +1503,6 @@ mod snapshot {
                 .path("miri")
                 .stage(1)
                 .render_steps(), @r"
-        [build] llvm <host>
         [check] rustc 0 <host> -> rustc 1 <host>
         [check] rustc 0 <host> -> Miri 1 <host>
         ");
@@ -1544,7 +1555,6 @@ mod snapshot {
             ctx.config("check")
                 .path("rustc_codegen_cranelift")
                 .render_steps(), @r"
-        [build] llvm <host>
         [check] rustc 0 <host> -> rustc 1 <host>
         [check] rustc 0 <host> -> cranelift 1 <host>
         [check] rustc 0 <host> -> gcc 1 <host>
@@ -1558,7 +1568,6 @@ mod snapshot {
             ctx.config("check")
                 .path("rust-analyzer")
                 .render_steps(), @r"
-        [build] llvm <host>
         [check] rustc 0 <host> -> rustc 1 <host>
         [check] rustc 0 <host> -> rust-analyzer 1 <host>
         ");
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 44be51815c7..63aab4d116a 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -253,12 +253,24 @@ pub enum Mode {
     /// These tools are intended to be only executed on the host system that
     /// invokes bootstrap, and they thus cannot be cross-compiled.
     ///
-    /// They are always built using the stage0 compiler, and typically they
+    /// They are always built using the stage0 compiler, and they
     /// can be compiled with stable Rust.
     ///
     /// These tools also essentially do not participate in staging.
     ToolBootstrap,
 
+    /// Build a cross-compilable helper tool. These tools do not depend on unstable features or
+    /// compiler internals, but they might be cross-compilable (so we cannot build them using the
+    /// stage0 compiler, unlike `ToolBootstrap`).
+    ///
+    /// Some of these tools are also shipped in our `dist` archives.
+    /// While we could compile them using the stage0 compiler when not cross-compiling, we instead
+    /// use the in-tree compiler (and std) to build them, so that we can ship e.g. std security
+    /// fixes and avoid depending fully on stage0 for the artifacts that we ship.
+    ///
+    /// This mode is used e.g. for linkers and linker tools invoked by rustc on its host target.
+    ToolTarget,
+
     /// Build a tool which uses the locally built std, placing output in the
     /// "stageN-tools" directory. Its usage is quite rare, mainly used by
     /// compiletest which needs libtest.
@@ -273,11 +285,21 @@ pub enum Mode {
 
 impl Mode {
     pub fn is_tool(&self) -> bool {
-        matches!(self, Mode::ToolBootstrap | Mode::ToolRustc | Mode::ToolStd)
+        match self {
+            Mode::ToolBootstrap | Mode::ToolRustc | Mode::ToolStd | Mode::ToolTarget => true,
+            Mode::Std | Mode::Codegen | Mode::Rustc => false,
+        }
     }
 
     pub fn must_support_dlopen(&self) -> bool {
-        matches!(self, Mode::Std | Mode::Codegen)
+        match self {
+            Mode::Std | Mode::Codegen => true,
+            Mode::ToolBootstrap
+            | Mode::ToolRustc
+            | Mode::ToolStd
+            | Mode::ToolTarget
+            | Mode::Rustc => false,
+        }
     }
 }
 
@@ -802,17 +824,39 @@ impl Build {
     /// stage when running with a particular host compiler.
     ///
     /// The mode indicates what the root directory is for.
-    fn stage_out(&self, compiler: Compiler, mode: Mode) -> PathBuf {
-        let suffix = match mode {
-            Mode::Std => "-std",
-            Mode::Rustc => "-rustc",
-            Mode::Codegen => "-codegen",
-            Mode::ToolBootstrap => {
-                return self.out.join(compiler.host).join("bootstrap-tools");
+    fn stage_out(&self, build_compiler: Compiler, mode: Mode) -> PathBuf {
+        use std::fmt::Write;
+
+        fn bootstrap_tool() -> (Option<u32>, &'static str) {
+            (None, "bootstrap-tools")
+        }
+        fn staged_tool(build_compiler: Compiler) -> (Option<u32>, &'static str) {
+            (Some(build_compiler.stage), "tools")
+        }
+
+        let (stage, suffix) = match mode {
+            Mode::Std => (Some(build_compiler.stage), "std"),
+            Mode::Rustc => (Some(build_compiler.stage), "rustc"),
+            Mode::Codegen => (Some(build_compiler.stage), "codegen"),
+            Mode::ToolBootstrap => bootstrap_tool(),
+            Mode::ToolStd | Mode::ToolRustc => (Some(build_compiler.stage), "tools"),
+            Mode::ToolTarget => {
+                // If we're not cross-compiling (the common case), share the target directory with
+                // bootstrap tools to reuse the build cache.
+                if build_compiler.stage == 0 {
+                    bootstrap_tool()
+                } else {
+                    staged_tool(build_compiler)
+                }
             }
-            Mode::ToolStd | Mode::ToolRustc => "-tools",
         };
-        self.out.join(compiler.host).join(format!("stage{}{}", compiler.stage, suffix))
+        let path = self.out.join(build_compiler.host);
+        let mut dir_name = String::new();
+        if let Some(stage) = stage {
+            write!(dir_name, "stage{stage}-").unwrap();
+        }
+        dir_name.push_str(suffix);
+        path.join(dir_name)
     }
 
     /// Returns the root output directory for all Cargo output in a given stage,
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index f0c52fe3d1c..0a6ebe44b3d 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -172,9 +172,9 @@ try:
 optional:
   # This job is used just to test optional jobs.
   # It will be replaced by tier 2 and tier 3 jobs in the future.
-  - name: optional-mingw-check-1
+  - name: optional-pr-check-1
     env:
-      IMAGE: mingw-check-1
+      IMAGE: pr-check-1
     <<: *job-linux-4c
 
 # Main CI jobs that have to be green to merge a commit into master
diff --git a/src/ci/scripts/install-mingw.sh b/src/ci/scripts/install-mingw.sh
index ad852071f29..ed87628659b 100755
--- a/src/ci/scripts/install-mingw.sh
+++ b/src/ci/scripts/install-mingw.sh
@@ -43,4 +43,9 @@ if isWindows && isKnownToBeMingwBuild; then
     curl -o mingw.7z "${MIRRORS_BASE}/${mingw_archive}"
     7z x -y mingw.7z > /dev/null
     ciCommandAddPath "$(cygpath -m "$(pwd)/${mingw_dir}/bin")"
+
+    # Initialize mingw for the user.
+    # This should be done by github but isn't for some reason.
+    # (see https://github.com/actions/runner-images/issues/12600)
+    /c/msys64/usr/bin/bash -lc ' '
 fi
diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md
index 63aa08c389c..5c3ae359ba0 100644
--- a/src/doc/rustc-dev-guide/src/tests/directives.md
+++ b/src/doc/rustc-dev-guide/src/tests/directives.md
@@ -75,8 +75,10 @@ expectations](ui.md#controlling-passfail-expectations).
 | `check-fail`                | Building (no codegen) should fail           | `ui`, `crashes`                           | N/A             |
 | `build-pass`                | Building should pass                        | `ui`, `crashes`, `codegen`, `incremental` | N/A             |
 | `build-fail`                | Building should fail                        | `ui`, `crashes`                           | N/A             |
-| `run-pass`                  | Running the test binary should pass         | `ui`, `crashes`, `incremental`            | N/A             |
-| `run-fail`                  | Running the test binary should fail         | `ui`, `crashes`                           | N/A             |
+| `run-pass`                  | Program must exit with code `0`             | `ui`, `crashes`, `incremental`            | N/A             |
+| `run-fail`                  | Program must exit with code `1..=127`       | `ui`, `crashes`                           | N/A             |
+| `run-crash`                 | Program must crash                          | `ui`                                      | N/A             |
+| `run-fail-or-crash`         | Program must `run-fail` or `run-crash`      | `ui`                                      | N/A             |
 | `ignore-pass`               | Ignore `--pass` flag                        | `ui`, `crashes`, `codegen`, `incremental` | N/A             |
 | `dont-check-failure-status` | Don't check exact failure status (i.e. `1`) | `ui`, `incremental`                       | N/A             |
 | `failure-status`            | Check                                       | `ui`, `crashes`                           | Any `u16`       |
@@ -203,6 +205,8 @@ settings:
   on `wasm32-unknown-unknown` target because the target does not support the
   `proc-macro` crate type.
 - `needs-target-std` — ignores if target platform does not have std support.
+- `ignore-backends` — ignores the listed backends, separated by whitespace characters.
+- `needs-backends` — only runs the test if current codegen backend is listed.
 
 The following directives will check LLVM support:
 
diff --git a/src/doc/rustc-dev-guide/src/tests/ui.md b/src/doc/rustc-dev-guide/src/tests/ui.md
index 4fce5838b6e..9bfc60e08a6 100644
--- a/src/doc/rustc-dev-guide/src/tests/ui.md
+++ b/src/doc/rustc-dev-guide/src/tests/ui.md
@@ -448,7 +448,7 @@ even run the resulting program. Just add one of the following
   - `//@ build-pass` — compilation and linking should succeed but do
     not run the resulting binary.
   - `//@ run-pass` — compilation should succeed and running the resulting
-    binary should also succeed.
+    binary should make it exit with code 0 which indicates success.
 - Fail directives:
   - `//@ check-fail` — compilation should fail (the codegen phase is skipped).
     This is the default for UI tests.
@@ -457,10 +457,20 @@ even run the resulting program. Just add one of the following
     - First time is to ensure that the compile succeeds without the codegen phase
     - Second time is to ensure that the full compile fails
   - `//@ run-fail` — compilation should succeed, but running the resulting
-    binary should fail.
-
-For `run-pass` and `run-fail` tests, by default the output of the program itself
-is not checked.
+    binary should make it exit with a code in the range `1..=127` which
+    indicates regular failure. On targets without unwind support, crashes
+    are also accepted.
+  - `//@ run-crash` — compilation should succeed, but running the resulting
+    binary should fail with a crash. Crashing is defined as "not exiting with
+    a code in the range `0..=127`". Example on Linux: Termination by `SIGABRT`
+    or `SIGSEGV`. Example on Windows: Exiting with the code for
+    `STATUS_ILLEGAL_INSTRUCTION` (`0xC000001D`).
+  - `//@ run-fail-or-crash` — compilation should succeed, but running the
+    resulting binary should either `run-fail` or `run-crash`. Useful if a test
+    crashes on some targets but just fails on others.
+
+For `run-pass`. `run-fail`, `run-crash` and `run-fail-or-crash` tests, by
+default the output of the program itself is not checked.
 
 If you want to check the output of running the program, include the
 `check-run-results` directive. This will check for a `.run.stderr` and
diff --git a/src/doc/rustc/src/platform-support/xtensa.md b/src/doc/rustc/src/platform-support/xtensa.md
index 994b3adb92e..8592ce7eda9 100644
--- a/src/doc/rustc/src/platform-support/xtensa.md
+++ b/src/doc/rustc/src/platform-support/xtensa.md
@@ -24,4 +24,4 @@ Xtensa targets that support `std` are documented in the [ESP-IDF platform suppor
 
 ## Building the targets
 
-The targets can be built by installing the [Xtensa enabled Rust channel](https://github.com/esp-rs/rust/). See instructions in the [RISC-V and Xtensa Targets section of The Rust on ESP Book](https://docs.esp-rs.org/book/installation/riscv-and-xtensa.html).
+The targets can be built by installing the [Xtensa enabled Rust channel](https://github.com/esp-rs/rust/). See instructions in the [RISC-V and Xtensa Targets section of The Rust on ESP Book](https://docs.espressif.com/projects/rust/book/installation/index.html).
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 09647492d93..5ac5da24299 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -1677,7 +1677,7 @@ impl Type {
         }
     }
 
-    pub(crate) fn generics<'a>(&'a self) -> Option<impl Iterator<Item = &'a Type>> {
+    pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
         match self {
             Type::Path { path, .. } => path.generics(),
             _ => None,
@@ -2227,7 +2227,7 @@ impl Path {
         self.segments.last().map(|seg| &seg.args)
     }
 
-    pub(crate) fn generics<'a>(&'a self) -> Option<impl Iterator<Item = &'a Type>> {
+    pub(crate) fn generics(&self) -> Option<impl Iterator<Item = &Type>> {
         self.segments.last().and_then(|seg| {
             if let GenericArgs::AngleBracketed { ref args, .. } = seg.args {
                 Some(args.iter().filter_map(|arg| match arg {
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index fd1b17b6476..813fdee57e1 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -343,13 +343,11 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
 pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String {
     match n.kind() {
         ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, args: _ }) => {
-            let s = if let Some(def) = def.as_local() {
+            if let Some(def) = def.as_local() {
                 rendered_const(cx.tcx, cx.tcx.hir_body_owned_by(def), def)
             } else {
                 inline::print_inlined_const(cx.tcx, def)
-            };
-
-            s
+            }
         }
         // array lengths are obviously usize
         ty::ConstKind::Value(cv) if *cv.ty.kind() == ty::Uint(ty::UintTy::Usize) => {
diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs
index 9b4d2533954..38ba6b4503d 100644
--- a/src/librustdoc/doctest.rs
+++ b/src/librustdoc/doctest.rs
@@ -632,7 +632,7 @@ fn run_test(
         // the user to exploit nightly-only features on stable
         runner_compiler.env("RUSTC_BOOTSTRAP", "1");
         runner_compiler.args(compiler_args);
-        runner_compiler.args(&["--crate-type=bin", "-o"]).arg(&output_file);
+        runner_compiler.args(["--crate-type=bin", "-o"]).arg(&output_file);
         let mut extern_path = std::ffi::OsString::from(format!(
             "--extern=doctest_bundle_{edition}=",
             edition = doctest.edition
@@ -657,7 +657,7 @@ fn run_test(
         extern_path.push(&output_bundle_file);
         runner_compiler.arg(extern_path);
         runner_compiler.arg(&runner_input_file);
-        if std::fs::write(&runner_input_file, &merged_test_code).is_err() {
+        if std::fs::write(&runner_input_file, merged_test_code).is_err() {
             // If we cannot write this file for any reason, we leave. All combined tests will be
             // tested as standalone tests.
             return Err(TestFailure::CompileError);
diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs
index 96975105ac5..f5ec828187a 100644
--- a/src/librustdoc/doctest/rust.rs
+++ b/src/librustdoc/doctest/rust.rs
@@ -140,7 +140,7 @@ impl HirCollector<'_> {
                 .iter()
                 .filter(|a| a.has_name(sym::attr))
                 .flat_map(|a| a.meta_item_list().unwrap_or_default())
-                .map(|i| pprust::meta_list_item_to_string(i))
+                .map(pprust::meta_list_item_to_string)
             {
                 // Add the additional attributes to the global_crate_attrs vector
                 self.collector.global_crate_attrs.push(attr);
diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs
index 79ff1fa38c3..aa4be4db997 100644
--- a/src/librustdoc/formats/renderer.rs
+++ b/src/librustdoc/formats/renderer.rs
@@ -81,7 +81,7 @@ fn run_format_inner<'tcx, T: FormatRenderer<'tcx>>(
         let _timer =
             prof.generic_activity_with_arg("render_mod_item", item.name.unwrap().to_string());
 
-        cx.mod_item_in(&item)?;
+        cx.mod_item_in(item)?;
         let (clean::StrippedItem(box clean::ModuleItem(ref module))
         | clean::ModuleItem(ref module)) = item.inner.kind
         else {
@@ -99,7 +99,7 @@ fn run_format_inner<'tcx, T: FormatRenderer<'tcx>>(
     } else if let Some(item_name) = item.name
         && !item.is_extern_crate()
     {
-        prof.generic_activity_with_arg("render_item", item_name.as_str()).run(|| cx.item(&item))?;
+        prof.generic_activity_with_arg("render_item", item_name.as_str()).run(|| cx.item(item))?;
     }
     Ok(())
 }
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index b16485107a0..be8a2d511e9 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -114,9 +114,9 @@ impl clean::Generics {
             let real_params =
                 fmt::from_fn(|f| real_params.clone().map(|g| g.print(cx)).joined(", ", f));
             if f.alternate() {
-                write!(f, "<{:#}>", real_params)
+                write!(f, "<{real_params:#}>")
             } else {
-                write!(f, "&lt;{}&gt;", real_params)
+                write!(f, "&lt;{real_params}&gt;")
             }
         })
     }
@@ -594,7 +594,7 @@ pub(crate) fn href_with_root_path(
             }
         }
     };
-    let url_parts = make_href(root_path, shortty, url_parts, &fqp, is_remote);
+    let url_parts = make_href(root_path, shortty, url_parts, fqp, is_remote);
     Ok((url_parts, shortty, fqp.clone()))
 }
 
@@ -1115,7 +1115,7 @@ impl clean::Impl {
                 {
                     let last = ty.last();
                     if f.alternate() {
-                        write!(f, "{}<", last)?;
+                        write!(f, "{last}<")?;
                         self.print_type(inner_type, f, use_absolute, cx)?;
                         write!(f, ">")?;
                     } else {
@@ -1219,7 +1219,7 @@ pub(crate) fn print_params(params: &[clean::Parameter], cx: &Context<'_>) -> imp
             .map(|param| {
                 fmt::from_fn(|f| {
                     if let Some(name) = param.name {
-                        write!(f, "{}: ", name)?;
+                        write!(f, "{name}: ")?;
                     }
                     param.type_.print(cx).fmt(f)
                 })
@@ -1341,7 +1341,7 @@ impl clean::FnDecl {
                     write!(f, "const ")?;
                 }
                 if let Some(name) = param.name {
-                    write!(f, "{}: ", name)?;
+                    write!(f, "{name}: ")?;
                 }
                 param.type_.print(cx).fmt(f)?;
             }
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index b2feee36c93..272180fb990 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -547,7 +547,7 @@ impl<'a> Iterator for TokenIter<'a> {
 fn get_real_ident_class(text: &str, allow_path_keywords: bool) -> Option<Class> {
     let ignore: &[&str] =
         if allow_path_keywords { &["self", "Self", "super", "crate"] } else { &["self", "Self"] };
-    if ignore.iter().any(|k| *k == text) {
+    if ignore.contains(&text) {
         return None;
     }
     Some(match text {
@@ -1159,7 +1159,7 @@ fn string_without_closing_tag<T: Display>(
         return Some("</a>");
     }
     if !open_tag {
-        write!(out, "{}", text_s).unwrap();
+        out.write_str(&text_s).unwrap();
         return None;
     }
     let klass_s = klass.as_html();
diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs
index 50320cb231d..1f92c521d46 100644
--- a/src/librustdoc/html/layout.rs
+++ b/src/librustdoc/html/layout.rs
@@ -132,6 +132,5 @@ pub(crate) fn redirect(url: &str) -> String {
     <script>location.replace("{url}" + location.search + location.hash);</script>
 </body>
 </html>"##,
-        url = url,
     )
 }
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index e41435de29c..4addf2c3c96 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -251,7 +251,7 @@ impl<'a, I: Iterator<Item = Event<'a>>> Iterator for CodeBlocks<'_, 'a, I> {
                     if !parse_result.rust {
                         let added_classes = parse_result.added_classes;
                         let lang_string = if let Some(lang) = parse_result.unknown.first() {
-                            format!("language-{}", lang)
+                            format!("language-{lang}")
                         } else {
                             String::new()
                         };
@@ -999,7 +999,7 @@ impl<'a, 'tcx> TagIterator<'a, 'tcx> {
 
         if let Some((_, c)) = self.inner.next() {
             if c != '=' {
-                self.emit_error(format!("expected `=`, found `{}`", c));
+                self.emit_error(format!("expected `=`, found `{c}`"));
                 return None;
             }
         } else {
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 7b814701a73..5ceb1fc988d 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -193,14 +193,12 @@ impl<'tcx> Context<'tcx> {
         if it.is_stripped()
             && let Some(def_id) = it.def_id()
             && def_id.is_local()
+            && (self.info.is_inside_inlined_module
+                || self.shared.cache.inlined_items.contains(&def_id))
         {
-            if self.info.is_inside_inlined_module
-                || self.shared.cache.inlined_items.contains(&def_id)
-            {
-                // For now we're forced to generate a redirect page for stripped items until
-                // `record_extern_fqn` correctly points to external items.
-                render_redirect_pages = true;
-            }
+            // For now we're forced to generate a redirect page for stripped items until
+            // `record_extern_fqn` correctly points to external items.
+            render_redirect_pages = true;
         }
         let mut title = String::new();
         if !is_module {
@@ -254,40 +252,36 @@ impl<'tcx> Context<'tcx> {
                 &self.shared.style_files,
             )
         } else {
-            if let Some(&(ref names, ty)) = self.cache().paths.get(&it.item_id.expect_def_id()) {
-                if self.current.len() + 1 != names.len()
-                    || self.current.iter().zip(names.iter()).any(|(a, b)| a != b)
-                {
-                    // We checked that the redirection isn't pointing to the current file,
-                    // preventing an infinite redirection loop in the generated
-                    // documentation.
-
-                    let path = fmt::from_fn(|f| {
-                        for name in &names[..names.len() - 1] {
-                            write!(f, "{name}/")?;
-                        }
-                        write!(f, "{}", print_item_path(ty, names.last().unwrap().as_str()))
-                    });
-                    match self.shared.redirections {
-                        Some(ref redirections) => {
-                            let mut current_path = String::new();
-                            for name in &self.current {
-                                current_path.push_str(name.as_str());
-                                current_path.push('/');
-                            }
-                            let _ = write!(
-                                current_path,
-                                "{}",
-                                print_item_path(ty, names.last().unwrap().as_str())
-                            );
-                            redirections.borrow_mut().insert(current_path, path.to_string());
-                        }
-                        None => {
-                            return layout::redirect(&format!(
-                                "{root}{path}",
-                                root = self.root_path()
-                            ));
+            if let Some(&(ref names, ty)) = self.cache().paths.get(&it.item_id.expect_def_id())
+                && (self.current.len() + 1 != names.len()
+                    || self.current.iter().zip(names.iter()).any(|(a, b)| a != b))
+            {
+                // We checked that the redirection isn't pointing to the current file,
+                // preventing an infinite redirection loop in the generated
+                // documentation.
+
+                let path = fmt::from_fn(|f| {
+                    for name in &names[..names.len() - 1] {
+                        write!(f, "{name}/")?;
+                    }
+                    write!(f, "{}", print_item_path(ty, names.last().unwrap().as_str()))
+                });
+                match self.shared.redirections {
+                    Some(ref redirections) => {
+                        let mut current_path = String::new();
+                        for name in &self.current {
+                            current_path.push_str(name.as_str());
+                            current_path.push('/');
                         }
+                        let _ = write!(
+                            current_path,
+                            "{}",
+                            print_item_path(ty, names.last().unwrap().as_str())
+                        );
+                        redirections.borrow_mut().insert(current_path, path.to_string());
+                    }
+                    None => {
+                        return layout::redirect(&format!("{root}{path}", root = self.root_path()));
                     }
                 }
             }
@@ -762,11 +756,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
         // Flush pending errors.
         self.shared.fs.close();
         let nb_errors = self.shared.errors.iter().map(|err| self.tcx().dcx().err(err)).count();
-        if nb_errors > 0 {
-            Err(Error::new(io::Error::new(io::ErrorKind::Other, "I/O error"), ""))
-        } else {
-            Ok(())
-        }
+        if nb_errors > 0 { Err(Error::new(io::Error::other("I/O error"), "")) } else { Ok(()) }
     }
 
     fn mod_item_in(&mut self, item: &clean::Item) -> Result<(), Error> {
@@ -842,7 +832,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             self.info.render_redirect_pages = item.is_stripped();
         }
 
-        let buf = self.render_item(&item, false);
+        let buf = self.render_item(item, false);
         // buf will be empty if the item is stripped and there is no redirect for it
         if !buf.is_empty() {
             let name = item.name.as_ref().unwrap();
@@ -853,7 +843,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             self.shared.fs.write(joint_dst, buf)?;
 
             if !self.info.render_redirect_pages {
-                self.shared.all.borrow_mut().append(full_path(self, &item), &item_type);
+                self.shared.all.borrow_mut().append(full_path(self, item), &item_type);
             }
             // If the item is a macro, redirect from the old macro URL (with !)
             // to the new one (without).
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 2cfc9af39e4..872dbbcd19e 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -1483,10 +1483,10 @@ fn render_deref_methods(
             }
         }
         render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs);
-    } else if let Some(prim) = target.primitive_type() {
-        if let Some(&did) = cache.primitive_locations.get(&prim) {
-            render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs);
-        }
+    } else if let Some(prim) = target.primitive_type()
+        && let Some(&did) = cache.primitive_locations.get(&prim)
+    {
+        render_assoc_items_inner(&mut w, cx, container_item, did, what, derefs);
     }
 }
 
@@ -2058,21 +2058,20 @@ fn render_impl(
         // default items which weren't overridden in the implementation block.
         // We don't emit documentation for default items if they appear in the
         // Implementations on Foreign Types or Implementors sections.
-        if rendering_params.show_default_items {
-            if let Some(t) = trait_
-                && !impl_.is_negative_trait_impl()
-            {
-                render_default_items(
-                    &mut default_impl_items,
-                    &mut impl_items,
-                    cx,
-                    t,
-                    impl_,
-                    &i.impl_item,
-                    render_mode,
-                    rendering_params,
-                )?;
-            }
+        if rendering_params.show_default_items
+            && let Some(t) = trait_
+            && !impl_.is_negative_trait_impl()
+        {
+            render_default_items(
+                &mut default_impl_items,
+                &mut impl_items,
+                cx,
+                t,
+                impl_,
+                &i.impl_item,
+                render_mode,
+                rendering_params,
+            )?;
         }
         if render_mode == RenderMode::Normal {
             let toggled = !(impl_items.is_empty() && default_impl_items.is_empty());
@@ -2570,7 +2569,7 @@ fn collect_paths_for_type(first_ty: &clean::Type, cache: &Cache) -> Vec<String>
         match ty {
             clean::Type::Path { path } => process_path(path.def_id()),
             clean::Type::Tuple(tys) => {
-                work.extend(tys.into_iter());
+                work.extend(tys.iter());
             }
             clean::Type::Slice(ty) => {
                 work.push_back(ty);
diff --git a/src/librustdoc/html/render/ordered_json.rs b/src/librustdoc/html/render/ordered_json.rs
index d1dddfebc83..be51dad1c2b 100644
--- a/src/librustdoc/html/render/ordered_json.rs
+++ b/src/librustdoc/html/render/ordered_json.rs
@@ -25,7 +25,7 @@ impl OrderedJson {
             .into_iter()
             .sorted_unstable_by(|a, b| a.borrow().cmp(b.borrow()))
             .format_with(",", |item, f| f(item.borrow()));
-        Self(format!("[{}]", items))
+        Self(format!("[{items}]"))
     }
 
     pub(crate) fn array_unsorted<T: Borrow<Self>, I: IntoIterator<Item = T>>(items: I) -> Self {
diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs
index 5fbda4797cc..02ee34aaac6 100644
--- a/src/librustdoc/html/render/print_item.rs
+++ b/src/librustdoc/html/render/print_item.rs
@@ -1451,7 +1451,7 @@ 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.cx)
     }
 
     fn document_field(&self, field: &'a clean::Item) -> impl Display {
@@ -1982,16 +1982,14 @@ fn item_constant(
                 w.write_str(";")?;
             }
 
-            if !is_literal {
-                if let Some(value) = &value {
-                    let value_lowercase = value.to_lowercase();
-                    let expr_lowercase = expr.to_lowercase();
+            if !is_literal && let Some(value) = &value {
+                let value_lowercase = value.to_lowercase();
+                let expr_lowercase = expr.to_lowercase();
 
-                    if value_lowercase != expr_lowercase
-                        && value_lowercase.trim_end_matches("i32") != expr_lowercase
-                    {
-                        write!(w, " // {value}", value = Escape(value))?;
-                    }
+                if value_lowercase != expr_lowercase
+                    && value_lowercase.trim_end_matches("i32") != expr_lowercase
+                {
+                    write!(w, " // {value}", value = Escape(value))?;
                 }
             }
             Ok::<(), fmt::Error>(())
@@ -2071,41 +2069,39 @@ fn item_fields(
                 _ => None,
             })
             .peekable();
-        if let None | Some(CtorKind::Fn) = ctor_kind {
-            if fields.peek().is_some() {
-                let title = format!(
-                    "{}{}",
-                    if ctor_kind.is_none() { "Fields" } else { "Tuple Fields" },
-                    document_non_exhaustive_header(it),
-                );
+        if let None | Some(CtorKind::Fn) = ctor_kind
+            && fields.peek().is_some()
+        {
+            let title = format!(
+                "{}{}",
+                if ctor_kind.is_none() { "Fields" } else { "Tuple Fields" },
+                document_non_exhaustive_header(it),
+            );
+            write!(
+                w,
+                "{}",
+                write_section_heading(
+                    &title,
+                    "fields",
+                    Some("fields"),
+                    document_non_exhaustive(it)
+                )
+            )?;
+            for (index, (field, ty)) in fields.enumerate() {
+                let field_name =
+                    field.name.map_or_else(|| index.to_string(), |sym| sym.as_str().to_string());
+                let id = cx.derive_id(format!("{typ}.{field_name}", typ = ItemType::StructField));
                 write!(
                     w,
-                    "{}",
-                    write_section_heading(
-                        &title,
-                        "fields",
-                        Some("fields"),
-                        document_non_exhaustive(it)
-                    )
+                    "<span id=\"{id}\" class=\"{item_type} section-header\">\
+                        <a href=\"#{id}\" class=\"anchor field\">§</a>\
+                        <code>{field_name}: {ty}</code>\
+                    </span>\
+                    {doc}",
+                    item_type = ItemType::StructField,
+                    ty = ty.print(cx),
+                    doc = document(cx, field, Some(it), HeadingOffset::H3),
                 )?;
-                for (index, (field, ty)) in fields.enumerate() {
-                    let field_name = field
-                        .name
-                        .map_or_else(|| index.to_string(), |sym| sym.as_str().to_string());
-                    let id =
-                        cx.derive_id(format!("{typ}.{field_name}", typ = ItemType::StructField));
-                    write!(
-                        w,
-                        "<span id=\"{id}\" class=\"{item_type} section-header\">\
-                            <a href=\"#{id}\" class=\"anchor field\">§</a>\
-                            <code>{field_name}: {ty}</code>\
-                        </span>\
-                        {doc}",
-                        item_type = ItemType::StructField,
-                        ty = ty.print(cx),
-                        doc = document(cx, field, Some(it), HeadingOffset::H3),
-                    )?;
-                }
             }
         }
         Ok(())
diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs
index 80a59fa218c..3c9be29ccc3 100644
--- a/src/librustdoc/html/render/search_index.rs
+++ b/src/librustdoc/html/render/search_index.rs
@@ -116,7 +116,7 @@ pub(crate) fn build_index(
     // Set up alias indexes.
     for (i, item) in cache.search_index.iter().enumerate() {
         for alias in &item.aliases[..] {
-            aliases.entry(alias.as_str().to_lowercase()).or_default().push(i);
+            aliases.entry(alias.to_string()).or_default().push(i);
         }
     }
 
diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs
index 91540e06e33..b9f5ada417c 100644
--- a/src/librustdoc/html/render/sidebar.rs
+++ b/src/librustdoc/html/render/sidebar.rs
@@ -541,7 +541,7 @@ fn sidebar_deref_methods<'a>(
                 .iter()
                 .filter(|i| {
                     i.inner_impl().trait_.is_none()
-                        && real_target.is_doc_subtype_of(&i.inner_impl().for_, &c)
+                        && real_target.is_doc_subtype_of(&i.inner_impl().for_, c)
                 })
                 .flat_map(|i| get_methods(i.inner_impl(), true, used_links, deref_mut, cx.tcx()))
                 .collect::<Vec<_>>();
diff --git a/src/librustdoc/html/render/sorted_template.rs b/src/librustdoc/html/render/sorted_template.rs
index a7b954ab70b..659c5e6093b 100644
--- a/src/librustdoc/html/render/sorted_template.rs
+++ b/src/librustdoc/html/render/sorted_template.rs
@@ -63,7 +63,8 @@ impl<F: FileFormat> fmt::Display for SortedTemplate<F> {
         for (p, fragment) in self.fragments.iter().with_position() {
             let mut f = DeltaWriter { inner: &mut f, delta: 0 };
             let sep = if matches!(p, Position::First | Position::Only) { "" } else { F::SEPARATOR };
-            write!(f, "{}{}", sep, fragment)?;
+            f.write_str(sep)?;
+            f.write_str(fragment)?;
             fragment_lengths.push(f.delta);
         }
         let offset = Offset { start: self.before.len(), fragment_lengths };
diff --git a/src/librustdoc/html/static/js/rustdoc.d.ts b/src/librustdoc/html/static/js/rustdoc.d.ts
index ca2512e5ab6..a9589764547 100644
--- a/src/librustdoc/html/static/js/rustdoc.d.ts
+++ b/src/librustdoc/html/static/js/rustdoc.d.ts
@@ -219,6 +219,8 @@ declare namespace rustdoc {
         crate: string,
         descShard: SearchDescShard,
         id: number,
+        // This is the name of the item. For doc aliases, if you want the name of the aliased
+        // item, take a look at `Row.original.name`.
         name: string,
         normalizedName: string,
         word: string,
@@ -227,6 +229,11 @@ declare namespace rustdoc {
         path: string,
         ty: number,
         type: FunctionSearchType | null,
+        descIndex: number,
+        bitIndex: number,
+        implDisambiguator: String | null,
+        is_alias?: boolean,
+        original?: Row,
     }
 
     /**
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 15cad31f555..2caf214ff73 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -830,7 +830,7 @@ function createQueryElement(query, parserState, name, generics, isInGenerics) {
  */
 function makePrimitiveElement(name, extra) {
     return Object.assign({
-        name: name,
+        name,
         id: null,
         fullPath: [name],
         pathWithoutLast: [],
@@ -1483,6 +1483,7 @@ class DocSearch {
          */
         this.assocTypeIdNameMap = new Map();
         this.ALIASES = new Map();
+        this.FOUND_ALIASES = new Set();
         this.rootPath = rootPath;
         this.searchState = searchState;
 
@@ -2030,6 +2031,8 @@ class DocSearch {
         // normalized names, type signature objects and fingerprints, and aliases.
         id = 0;
 
+        /** @type {Array<[string, { [key: string]: Array<number> },  number]>} */
+        const allAliases = [];
         for (const [crate, crateCorpus] of rawSearchIndex) {
             // a string representing the lengths of each description shard
             // a string representing the list of function types
@@ -2178,10 +2181,10 @@ class DocSearch {
                 paths[i] = { ty, name, path, exactPath, unboxFlag };
             }
 
-            // convert `item*` into an object form, and construct word indices.
+            // Convert `item*` into an object form, and construct word indices.
             //
-            // before any analysis is performed lets gather the search terms to
-            // search against apart from the rest of the data.  This is a quick
+            // Before any analysis is performed, let's gather the search terms to
+            // search against apart from the rest of the data. This is a quick
             // operation that is cached for the life of the page state so that
             // all other search operations have access to this cached data for
             // faster analysis operations
@@ -2269,29 +2272,58 @@ class DocSearch {
             }
 
             if (aliases) {
-                const currentCrateAliases = new Map();
-                this.ALIASES.set(crate, currentCrateAliases);
-                for (const alias_name in aliases) {
-                    if (!Object.prototype.hasOwnProperty.call(aliases, alias_name)) {
-                        continue;
-                    }
-
-                    /** @type{number[]} */
-                    let currentNameAliases;
-                    if (currentCrateAliases.has(alias_name)) {
-                        currentNameAliases = currentCrateAliases.get(alias_name);
-                    } else {
-                        currentNameAliases = [];
-                        currentCrateAliases.set(alias_name, currentNameAliases);
-                    }
-                    for (const local_alias of aliases[alias_name]) {
-                        currentNameAliases.push(local_alias + currentIndex);
-                    }
-                }
+                // We need to add the aliases in `searchIndex` after we finished filling it
+                // to not mess up indexes.
+                allAliases.push([crate, aliases, currentIndex]);
             }
             currentIndex += itemTypes.length;
             this.searchState.descShards.set(crate, descShardList);
         }
+
+        for (const [crate, aliases, index] of allAliases) {
+            for (const [alias_name, alias_refs] of Object.entries(aliases)) {
+                if (!this.ALIASES.has(crate)) {
+                    this.ALIASES.set(crate, new Map());
+                }
+                const word = alias_name.toLowerCase();
+                const crate_alias_map = this.ALIASES.get(crate);
+                if (!crate_alias_map.has(word)) {
+                    crate_alias_map.set(word, []);
+                }
+                const aliases_map = crate_alias_map.get(word);
+
+                const normalizedName = word.indexOf("_") === -1 ? word : word.replace(/_/g, "");
+                for (const alias of alias_refs) {
+                    const originalIndex = alias + index;
+                    const original = searchIndex[originalIndex];
+                    /** @type {rustdoc.Row} */
+                    const row = {
+                        crate,
+                        name: alias_name,
+                        normalizedName,
+                        is_alias: true,
+                        ty: original.ty,
+                        type: original.type,
+                        paramNames: [],
+                        word,
+                        id,
+                        parent: undefined,
+                        original,
+                        path: "",
+                        implDisambiguator: original.implDisambiguator,
+                        // Needed to load the description of the original item.
+                        // @ts-ignore
+                        descShard: original.descShard,
+                        descIndex: original.descIndex,
+                        bitIndex: original.bitIndex,
+                    };
+                    aliases_map.push(row);
+                    this.nameTrie.insert(normalizedName, id, this.tailTable);
+                    id += 1;
+                    searchIndex.push(row);
+                }
+            }
+        }
         // Drop the (rather large) hash table used for reusing function items
         this.TYPES_POOL = new Map();
         return searchIndex;
@@ -2536,6 +2568,8 @@ class DocSearch {
             parsedQuery.elems.reduce((acc, next) => acc + next.pathLast.length, 0) +
             parsedQuery.returned.reduce((acc, next) => acc + next.pathLast.length, 0);
         const maxEditDistance = Math.floor(queryLen / 3);
+        // We reinitialize the `FOUND_ALIASES` map.
+        this.FOUND_ALIASES.clear();
 
         /**
          * @type {Map<string, number>}
@@ -2695,6 +2729,10 @@ class DocSearch {
         const buildHrefAndPath = item => {
             let displayPath;
             let href;
+            if (item.is_alias) {
+                this.FOUND_ALIASES.add(item.word);
+                item = item.original;
+            }
             const type = itemTypes[item.ty];
             const name = item.name;
             let path = item.path;
@@ -3198,8 +3236,7 @@ class DocSearch {
                 result.item = this.searchIndex[result.id];
                 result.word = this.searchIndex[result.id].word;
                 if (isReturnTypeQuery) {
-                    // we are doing a return-type based search,
-                    // deprioritize "clone-like" results,
+                    // We are doing a return-type based search, deprioritize "clone-like" results,
                     // ie. functions that also take the queried type as an argument.
                     const resultItemType = result.item && result.item.type;
                     if (!resultItemType) {
@@ -4259,28 +4296,13 @@ class DocSearch {
             return false;
         }
 
-        // this does not yet have a type in `rustdoc.d.ts`.
-        // @ts-expect-error
-        function createAliasFromItem(item) {
-            return {
-                crate: item.crate,
-                name: item.name,
-                path: item.path,
-                descShard: item.descShard,
-                descIndex: item.descIndex,
-                exactPath: item.exactPath,
-                ty: item.ty,
-                parent: item.parent,
-                type: item.type,
-                is_alias: true,
-                bitIndex: item.bitIndex,
-                implDisambiguator: item.implDisambiguator,
-            };
-        }
-
         // @ts-expect-error
         const handleAliases = async(ret, query, filterCrates, currentCrate) => {
             const lowerQuery = query.toLowerCase();
+            if (this.FOUND_ALIASES.has(lowerQuery)) {
+                return;
+            }
+            this.FOUND_ALIASES.add(lowerQuery);
             // We separate aliases and crate aliases because we want to have current crate
             // aliases to be before the others in the displayed results.
             // @ts-expect-error
@@ -4292,7 +4314,7 @@ class DocSearch {
                     && this.ALIASES.get(filterCrates).has(lowerQuery)) {
                     const query_aliases = this.ALIASES.get(filterCrates).get(lowerQuery);
                     for (const alias of query_aliases) {
-                        aliases.push(createAliasFromItem(this.searchIndex[alias]));
+                        aliases.push(alias);
                     }
                 }
             } else {
@@ -4302,7 +4324,7 @@ class DocSearch {
                         const pushTo = crate === currentCrate ? crateAliases : aliases;
                         const query_aliases = crateAliasesIndex.get(lowerQuery);
                         for (const alias of query_aliases) {
-                            pushTo.push(createAliasFromItem(this.searchIndex[alias]));
+                            pushTo.push(alias);
                         }
                     }
                 }
@@ -4310,9 +4332,9 @@ class DocSearch {
 
             // @ts-expect-error
             const sortFunc = (aaa, bbb) => {
-                if (aaa.path < bbb.path) {
+                if (aaa.original.path < bbb.original.path) {
                     return 1;
-                } else if (aaa.path === bbb.path) {
+                } else if (aaa.original.path === bbb.original.path) {
                     return 0;
                 }
                 return -1;
@@ -4322,20 +4344,9 @@ class DocSearch {
             aliases.sort(sortFunc);
 
             // @ts-expect-error
-            const fetchDesc = alias => {
-                // @ts-expect-error
-                return this.searchIndexEmptyDesc.get(alias.crate).contains(alias.bitIndex) ?
-                    "" : this.searchState.loadDesc(alias);
-            };
-            const [crateDescs, descs] = await Promise.all([
-                // @ts-expect-error
-                Promise.all(crateAliases.map(fetchDesc)),
-                Promise.all(aliases.map(fetchDesc)),
-            ]);
-
-            // @ts-expect-error
             const pushFunc = alias => {
-                alias.alias = query;
+                // Cloning `alias` to prevent its fields to be updated.
+                alias = {...alias};
                 const res = buildHrefAndPath(alias);
                 alias.displayPath = pathSplitter(res[0]);
                 alias.fullPath = alias.displayPath + alias.name;
@@ -4347,16 +4358,8 @@ class DocSearch {
                 }
             };
 
-            aliases.forEach((alias, i) => {
-                // @ts-expect-error
-                alias.desc = descs[i];
-            });
             aliases.forEach(pushFunc);
             // @ts-expect-error
-            crateAliases.forEach((alias, i) => {
-                alias.desc = crateDescs[i];
-            });
-            // @ts-expect-error
             crateAliases.forEach(pushFunc);
         };
 
@@ -4802,7 +4805,7 @@ async function addTab(array, query, display) {
         output.className = "search-results " + extraClass;
 
         const lis = Promise.all(array.map(async item => {
-            const name = item.name;
+            const name = item.is_alias ? item.original.name : item.name;
             const type = itemTypes[item.ty];
             const longType = longItemTypes[item.ty];
             const typeName = longType.length !== 0 ? `${longType}` : "?";
@@ -4822,7 +4825,7 @@ async function addTab(array, query, display) {
             let alias = " ";
             if (item.is_alias) {
                 alias = ` <div class="alias">\
-<b>${item.alias}</b><i class="grey">&nbsp;- see&nbsp;</i>\
+<b>${item.name}</b><i class="grey">&nbsp;- see&nbsp;</i>\
 </div>`;
             }
             resultName.insertAdjacentHTML(
@@ -5201,6 +5204,7 @@ function registerSearchEvents() {
         if (searchState.input.value.length === 0) {
             searchState.hideResults();
         } else {
+            // @ts-ignore
             searchState.timeout = setTimeout(search, 500);
         }
     };
@@ -5842,8 +5846,8 @@ Lev1TParametricDescription.prototype.offsetIncrs3 = /*2 bits per value */ new In
 // be called ONLY when the whole file has been parsed and loaded.
 
 // @ts-expect-error
-function initSearch(searchIndx) {
-    rawSearchIndex = searchIndx;
+function initSearch(searchIndex) {
+    rawSearchIndex = searchIndex;
     if (typeof window !== "undefined") {
         // @ts-expect-error
         docSearch = new DocSearch(rawSearchIndex, ROOT_PATH, searchState);
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 0a84d8caa30..08bc0bb1950 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -50,7 +50,7 @@ impl JsonRenderer<'_> {
         let span = item.span(self.tcx);
         let visibility = item.visibility(self.tcx);
         let clean::ItemInner { name, item_id, .. } = *item.inner;
-        let id = self.id_from_item(&item);
+        let id = self.id_from_item(item);
         let inner = match item.kind {
             clean::KeywordItem => return None,
             clean::StrippedItem(ref inner) => {
@@ -86,14 +86,14 @@ impl JsonRenderer<'_> {
         items
             .iter()
             .filter(|i| !i.is_stripped() && !i.is_keyword())
-            .map(|i| self.id_from_item(&i))
+            .map(|i| self.id_from_item(i))
             .collect()
     }
 
     fn ids_keeping_stripped(&self, items: &[clean::Item]) -> Vec<Option<Id>> {
         items
             .iter()
-            .map(|i| (!i.is_stripped() && !i.is_keyword()).then(|| self.id_from_item(&i)))
+            .map(|i| (!i.is_stripped() && !i.is_keyword()).then(|| self.id_from_item(i)))
             .collect()
     }
 }
@@ -358,12 +358,12 @@ impl FromClean<clean::Struct> for Struct {
         let clean::Struct { ctor_kind, generics, fields } = struct_;
 
         let kind = match ctor_kind {
-            Some(CtorKind::Fn) => StructKind::Tuple(renderer.ids_keeping_stripped(&fields)),
+            Some(CtorKind::Fn) => StructKind::Tuple(renderer.ids_keeping_stripped(fields)),
             Some(CtorKind::Const) => {
                 assert!(fields.is_empty());
                 StructKind::Unit
             }
-            None => StructKind::Plain { fields: renderer.ids(&fields), has_stripped_fields },
+            None => StructKind::Plain { fields: renderer.ids(fields), has_stripped_fields },
         };
 
         Struct {
@@ -381,7 +381,7 @@ impl FromClean<clean::Union> for Union {
         Union {
             generics: generics.into_json(renderer),
             has_stripped_fields,
-            fields: renderer.ids(&fields),
+            fields: renderer.ids(fields),
             impls: Vec::new(), // Added in JsonRenderer::item
         }
     }
@@ -659,7 +659,7 @@ impl FromClean<clean::FnDecl> for FunctionSignature {
         let clean::FnDecl { inputs, output, c_variadic } = decl;
         FunctionSignature {
             inputs: inputs
-                .into_iter()
+                .iter()
                 .map(|param| {
                     // `_` is the most sensible name for missing param names.
                     let name = param.name.unwrap_or(kw::Underscore).to_string();
@@ -684,7 +684,7 @@ impl FromClean<clean::Trait> for Trait {
             is_auto,
             is_unsafe,
             is_dyn_compatible,
-            items: renderer.ids(&items),
+            items: renderer.ids(items),
             generics: generics.into_json(renderer),
             bounds: bounds.into_json(renderer),
             implementations: Vec::new(), // Added in JsonRenderer::item
@@ -727,7 +727,7 @@ impl FromClean<clean::Impl> for Impl {
                 .collect(),
             trait_: trait_.into_json(renderer),
             for_: for_.into_json(renderer),
-            items: renderer.ids(&items),
+            items: renderer.ids(items),
             is_negative,
             is_synthetic,
             blanket_impl: blanket_impl.map(|x| x.into_json(renderer)),
@@ -770,7 +770,7 @@ impl FromClean<clean::Variant> for Variant {
 
         let kind = match &variant.kind {
             CLike => VariantKind::Plain,
-            Tuple(fields) => VariantKind::Tuple(renderer.ids_keeping_stripped(&fields)),
+            Tuple(fields) => VariantKind::Tuple(renderer.ids_keeping_stripped(fields)),
             Struct(s) => VariantKind::Struct {
                 has_stripped_fields: s.has_stripped_entries(),
                 fields: renderer.ids(&s.fields),
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index 600a4b429f3..760e48baffa 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -133,7 +133,7 @@ fn target(sess: &rustc_session::Session) -> types::Target {
     let feature_stability: FxHashMap<&str, Stability> = sess
         .target
         .rust_target_features()
-        .into_iter()
+        .iter()
         .copied()
         .map(|(name, stability, _)| (name, stability))
         .collect();
@@ -143,7 +143,7 @@ fn target(sess: &rustc_session::Session) -> types::Target {
         target_features: sess
             .target
             .rust_target_features()
-            .into_iter()
+            .iter()
             .copied()
             .filter(|(_, stability, _)| {
                 // Describe only target features which the user can toggle
@@ -157,7 +157,7 @@ fn target(sess: &rustc_session::Session) -> types::Target {
                         _ => None,
                     },
                     implies_features: implied_features
-                        .into_iter()
+                        .iter()
                         .copied()
                         .filter(|name| {
                             // Imply only target features which the user can toggle
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index ca6f67eb6df..5a9aa2a94c8 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -274,7 +274,7 @@ impl From<DiagnosticInfo<'_>> for OwnedDiagnosticInfo {
 }
 
 impl OwnedDiagnosticInfo {
-    pub(crate) fn into_info(&self) -> DiagnosticInfo<'_> {
+    pub(crate) fn as_info(&self) -> DiagnosticInfo<'_> {
         DiagnosticInfo {
             item: &self.item,
             ori_link: &self.ori_link,
@@ -1177,7 +1177,7 @@ impl LinkCollector<'_, '_> {
                     // Primitive types are always valid.
                     Res::Primitive(_) => true,
                 });
-                let diag_info = info.diag_info.into_info();
+                let diag_info = info.diag_info.as_info();
                 match info.resolved.len() {
                     1 => {
                         let (res, fragment) = info.resolved.pop().unwrap();
@@ -1243,17 +1243,16 @@ impl LinkCollector<'_, '_> {
             disambiguator,
             None | Some(Disambiguator::Namespace(Namespace::TypeNS) | Disambiguator::Primitive)
         ) && !matches!(res, Res::Primitive(_))
+            && let Some(prim) = resolve_primitive(path_str, TypeNS)
         {
-            if let Some(prim) = resolve_primitive(path_str, TypeNS) {
-                // `prim@char`
-                if matches!(disambiguator, Some(Disambiguator::Primitive)) {
-                    res = prim;
-                } else {
-                    // `[char]` when a `char` module is in scope
-                    let candidates = &[(res, res.def_id(self.cx.tcx)), (prim, None)];
-                    ambiguity_error(self.cx, &diag_info, path_str, candidates, true);
-                    return None;
-                }
+            // `prim@char`
+            if matches!(disambiguator, Some(Disambiguator::Primitive)) {
+                res = prim;
+            } else {
+                // `[char]` when a `char` module is in scope
+                let candidates = &[(res, res.def_id(self.cx.tcx)), (prim, None)];
+                ambiguity_error(self.cx, &diag_info, path_str, candidates, true);
+                return None;
             }
         }
 
@@ -2233,7 +2232,7 @@ fn ambiguity_error(
     // proc macro can exist in multiple namespaces at once, so we need to compare `DefIds`
     //  to remove the candidate in the fn namespace.
     let mut possible_proc_macro_id = None;
-    let is_proc_macro_crate = cx.tcx.crate_types() == &[CrateType::ProcMacro];
+    let is_proc_macro_crate = cx.tcx.crate_types() == [CrateType::ProcMacro];
     let mut kinds = candidates
         .iter()
         .map(|(res, def_id)| {
diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs
index 5757b6a9740..e69cf87f957 100644
--- a/src/librustdoc/passes/lint/redundant_explicit_links.rs
+++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs
@@ -93,14 +93,14 @@ fn check_redundant_explicit_link<'md>(
         if let Event::Start(Tag::Link { link_type, dest_url, .. }) = event {
             let link_data = collect_link_data(&mut offset_iter);
 
-            if let Some(resolvable_link) = link_data.resolvable_link.as_ref() {
-                if &link_data.display_link.replace('`', "") != resolvable_link {
-                    // Skips if display link does not match to actual
-                    // resolvable link, usually happens if display link
-                    // has several segments, e.g.
-                    // [this is just an `Option`](Option)
-                    continue;
-                }
+            if let Some(resolvable_link) = link_data.resolvable_link.as_ref()
+                && &link_data.display_link.replace('`', "") != resolvable_link
+            {
+                // Skips if display link does not match to actual
+                // resolvable link, usually happens if display link
+                // has several segments, e.g.
+                // [this is just an `Option`](Option)
+                continue;
             }
 
             let explicit_link = dest_url.to_string();
diff --git a/src/librustdoc/passes/strip_aliased_non_local.rs b/src/librustdoc/passes/strip_aliased_non_local.rs
index b53e3b4e3d7..bb13308e6c2 100644
--- a/src/librustdoc/passes/strip_aliased_non_local.rs
+++ b/src/librustdoc/passes/strip_aliased_non_local.rs
@@ -47,13 +47,11 @@ impl DocFolder for NonLocalStripper<'_> {
         // FIXME(#125009): Not-local should probably consider same Cargo workspace
         if let Some(def_id) = i.def_id()
             && !def_id.is_local()
-        {
-            if i.is_doc_hidden()
+            && (i.is_doc_hidden()
                 // Default to *not* stripping items with inherited visibility.
-                || i.visibility(self.tcx).is_some_and(|viz| viz != Visibility::Public)
-            {
-                return Some(strip_item(i));
-            }
+                || i.visibility(self.tcx).is_some_and(|viz| viz != Visibility::Public))
+        {
+            return Some(strip_item(i));
         }
 
         Some(self.fold_item_recur(i))
diff --git a/src/llvm-project b/src/llvm-project
-Subproject d3c793b025645a4565ac59aceb30d2d116ff1a4
+Subproject e8a2ffcf322f45b8dce82c65ab27a3e2430a6b5
diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs
index 33da1a25db1..12084fa0b15 100644
--- a/src/tools/compiletest/src/common.rs
+++ b/src/tools/compiletest/src/common.rs
@@ -88,11 +88,37 @@ string_enum! {
     }
 }
 
+string_enum! {
+    #[derive(Clone, Copy, PartialEq, Debug, Hash)]
+    pub enum RunResult {
+        Pass => "run-pass",
+        Fail => "run-fail",
+        Crash => "run-crash",
+    }
+}
+
+#[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
+pub enum RunFailMode {
+    /// Running the program must make it exit with a regular failure exit code
+    /// in the range `1..=127`. If the program is terminated by e.g. a signal
+    /// the test will fail.
+    Fail,
+    /// Running the program must result in a crash, e.g. by `SIGABRT` or
+    /// `SIGSEGV` on Unix or on Windows by having an appropriate NTSTATUS high
+    /// bit in the exit code.
+    Crash,
+    /// Running the program must either fail or crash. Useful for e.g. sanitizer
+    /// tests since some sanitizer implementations exit the process with code 1
+    /// to in the face of memory errors while others abort (crash) the process
+    /// in the face of memory errors.
+    FailOrCrash,
+}
+
 #[derive(Copy, Clone, Debug, PartialEq, PartialOrd)]
 pub enum FailMode {
     Check,
     Build,
-    Run,
+    Run(RunFailMode),
 }
 
 string_enum! {
@@ -149,6 +175,36 @@ pub enum Sanitizer {
     Hwaddress,
 }
 
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub enum CodegenBackend {
+    Cranelift,
+    Gcc,
+    Llvm,
+}
+
+impl<'a> TryFrom<&'a str> for CodegenBackend {
+    type Error = &'static str;
+
+    fn try_from(value: &'a str) -> Result<Self, Self::Error> {
+        match value.to_lowercase().as_str() {
+            "cranelift" => Ok(Self::Cranelift),
+            "gcc" => Ok(Self::Gcc),
+            "llvm" => Ok(Self::Llvm),
+            _ => Err("unknown backend"),
+        }
+    }
+}
+
+impl CodegenBackend {
+    pub fn as_str(self) -> &'static str {
+        match self {
+            Self::Cranelift => "cranelift",
+            Self::Gcc => "gcc",
+            Self::Llvm => "llvm",
+        }
+    }
+}
+
 /// Configuration for `compiletest` *per invocation*.
 ///
 /// In terms of `bootstrap`, this means that `./x test tests/ui tests/run-make` actually correspond
@@ -625,6 +681,9 @@ pub struct Config {
     /// need `core` stubs in cross-compilation scenarios that do not otherwise want/need to
     /// `-Zbuild-std`. Used in e.g. ABI tests.
     pub minicore_path: Utf8PathBuf,
+
+    /// Current codegen backend used.
+    pub codegen_backend: CodegenBackend,
 }
 
 impl Config {
@@ -727,6 +786,7 @@ impl Config {
             profiler_runtime: Default::default(),
             diff_command: Default::default(),
             minicore_path: Default::default(),
+            codegen_backend: CodegenBackend::Llvm,
         }
     }
 
diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs
index 93133ea0bfd..1397c87ab07 100644
--- a/src/tools/compiletest/src/directives.rs
+++ b/src/tools/compiletest/src/directives.rs
@@ -9,7 +9,7 @@ use camino::{Utf8Path, Utf8PathBuf};
 use semver::Version;
 use tracing::*;
 
-use crate::common::{Config, Debugger, FailMode, PassMode, TestMode};
+use crate::common::{CodegenBackend, Config, Debugger, FailMode, PassMode, RunFailMode, TestMode};
 use crate::debuggers::{extract_cdb_version, extract_gdb_version};
 use crate::directives::auxiliary::{AuxProps, parse_and_update_aux};
 use crate::directives::needs::CachedNeedsConditions;
@@ -654,7 +654,13 @@ impl TestProps {
             Some(FailMode::Build)
         } else if config.parse_name_directive(ln, "run-fail") {
             check_ui("run");
-            Some(FailMode::Run)
+            Some(FailMode::Run(RunFailMode::Fail))
+        } else if config.parse_name_directive(ln, "run-crash") {
+            check_ui("run");
+            Some(FailMode::Run(RunFailMode::Crash))
+        } else if config.parse_name_directive(ln, "run-fail-or-crash") {
+            check_ui("run");
+            Some(FailMode::Run(RunFailMode::FailOrCrash))
         } else {
             None
         };
@@ -812,6 +818,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "ignore-arm-unknown-linux-musleabihf",
     "ignore-auxiliary",
     "ignore-avr",
+    "ignore-backends",
     "ignore-beta",
     "ignore-cdb",
     "ignore-compare-mode-next-solver",
@@ -901,6 +908,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "min-llvm-version",
     "min-system-llvm-version",
     "needs-asm-support",
+    "needs-backends",
     "needs-crate-type",
     "needs-deterministic-layouts",
     "needs-dlltool",
@@ -1007,7 +1015,9 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
     "regex-error-pattern",
     "remap-src-base",
     "revisions",
+    "run-crash",
     "run-fail",
+    "run-fail-or-crash",
     "run-flags",
     "run-pass",
     "run-rustfix",
@@ -1661,6 +1671,8 @@ pub(crate) fn make_test_description<R: Read>(
             decision!(cfg::handle_only(config, ln));
             decision!(needs::handle_needs(&cache.needs, config, ln));
             decision!(ignore_llvm(config, path, ln));
+            decision!(ignore_backends(config, path, ln));
+            decision!(needs_backends(config, path, ln));
             decision!(ignore_cdb(config, ln));
             decision!(ignore_gdb(config, ln));
             decision!(ignore_lldb(config, ln));
@@ -1787,6 +1799,49 @@ fn ignore_lldb(config: &Config, line: &str) -> IgnoreDecision {
     IgnoreDecision::Continue
 }
 
+fn ignore_backends(config: &Config, path: &Utf8Path, line: &str) -> IgnoreDecision {
+    if let Some(backends_to_ignore) = config.parse_name_value_directive(line, "ignore-backends") {
+        for backend in backends_to_ignore.split_whitespace().map(|backend| {
+            match CodegenBackend::try_from(backend) {
+                Ok(backend) => backend,
+                Err(error) => {
+                    panic!("Invalid ignore-backends value `{backend}` in `{path}`: {error}")
+                }
+            }
+        }) {
+            if config.codegen_backend == backend {
+                return IgnoreDecision::Ignore {
+                    reason: format!("{} backend is marked as ignore", backend.as_str()),
+                };
+            }
+        }
+    }
+    IgnoreDecision::Continue
+}
+
+fn needs_backends(config: &Config, path: &Utf8Path, line: &str) -> IgnoreDecision {
+    if let Some(needed_backends) = config.parse_name_value_directive(line, "needs-backends") {
+        if !needed_backends
+            .split_whitespace()
+            .map(|backend| match CodegenBackend::try_from(backend) {
+                Ok(backend) => backend,
+                Err(error) => {
+                    panic!("Invalid needs-backends value `{backend}` in `{path}`: {error}")
+                }
+            })
+            .any(|backend| config.codegen_backend == backend)
+        {
+            return IgnoreDecision::Ignore {
+                reason: format!(
+                    "{} backend is not part of required backends",
+                    config.codegen_backend.as_str()
+                ),
+            };
+        }
+    }
+    IgnoreDecision::Continue
+}
+
 fn ignore_llvm(config: &Config, path: &Utf8Path, line: &str) -> IgnoreDecision {
     if let Some(needed_components) =
         config.parse_name_value_directive(line, "needs-llvm-components")
diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs
index f3b3605a120..41bed8ed8a0 100644
--- a/src/tools/compiletest/src/lib.rs
+++ b/src/tools/compiletest/src/lib.rs
@@ -39,7 +39,7 @@ use walkdir::WalkDir;
 
 use self::directives::{EarlyProps, make_test_description};
 use crate::common::{
-    CompareMode, Config, Debugger, PassMode, TestMode, TestPaths, UI_EXTENSIONS,
+    CodegenBackend, CompareMode, Config, Debugger, PassMode, TestMode, TestPaths, UI_EXTENSIONS,
     expected_output_path, output_base_dir, output_relative_path,
 };
 use crate::directives::DirectivesCache;
@@ -203,6 +203,12 @@ pub fn parse_config(args: Vec<String>) -> Config {
             "debugger",
             "only test a specific debugger in debuginfo tests",
             "gdb | lldb | cdb",
+        )
+        .optopt(
+            "",
+            "codegen-backend",
+            "the codegen backend currently used",
+            "CODEGEN BACKEND NAME",
         );
 
     let (argv0, args_) = args.split_first().unwrap();
@@ -264,6 +270,15 @@ pub fn parse_config(args: Vec<String>) -> Config {
             || directives::extract_llvm_version_from_binary(&matches.opt_str("llvm-filecheck")?),
         );
 
+    let codegen_backend = match matches.opt_str("codegen-backend").as_deref() {
+        Some(backend) => match CodegenBackend::try_from(backend) {
+            Ok(backend) => backend,
+            Err(error) => panic!("invalid value `{backend}` for `--codegen-backend`: {error}"),
+        },
+        // By default, it's always llvm.
+        None => CodegenBackend::Llvm,
+    };
+
     let run_ignored = matches.opt_present("ignored");
     let with_rustc_debug_assertions = matches.opt_present("with-rustc-debug-assertions");
     let with_std_debug_assertions = matches.opt_present("with-std-debug-assertions");
@@ -449,6 +464,8 @@ pub fn parse_config(args: Vec<String>) -> Config {
         diff_command: matches.opt_str("compiletest-diff-tool"),
 
         minicore_path: opt_path(matches, "minicore-path"),
+
+        codegen_backend,
     }
 }
 
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index cb8f593c9df..f66d4f98f1f 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -16,8 +16,8 @@ use regex::{Captures, Regex};
 use tracing::*;
 
 use crate::common::{
-    CompareMode, Config, Debugger, FailMode, PassMode, TestMode, TestPaths, TestSuite,
-    UI_EXTENSIONS, UI_FIXED, UI_RUN_STDERR, UI_RUN_STDOUT, UI_STDERR, UI_STDOUT, UI_SVG,
+    CompareMode, Config, Debugger, FailMode, PassMode, RunFailMode, RunResult, TestMode, TestPaths,
+    TestSuite, UI_EXTENSIONS, UI_FIXED, UI_RUN_STDERR, UI_RUN_STDOUT, UI_STDERR, UI_STDOUT, UI_SVG,
     UI_WINDOWS_SVG, expected_output_path, incremental_dir, output_base_dir, output_base_name,
     output_testname_unique,
 };
@@ -282,7 +282,8 @@ impl<'test> TestCx<'test> {
     fn should_run(&self, pm: Option<PassMode>) -> WillExecute {
         let test_should_run = match self.config.mode {
             TestMode::Ui
-                if pm == Some(PassMode::Run) || self.props.fail_mode == Some(FailMode::Run) =>
+                if pm == Some(PassMode::Run)
+                    || matches!(self.props.fail_mode, Some(FailMode::Run(_))) =>
             {
                 true
             }
diff --git a/src/tools/compiletest/src/runtest/ui.rs b/src/tools/compiletest/src/runtest/ui.rs
index f6bc85cd051..0507c2600ae 100644
--- a/src/tools/compiletest/src/runtest/ui.rs
+++ b/src/tools/compiletest/src/runtest/ui.rs
@@ -6,8 +6,8 @@ use rustfix::{Filter, apply_suggestions, get_suggestions_from_json};
 use tracing::debug;
 
 use super::{
-    AllowUnused, Emit, FailMode, LinkToAux, PassMode, TargetLocation, TestCx, TestOutput,
-    Truncated, UI_FIXED, WillExecute,
+    AllowUnused, Emit, FailMode, LinkToAux, PassMode, RunFailMode, RunResult, TargetLocation,
+    TestCx, TestOutput, Truncated, UI_FIXED, WillExecute,
 };
 use crate::json;
 
@@ -140,12 +140,53 @@ impl TestCx<'_> {
                     &proc_res,
                 );
             }
+            let code = proc_res.status.code();
+            let run_result = if proc_res.status.success() {
+                RunResult::Pass
+            } else if code.is_some_and(|c| c >= 1 && c <= 127) {
+                RunResult::Fail
+            } else {
+                RunResult::Crash
+            };
+            // Help users understand why the test failed by including the actual
+            // exit code and actual run result in the failure message.
+            let pass_hint = format!("code={code:?} so test would pass with `{run_result}`");
             if self.should_run_successfully(pm) {
-                if !proc_res.status.success() {
-                    self.fatal_proc_rec("test run failed!", &proc_res);
+                if run_result != RunResult::Pass {
+                    self.fatal_proc_rec(
+                        &format!("test did not exit with success! {pass_hint}"),
+                        &proc_res,
+                    );
+                }
+            } else if self.props.fail_mode == Some(FailMode::Run(RunFailMode::Fail)) {
+                // If the test is marked as `run-fail` but do not support
+                // unwinding we allow it to crash, since a panic will trigger an
+                // abort (crash) instead of unwind (exit with code 101).
+                let crash_ok = !self.config.can_unwind();
+                if run_result != RunResult::Fail && !(crash_ok && run_result == RunResult::Crash) {
+                    let err = if crash_ok {
+                        format!(
+                            "test did not exit with failure or crash (`{}` can't unwind)! {pass_hint}",
+                            self.config.target
+                        )
+                    } else {
+                        format!("test did not exit with failure! {pass_hint}")
+                    };
+                    self.fatal_proc_rec(&err, &proc_res);
                 }
-            } else if proc_res.status.success() {
-                self.fatal_proc_rec("test run succeeded!", &proc_res);
+            } else if self.props.fail_mode == Some(FailMode::Run(RunFailMode::Crash)) {
+                if run_result != RunResult::Crash {
+                    self.fatal_proc_rec(&format!("test did not crash! {pass_hint}"), &proc_res);
+                }
+            } else if self.props.fail_mode == Some(FailMode::Run(RunFailMode::FailOrCrash)) {
+                if run_result != RunResult::Fail && run_result != RunResult::Crash {
+                    self.fatal_proc_rec(
+                        &format!("test did not exit with failure or crash! {pass_hint}"),
+                        &proc_res,
+                    );
+                }
+            } else {
+                unreachable!("run_ui_test() must not be called if the test should not run");
             }
 
             self.get_output(&proc_res)
diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs
index 3cc38fa087c..10339928ac2 100644
--- a/src/tools/miri/src/alloc_addresses/mod.rs
+++ b/src/tools/miri/src/alloc_addresses/mod.rs
@@ -157,7 +157,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
                         this.get_alloc_bytes_unchecked_raw(alloc_id)?
                     }
                 }
-                AllocKind::Function | AllocKind::VTable => {
+                AllocKind::Function | AllocKind::Virtual => {
                     // Allocate some dummy memory to get a unique address for this function/vtable.
                     let alloc_bytes = MiriAllocBytes::from_bytes(
                         &[0u8; 1],
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
index 834a4b41f22..e834fdffdd1 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
@@ -650,7 +650,7 @@ trait EvalContextPrivExt<'tcx, 'ecx>: crate::MiriInterpCxExt<'tcx> {
                         dcx.log_protector();
                     }
                 },
-                AllocKind::Function | AllocKind::VTable | AllocKind::Dead => {
+                AllocKind::Function | AllocKind::Virtual | AllocKind::Dead => {
                     // No stacked borrows on these allocations.
                 }
             }
@@ -1021,7 +1021,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 trace!("Stacked Borrows tag {tag:?} exposed in {alloc_id:?}");
                 alloc_extra.borrow_tracker_sb().borrow_mut().exposed_tags.insert(tag);
             }
-            AllocKind::Function | AllocKind::VTable | AllocKind::Dead => {
+            AllocKind::Function | AllocKind::Virtual | AllocKind::Dead => {
                 // No stacked borrows on these allocations.
             }
         }
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
index c157c69d7c8..aa92f8a8c30 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
@@ -673,7 +673,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 trace!("Tree Borrows tag {tag:?} exposed in {alloc_id:?}");
                 alloc_extra.borrow_tracker_tb().borrow_mut().expose_tag(tag);
             }
-            AllocKind::Function | AllocKind::VTable | AllocKind::Dead => {
+            AllocKind::Function | AllocKind::Virtual | AllocKind::Dead => {
                 // No tree borrows on these allocations.
             }
         }
diff --git a/src/tools/miri/tests/panic/mir-validation.stderr b/src/tools/miri/tests/panic/mir-validation.stderr
index dc70d129da3..f801ac907e6 100644
--- a/src/tools/miri/tests/panic/mir-validation.stderr
+++ b/src/tools/miri/tests/panic/mir-validation.stderr
@@ -1,11 +1,15 @@
+error: internal compiler error: compiler/rustc_mir_transform/src/validate.rs:LL:CC: broken MIR in Item(DefId) (after phase change to runtime-optimized) at bb0[1]:
+                                place (*(_2.0: *mut i32)) has deref as a later projection (it is only permitted as the first projection)
+  --> tests/panic/mir-validation.rs:LL:CC
+   |
+LL |             *(tuple.0) = 1;
+   |             ^^^^^^^^^^^^^^
+
 
 thread 'rustc' panicked at compiler/rustc_mir_transform/src/validate.rs:LL:CC:
-broken MIR in Item(DefId) (after phase change to runtime-optimized) at bb0[1]:
-place (*(_2.0: *mut i32)) has deref as a later projection (it is only permitted as the first projection)
+Box<dyn Any>
 stack backtrace:
 
-error: the compiler unexpectedly panicked. this is a bug.
-
 
 
 
@@ -20,3 +24,5 @@ LL |     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 
+error: aborting due to 1 previous error
+
diff --git a/src/tools/miri/tests/pass-dep/libc/libc-time.rs b/src/tools/miri/tests/pass-dep/libc/libc-time.rs
index e8957846ad5..9e9fadfca9e 100644
--- a/src/tools/miri/tests/pass-dep/libc/libc-time.rs
+++ b/src/tools/miri/tests/pass-dep/libc/libc-time.rs
@@ -336,7 +336,7 @@ fn test_nanosleep() {
     let remainder = ptr::null_mut::<libc::timespec>();
     let is_error = unsafe { libc::nanosleep(&duration_zero, remainder) };
     assert_eq!(is_error, 0);
-    assert!(start_test_sleep.elapsed() < Duration::from_millis(10));
+    assert!(start_test_sleep.elapsed() < Duration::from_millis(100));
 
     let start_test_sleep = Instant::now();
     let duration_100_millis = libc::timespec { tv_sec: 0, tv_nsec: 1_000_000_000 / 10 };
@@ -390,7 +390,7 @@ mod test_clock_nanosleep {
             )
         };
         assert_eq!(error, 0);
-        assert!(start_test_sleep.elapsed() < Duration::from_millis(10));
+        assert!(start_test_sleep.elapsed() < Duration::from_millis(100));
 
         let start_test_sleep = Instant::now();
         let hunderd_millis_after_start = add_100_millis(timespec_now(libc::CLOCK_MONOTONIC));
@@ -417,7 +417,7 @@ mod test_clock_nanosleep {
             libc::clock_nanosleep(libc::CLOCK_MONOTONIC, NO_FLAGS, &duration_zero, remainder)
         };
         assert_eq!(error, 0);
-        assert!(start_test_sleep.elapsed() < Duration::from_millis(10));
+        assert!(start_test_sleep.elapsed() < Duration::from_millis(100));
 
         let start_test_sleep = Instant::now();
         let duration_100_millis = libc::timespec { tv_sec: 0, tv_nsec: 1_000_000_000 / 10 };
diff --git a/src/tools/miri/tests/pass/intrinsics/type-id.rs b/src/tools/miri/tests/pass/intrinsics/type-id.rs
new file mode 100644
index 00000000000..123fdbdc9ce
--- /dev/null
+++ b/src/tools/miri/tests/pass/intrinsics/type-id.rs
@@ -0,0 +1,19 @@
+use std::any::{Any, TypeId};
+
+fn main() {
+    let t1 = TypeId::of::<u64>();
+    let t2 = TypeId::of::<u64>();
+    assert_eq!(t1, t2);
+    let t3 = TypeId::of::<usize>();
+    assert_ne!(t1, t3);
+
+    let _ = format!("{t1:?}"); // test that we can debug-print
+
+    let b = Box::new(0u64) as Box<dyn Any>;
+    assert_eq!(*b.downcast_ref::<u64>().unwrap(), 0);
+    assert!(b.downcast_ref::<usize>().is_none());
+
+    // Get the first pointer chunk and try to make it a ZST ref.
+    // This used to trigger an error because TypeId allocs got misclassified as "LiveData".
+    let _raw_chunk = unsafe { (&raw const t1).cast::<&()>().read() };
+}
diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock
index 27798d6aeb0..e363668d462 100644
--- a/src/tools/rustbook/Cargo.lock
+++ b/src/tools/rustbook/Cargo.lock
@@ -19,9 +19,9 @@ dependencies = [
 
 [[package]]
 name = "ammonia"
-version = "4.1.0"
+version = "4.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ada2ee439075a3e70b6992fce18ac4e407cd05aea9ca3f75d2c0b0c20bbb364"
+checksum = "d6b346764dd0814805de8abf899fe03065bcee69bb1a4771c785817e39f3978f"
 dependencies = [
  "cssparser",
  "html5ever",
@@ -156,9 +156,9 @@ checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
 
 [[package]]
 name = "cc"
-version = "1.2.29"
+version = "1.2.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c1599538de2394445747c8cf7935946e3cc27e9625f889d979bfb2aaf569362"
+checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7"
 dependencies = [
  "shlex",
 ]
@@ -185,9 +185,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.5.40"
+version = "4.5.41"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f"
+checksum = "be92d32e80243a54711e5d7ce823c35c41c9d929dc4ab58e1276f625841aadf9"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -195,9 +195,9 @@ dependencies = [
 
 [[package]]
 name = "clap_builder"
-version = "4.5.40"
+version = "4.5.41"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e"
+checksum = "707eab41e9622f9139419d573eca0900137718000c517d47da73045f54331c3d"
 dependencies = [
  "anstream",
  "anstyle",
@@ -208,18 +208,18 @@ dependencies = [
 
 [[package]]
 name = "clap_complete"
-version = "4.5.54"
+version = "4.5.55"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "aad5b1b4de04fead402672b48897030eec1f3bfe1550776322f59f6d6e6a5677"
+checksum = "a5abde44486daf70c5be8b8f8f1b66c49f86236edf6fa2abadb4d961c4c6229a"
 dependencies = [
  "clap",
 ]
 
 [[package]]
 name = "clap_derive"
-version = "4.5.40"
+version = "4.5.41"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce"
+checksum = "ef4f52386a59ca4c860f7393bcf8abd8dfd91ecccc0f774635ff68e92eeef491"
 dependencies = [
  "heck",
  "proc-macro2",
@@ -256,9 +256,9 @@ dependencies = [
 
 [[package]]
 name = "crc32fast"
-version = "1.4.2"
+version = "1.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3"
+checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
 dependencies = [
  "cfg-if",
 ]
@@ -582,12 +582,11 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
 
 [[package]]
 name = "html5ever"
-version = "0.31.0"
+version = "0.35.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "953cbbe631aae7fc0a112702ad5d3aaf09da38beaf45ea84610d6e1c358f569c"
+checksum = "55d958c2f74b664487a2035fe1dadb032c48718a03b63f3ab0b8537db8549ed4"
 dependencies = [
  "log",
- "mac",
  "markup5ever",
  "match_token",
 ]
@@ -863,9 +862,9 @@ checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
 
 [[package]]
 name = "markup5ever"
-version = "0.16.2"
+version = "0.35.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e4cd8c02f18a011991a039855480c64d74291c5792fcc160d55d77dc4de4a39"
+checksum = "311fe69c934650f8f19652b3946075f0fc41ad8757dbb68f1ca14e7900ecc1c3"
 dependencies = [
  "log",
  "tendril",
@@ -874,9 +873,9 @@ dependencies = [
 
 [[package]]
 name = "match_token"
-version = "0.1.0"
+version = "0.35.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b"
+checksum = "ac84fd3f360fcc43dc5f5d186f02a94192761a080e8bc58621ad4d12296a58cf"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1394,15 +1393,15 @@ dependencies = [
 
 [[package]]
 name = "rustix"
-version = "1.0.7"
+version = "1.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266"
+checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
 dependencies = [
  "bitflags 2.9.1",
  "errno",
  "libc",
  "linux-raw-sys",
- "windows-sys 0.59.0",
+ "windows-sys 0.60.2",
 ]
 
 [[package]]
@@ -1460,9 +1459,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.140"
+version = "1.0.141"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
+checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3"
 dependencies = [
  "itoa",
  "memchr",
@@ -2103,9 +2102,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
 
 [[package]]
 name = "winnow"
-version = "0.7.11"
+version = "0.7.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74c7b26e3480b707944fc872477815d29a8e429d2f93a1ce000f5fa84a15cbcd"
+checksum = "f3edebf492c8125044983378ecb5766203ad3b4c2f7a922bd7dd207f6d443e95"
 dependencies = [
  "memchr",
 ]
diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js
index f70fc917770..0baa179e16b 100644
--- a/src/tools/rustdoc-js/tester.js
+++ b/src/tools/rustdoc-js/tester.js
@@ -28,7 +28,14 @@ function readFile(filePath) {
 }
 
 function contentToDiffLine(key, value) {
-    return `"${key}": "${value}",`;
+    if (typeof value === "object" && !Array.isArray(value) && value !== null) {
+        const out = Object.entries(value)
+            .filter(([subKey, _]) => ["path", "name"].includes(subKey))
+            .map(([subKey, subValue]) => `"${subKey}": ${JSON.stringify(subValue)}`)
+            .join(", ");
+        return `"${key}": ${out},`;
+    }
+    return `"${key}": ${JSON.stringify(value)},`;
 }
 
 function shouldIgnoreField(fieldName) {
@@ -37,47 +44,61 @@ function shouldIgnoreField(fieldName) {
         fieldName === "proposeCorrectionTo";
 }
 
+function valueMapper(key, testOutput) {
+    const isAlias = testOutput["is_alias"];
+    let value = testOutput[key];
+    // To make our life easier, if there is a "parent" type, we add it to the path.
+    if (key === "path") {
+        if (testOutput["parent"] !== undefined) {
+            if (value.length > 0) {
+                value += "::" + testOutput["parent"]["name"];
+            } else {
+                value = testOutput["parent"]["name"];
+            }
+        } else if (testOutput["is_alias"]) {
+            value = valueMapper(key, testOutput["original"]);
+        }
+    } else if (isAlias && key === "alias") {
+        value = testOutput["name"];
+    } else if (isAlias && ["name"].includes(key)) {
+        value = testOutput["original"][key];
+    }
+    return value;
+}
+
 // This function is only called when no matching result was found and therefore will only display
 // the diff between the two items.
-function betterLookingDiff(entry, data) {
+function betterLookingDiff(expected, testOutput) {
     let output = " {\n";
-    const spaces = "     ";
-    for (const key in entry) {
-        if (!Object.prototype.hasOwnProperty.call(entry, key)) {
+    const spaces = "    ";
+    for (const key in expected) {
+        if (!Object.prototype.hasOwnProperty.call(expected, key)) {
             continue;
         }
-        if (!data || !Object.prototype.hasOwnProperty.call(data, key)) {
-            output += "-" + spaces + contentToDiffLine(key, entry[key]) + "\n";
+        if (!testOutput || !Object.prototype.hasOwnProperty.call(testOutput, key)) {
+            output += "-" + spaces + contentToDiffLine(key, expected[key]) + "\n";
             continue;
         }
-        const value = data[key];
-        if (value !== entry[key]) {
-            output += "-" + spaces + contentToDiffLine(key, entry[key]) + "\n";
+        const value = valueMapper(key, testOutput);
+        if (value !== expected[key]) {
+            output += "-" + spaces + contentToDiffLine(key, expected[key]) + "\n";
             output += "+" + spaces + contentToDiffLine(key, value) + "\n";
         } else {
-            output += spaces + contentToDiffLine(key, value) + "\n";
+            output += spaces + " " + contentToDiffLine(key, value) + "\n";
         }
     }
     return output + " }";
 }
 
-function lookForEntry(entry, data) {
-    return data.findIndex(data_entry => {
+function lookForEntry(expected, testOutput) {
+    return testOutput.findIndex(testOutputEntry => {
         let allGood = true;
-        for (const key in entry) {
-            if (!Object.prototype.hasOwnProperty.call(entry, key)) {
+        for (const key in expected) {
+            if (!Object.prototype.hasOwnProperty.call(expected, key)) {
                 continue;
             }
-            let value = data_entry[key];
-            // To make our life easier, if there is a "parent" type, we add it to the path.
-            if (key === "path" && data_entry["parent"] !== undefined) {
-                if (value.length > 0) {
-                    value += "::" + data_entry["parent"]["name"];
-                } else {
-                    value = data_entry["parent"]["name"];
-                }
-            }
-            if (value !== entry[key]) {
+            const value = valueMapper(key, testOutputEntry);
+            if (value !== expected[key]) {
                 allGood = false;
                 break;
             }
diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs
index e83b47e1380..fb00b3a943f 100644
--- a/src/tools/tidy/src/features.rs
+++ b/src/tools/tidy/src/features.rs
@@ -331,11 +331,9 @@ fn collect_lang_features_in(features: &mut Features, base: &Path, file: &str, ba
             continue;
         }
 
-        if in_feature_group {
-            if let Some(doc_comment) = line.strip_prefix("///") {
-                doc_comments.push(doc_comment.trim().to_string());
-                continue;
-            }
+        if in_feature_group && let Some(doc_comment) = line.strip_prefix("///") {
+            doc_comments.push(doc_comment.trim().to_string());
+            continue;
         }
 
         let mut parts = line.split(',');
@@ -465,19 +463,20 @@ fn get_and_check_lib_features(
     map_lib_features(base_src_path, &mut |res, file, line| match res {
         Ok((name, f)) => {
             let mut check_features = |f: &Feature, list: &Features, display: &str| {
-                if let Some(s) = list.get(name) {
-                    if f.tracking_issue != s.tracking_issue && f.level != Status::Accepted {
-                        tidy_error!(
-                            bad,
-                            "{}:{}: feature gate {} has inconsistent `issue`: \"{}\" mismatches the {} `issue` of \"{}\"",
-                            file.display(),
-                            line,
-                            name,
-                            f.tracking_issue_display(),
-                            display,
-                            s.tracking_issue_display(),
-                        );
-                    }
+                if let Some(s) = list.get(name)
+                    && f.tracking_issue != s.tracking_issue
+                    && f.level != Status::Accepted
+                {
+                    tidy_error!(
+                        bad,
+                        "{}:{}: feature gate {} has inconsistent `issue`: \"{}\" mismatches the {} `issue` of \"{}\"",
+                        file.display(),
+                        line,
+                        name,
+                        f.tracking_issue_display(),
+                        display,
+                        s.tracking_issue_display(),
+                    );
                 }
             };
             check_features(&f, lang_features, "corresponding lang feature");
diff --git a/src/tools/tidy/src/fluent_period.rs b/src/tools/tidy/src/fluent_period.rs
index 85c1ef6166a..836b5699289 100644
--- a/src/tools/tidy/src/fluent_period.rs
+++ b/src/tools/tidy/src/fluent_period.rs
@@ -33,14 +33,14 @@ fn check_period(filename: &str, contents: &str, bad: &mut bool) {
                 continue;
             }
 
-            if let Some(pat) = &m.value {
-                if let Some(PatternElement::TextElement { value }) = pat.elements.last() {
-                    // We don't care about ellipses.
-                    if value.ends_with(".") && !value.ends_with("...") {
-                        let ll = find_line(contents, value);
-                        let name = m.id.name;
-                        tidy_error!(bad, "{filename}:{ll}: message `{name}` ends in a period");
-                    }
+            if let Some(pat) = &m.value
+                && let Some(PatternElement::TextElement { value }) = pat.elements.last()
+            {
+                // We don't care about ellipses.
+                if value.ends_with(".") && !value.ends_with("...") {
+                    let ll = find_line(contents, value);
+                    let name = m.id.name;
+                    tidy_error!(bad, "{filename}:{ll}: message `{name}` ends in a period");
                 }
             }
 
@@ -50,12 +50,13 @@ fn check_period(filename: &str, contents: &str, bad: &mut bool) {
                     continue;
                 }
 
-                if let Some(PatternElement::TextElement { value }) = attr.value.elements.last() {
-                    if value.ends_with(".") && !value.ends_with("...") {
-                        let ll = find_line(contents, value);
-                        let name = attr.id.name;
-                        tidy_error!(bad, "{filename}:{ll}: attr `{name}` ends in a period");
-                    }
+                if let Some(PatternElement::TextElement { value }) = attr.value.elements.last()
+                    && value.ends_with(".")
+                    && !value.ends_with("...")
+                {
+                    let ll = find_line(contents, value);
+                    let name = attr.id.name;
+                    tidy_error!(bad, "{filename}:{ll}: attr `{name}` ends in a period");
                 }
             }
         }
diff --git a/src/tools/tidy/src/fluent_used.rs b/src/tools/tidy/src/fluent_used.rs
index 12fafd9a7ff..909bf482ddf 100644
--- a/src/tools/tidy/src/fluent_used.rs
+++ b/src/tools/tidy/src/fluent_used.rs
@@ -12,7 +12,7 @@ fn filter_used_messages(
 ) {
     // we don't just check messages never appear in Rust files,
     // because messages can be used as parts of other fluent messages in Fluent files,
-    // so we do checking messages appear only once in all Rust and Fluent files.
+    // so we check messages appear only once in all Rust and Fluent files.
     let matches = static_regex!(r"\w+").find_iter(contents);
     for name in matches {
         if let Some((name, filename)) = msgs_not_appeared_yet.remove_entry(name.as_str()) {
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index ade4055b5bd..cb875504e1e 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -13,8 +13,9 @@ use termcolor::WriteColor;
 
 macro_rules! static_regex {
     ($re:literal) => {{
-        static RE: ::std::sync::OnceLock<::regex::Regex> = ::std::sync::OnceLock::new();
-        RE.get_or_init(|| ::regex::Regex::new($re).unwrap())
+        static RE: ::std::sync::LazyLock<::regex::Regex> =
+            ::std::sync::LazyLock::new(|| ::regex::Regex::new($re).unwrap());
+        &*RE
     }};
 }
 
@@ -134,7 +135,7 @@ pub fn files_modified(ci_info: &CiInfo, pred: impl Fn(&str) -> bool) -> bool {
         eprintln!("No base commit, assuming all files are modified");
         return true;
     };
-    match crate::git_diff(&base_commit, "--name-status") {
+    match crate::git_diff(base_commit, "--name-status") {
         Some(output) => {
             let modified_files = output.lines().filter_map(|ln| {
                 let (status, name) = ln
diff --git a/src/tools/tidy/src/mir_opt_tests.rs b/src/tools/tidy/src/mir_opt_tests.rs
index 1efe71b1687..6119eb58383 100644
--- a/src/tools/tidy/src/mir_opt_tests.rs
+++ b/src/tools/tidy/src/mir_opt_tests.rs
@@ -55,22 +55,21 @@ fn check_dash_files(path: &Path, bless: bool, bad: &mut bool) {
         .filter(|e| e.file_type().is_file())
     {
         let path = file.path();
-        if path.extension() == Some("rs".as_ref()) {
-            if let Some(name) = path.file_name().and_then(|s| s.to_str()) {
-                if name.contains('-') {
-                    if !bless {
-                        tidy_error!(
-                            bad,
-                            "mir-opt test files should not have dashes in them: {}",
-                            path.display()
-                        );
-                    } else {
-                        let new_name = name.replace('-', "_");
-                        let mut new_path = path.to_owned();
-                        new_path.set_file_name(new_name);
-                        let _ = std::fs::rename(path, new_path);
-                    }
-                }
+        if path.extension() == Some("rs".as_ref())
+            && let Some(name) = path.file_name().and_then(|s| s.to_str())
+            && name.contains('-')
+        {
+            if !bless {
+                tidy_error!(
+                    bad,
+                    "mir-opt test files should not have dashes in them: {}",
+                    path.display()
+                );
+            } else {
+                let new_name = name.replace('-', "_");
+                let mut new_path = path.to_owned();
+                new_path.set_file_name(new_name);
+                let _ = std::fs::rename(path, new_path);
             }
         }
     }
diff --git a/src/tools/tidy/src/rustdoc_templates.rs b/src/tools/tidy/src/rustdoc_templates.rs
index dca3e8d9d25..597290a6a9a 100644
--- a/src/tools/tidy/src/rustdoc_templates.rs
+++ b/src/tools/tidy/src/rustdoc_templates.rs
@@ -26,7 +26,7 @@ pub fn check(librustdoc_path: &Path, bad: &mut bool) {
                         None
                     // Then we check if this a comment tag.
                     } else if *tag != "{#" {
-                        return Some(false);
+                        Some(false)
                     // And finally we check if the comment is empty (ie, only there to strip
                     // extra whitespace characters).
                     } else if let Some(start_pos) = line.rfind(tag) {
diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs
index 8dde4618ce5..35ed61eacc7 100644
--- a/src/tools/tidy/src/style.rs
+++ b/src/tools/tidy/src/style.rs
@@ -417,10 +417,10 @@ pub fn check(path: &Path, bad: &mut bool) {
             return;
         }
         // Shell completions are automatically generated
-        if let Some(p) = file.parent() {
-            if p.ends_with(Path::new("src/etc/completions")) {
-                return;
-            }
+        if let Some(p) = file.parent()
+            && p.ends_with(Path::new("src/etc/completions"))
+        {
+            return;
         }
         let [
             mut skip_cr,
@@ -604,25 +604,25 @@ pub fn check(path: &Path, bad: &mut bool) {
                         backtick_count += comment_text.chars().filter(|ch| *ch == '`').count();
                     }
                     comment_block = Some((start_line, backtick_count));
-                } else if let Some((start_line, backtick_count)) = comment_block.take() {
-                    if backtick_count % 2 == 1 {
-                        let mut err = |msg: &str| {
-                            tidy_error!(bad, "{}:{start_line}: {msg}", file.display());
-                        };
-                        let block_len = (i + 1) - start_line;
-                        if block_len == 1 {
-                            suppressible_tidy_err!(
-                                err,
-                                skip_odd_backticks,
-                                "comment with odd number of backticks"
-                            );
-                        } else {
-                            suppressible_tidy_err!(
-                                err,
-                                skip_odd_backticks,
-                                "{block_len}-line comment block with odd number of backticks"
-                            );
-                        }
+                } else if let Some((start_line, backtick_count)) = comment_block.take()
+                    && backtick_count % 2 == 1
+                {
+                    let mut err = |msg: &str| {
+                        tidy_error!(bad, "{}:{start_line}: {msg}", file.display());
+                    };
+                    let block_len = (i + 1) - start_line;
+                    if block_len == 1 {
+                        suppressible_tidy_err!(
+                            err,
+                            skip_odd_backticks,
+                            "comment with odd number of backticks"
+                        );
+                    } else {
+                        suppressible_tidy_err!(
+                            err,
+                            skip_odd_backticks,
+                            "{block_len}-line comment block with odd number of backticks"
+                        );
                     }
                 }
             }
diff --git a/src/tools/tidy/src/target_specific_tests.rs b/src/tools/tidy/src/target_specific_tests.rs
index 1a6fd3eaf2d..f4a6783abb6 100644
--- a/src/tools/tidy/src/target_specific_tests.rs
+++ b/src/tools/tidy/src/target_specific_tests.rs
@@ -30,17 +30,17 @@ pub fn check(tests_path: &Path, bad: &mut bool) {
                         comp_vec.push(component);
                     }
                 }
-            } else if let Some(compile_flags) = directive.strip_prefix(COMPILE_FLAGS_HEADER) {
-                if let Some((_, v)) = compile_flags.split_once("--target") {
-                    let v = v.trim_start_matches([' ', '=']);
-                    let v = if v == "{{target}}" { Some((v, v)) } else { v.split_once("-") };
-                    if let Some((arch, _)) = v {
-                        let info = header_map.entry(revision).or_insert(RevisionInfo::default());
-                        info.target_arch.replace(arch);
-                    } else {
-                        eprintln!("{file}: seems to have a malformed --target value");
-                        *bad = true;
-                    }
+            } else if let Some(compile_flags) = directive.strip_prefix(COMPILE_FLAGS_HEADER)
+                && let Some((_, v)) = compile_flags.split_once("--target")
+            {
+                let v = v.trim_start_matches([' ', '=']);
+                let v = if v == "{{target}}" { Some((v, v)) } else { v.split_once("-") };
+                if let Some((arch, _)) = v {
+                    let info = header_map.entry(revision).or_insert(RevisionInfo::default());
+                    info.target_arch.replace(arch);
+                } else {
+                    eprintln!("{file}: seems to have a malformed --target value");
+                    *bad = true;
                 }
             }
         });
diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs
index 7e295731c56..b9d22ece597 100644
--- a/src/tools/tidy/src/ui_tests.rs
+++ b/src/tools/tidy/src/ui_tests.rs
@@ -161,31 +161,30 @@ pub fn check(root_path: &Path, bless: bool, bad: &mut bool) {
                     tidy_error!(bad, "Stray file with UI testing output: {:?}", file_path);
                 }
 
-                if let Ok(metadata) = fs::metadata(file_path) {
-                    if metadata.len() == 0 {
-                        tidy_error!(bad, "Empty file with UI testing output: {:?}", file_path);
-                    }
+                if let Ok(metadata) = fs::metadata(file_path)
+                    && metadata.len() == 0
+                {
+                    tidy_error!(bad, "Empty file with UI testing output: {:?}", file_path);
                 }
             }
 
-            if ext == "rs" {
-                if let Some(test_name) = static_regex!(r"^issues?[-_]?(\d{3,})").captures(testname)
-                {
-                    // these paths are always relative to the passed `path` and always UTF8
-                    let stripped_path = file_path
-                        .strip_prefix(path)
-                        .unwrap()
-                        .to_str()
-                        .unwrap()
-                        .replace(std::path::MAIN_SEPARATOR_STR, "/");
-
-                    if !remaining_issue_names.remove(stripped_path.as_str()) {
-                        tidy_error!(
-                            bad,
-                            "file `tests/{stripped_path}` must begin with a descriptive name, consider `{{reason}}-issue-{issue_n}.rs`",
-                            issue_n = &test_name[1],
-                        );
-                    }
+            if ext == "rs"
+                && let Some(test_name) = static_regex!(r"^issues?[-_]?(\d{3,})").captures(testname)
+            {
+                // these paths are always relative to the passed `path` and always UTF8
+                let stripped_path = file_path
+                    .strip_prefix(path)
+                    .unwrap()
+                    .to_str()
+                    .unwrap()
+                    .replace(std::path::MAIN_SEPARATOR_STR, "/");
+
+                if !remaining_issue_names.remove(stripped_path.as_str()) {
+                    tidy_error!(
+                        bad,
+                        "file `tests/{stripped_path}` must begin with a descriptive name, consider `{{reason}}-issue-{issue_n}.rs`",
+                        issue_n = &test_name[1],
+                    );
                 }
             }
         }
diff --git a/src/tools/tidy/src/x_version.rs b/src/tools/tidy/src/x_version.rs
index 6a5e9eca813..9f7f43c4000 100644
--- a/src/tools/tidy/src/x_version.rs
+++ b/src/tools/tidy/src/x_version.rs
@@ -25,12 +25,12 @@ pub fn check(root: &Path, cargo: &Path, bad: &mut bool) {
                 if let Some(version) = iter.next() {
                     // Check this is the rust-lang/rust x tool installation since it should be
                     // installed at a path containing `src/tools/x`.
-                    if let Some(path) = iter.next() {
-                        if path.contains("src/tools/x") {
-                            let version = version.strip_prefix("v").unwrap();
-                            installed = Some(Version::parse(version).unwrap());
-                            break;
-                        }
+                    if let Some(path) = iter.next()
+                        && path.contains("src/tools/x")
+                    {
+                        let version = version.strip_prefix("v").unwrap();
+                        installed = Some(Version::parse(version).unwrap());
+                        break;
                     };
                 }
             } else {
diff --git a/src/tools/unicode-table-generator/Cargo.toml b/src/tools/unicode-table-generator/Cargo.toml
index f8a500922d0..3ca6e9e316f 100644
--- a/src/tools/unicode-table-generator/Cargo.toml
+++ b/src/tools/unicode-table-generator/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "unicode-table-generator"
 version = "0.1.0"
-edition = "2021"
+edition = "2024"
 
 # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
 
diff --git a/src/tools/unicode-table-generator/src/cascading_map.rs b/src/tools/unicode-table-generator/src/cascading_map.rs
index 1eb35e819c0..78a7bba3208 100644
--- a/src/tools/unicode-table-generator/src/cascading_map.rs
+++ b/src/tools/unicode-table-generator/src/cascading_map.rs
@@ -21,7 +21,7 @@ impl RawEmitter {
 
         let points = ranges
             .iter()
-            .flat_map(|r| (r.start..r.end).into_iter().collect::<Vec<u32>>())
+            .flat_map(|r| (r.start..r.end).collect::<Vec<u32>>())
             .collect::<Vec<u32>>();
 
         println!("there are {} points", points.len());
@@ -32,21 +32,20 @@ impl RawEmitter {
             // assert that there is no whitespace over the 0x3000 range.
             assert!(point <= 0x3000, "the highest unicode whitespace value has changed");
             let high_bytes = point as usize >> 8;
-            let codepoints = codepoints_by_high_bytes.entry(high_bytes).or_insert_with(Vec::new);
+            let codepoints = codepoints_by_high_bytes.entry(high_bytes).or_default();
             codepoints.push(point);
         }
 
         let mut bit_for_high_byte = 1u8;
         let mut arms = Vec::<String>::new();
 
-        let mut high_bytes: Vec<usize> =
-            codepoints_by_high_bytes.keys().map(|k| k.clone()).collect();
+        let mut high_bytes: Vec<usize> = codepoints_by_high_bytes.keys().copied().collect();
         high_bytes.sort();
         for high_byte in high_bytes {
             let codepoints = codepoints_by_high_bytes.get_mut(&high_byte).unwrap();
             if codepoints.len() == 1 {
                 let ch = codepoints.pop().unwrap();
-                arms.push(format!("{} => c as u32 == {:#04x}", high_byte, ch));
+                arms.push(format!("{high_byte} => c as u32 == {ch:#04x}"));
                 continue;
             }
             // more than 1 codepoint in this arm
@@ -54,8 +53,7 @@ impl RawEmitter {
                 map[(*codepoint & 0xff) as usize] |= bit_for_high_byte;
             }
             arms.push(format!(
-                "{} => WHITESPACE_MAP[c as usize & 0xff] & {} != 0",
-                high_byte, bit_for_high_byte
+                "{high_byte} => WHITESPACE_MAP[c as usize & 0xff] & {bit_for_high_byte} != 0"
             ));
             bit_for_high_byte <<= 1;
         }
@@ -68,7 +66,7 @@ impl RawEmitter {
         writeln!(&mut self.file, "pub const fn lookup(c: char) -> bool {{").unwrap();
         writeln!(&mut self.file, "    match c as u32 >> 8 {{").unwrap();
         for arm in arms {
-            writeln!(&mut self.file, "        {},", arm).unwrap();
+            writeln!(&mut self.file, "        {arm},").unwrap();
         }
         writeln!(&mut self.file, "        _ => false,").unwrap();
         writeln!(&mut self.file, "    }}").unwrap();
diff --git a/src/tools/unicode-table-generator/src/case_mapping.rs b/src/tools/unicode-table-generator/src/case_mapping.rs
index 00241b7ee0e..9c6454492e7 100644
--- a/src/tools/unicode-table-generator/src/case_mapping.rs
+++ b/src/tools/unicode-table-generator/src/case_mapping.rs
@@ -9,7 +9,7 @@ const INDEX_MASK: u32 = 1 << 22;
 pub(crate) fn generate_case_mapping(data: &UnicodeData) -> String {
     let mut file = String::new();
 
-    write!(file, "const INDEX_MASK: u32 = 0x{:x};", INDEX_MASK).unwrap();
+    write!(file, "const INDEX_MASK: u32 = 0x{INDEX_MASK:x};").unwrap();
     file.push_str("\n\n");
     file.push_str(HEADER.trim_start());
     file.push('\n');
diff --git a/src/tools/unicode-table-generator/src/main.rs b/src/tools/unicode-table-generator/src/main.rs
index 415db2c4dbc..6cdb82a87bd 100644
--- a/src/tools/unicode-table-generator/src/main.rs
+++ b/src/tools/unicode-table-generator/src/main.rs
@@ -160,15 +160,15 @@ fn load_data() -> UnicodeData {
                 .push(Codepoints::Single(row.codepoint));
         }
 
-        if let Some(mapped) = row.simple_lowercase_mapping {
-            if mapped != row.codepoint {
-                to_lower.insert(row.codepoint.value(), (mapped.value(), 0, 0));
-            }
+        if let Some(mapped) = row.simple_lowercase_mapping
+            && mapped != row.codepoint
+        {
+            to_lower.insert(row.codepoint.value(), (mapped.value(), 0, 0));
         }
-        if let Some(mapped) = row.simple_uppercase_mapping {
-            if mapped != row.codepoint {
-                to_upper.insert(row.codepoint.value(), (mapped.value(), 0, 0));
-            }
+        if let Some(mapped) = row.simple_uppercase_mapping
+            && mapped != row.codepoint
+        {
+            to_upper.insert(row.codepoint.value(), (mapped.value(), 0, 0));
         }
     }
 
@@ -196,12 +196,12 @@ fn load_data() -> UnicodeData {
                     .flat_map(|codepoints| match codepoints {
                         Codepoints::Single(c) => c
                             .scalar()
-                            .map(|ch| (ch as u32..ch as u32 + 1))
+                            .map(|ch| ch as u32..ch as u32 + 1)
                             .into_iter()
                             .collect::<Vec<_>>(),
                         Codepoints::Range(c) => c
                             .into_iter()
-                            .flat_map(|c| c.scalar().map(|ch| (ch as u32..ch as u32 + 1)))
+                            .flat_map(|c| c.scalar().map(|ch| ch as u32..ch as u32 + 1))
                             .collect::<Vec<_>>(),
                     })
                     .collect::<Vec<Range<u32>>>(),
@@ -236,7 +236,7 @@ fn main() {
     let ranges_by_property = &unicode_data.ranges;
 
     if let Some(path) = test_path {
-        std::fs::write(&path, generate_tests(&write_location, &ranges_by_property)).unwrap();
+        std::fs::write(&path, generate_tests(&write_location, ranges_by_property)).unwrap();
     }
 
     let mut total_bytes = 0;
@@ -246,9 +246,9 @@ fn main() {
 
         let mut emitter = RawEmitter::new();
         if property == &"White_Space" {
-            emit_whitespace(&mut emitter, &ranges);
+            emit_whitespace(&mut emitter, ranges);
         } else {
-            emit_codepoints(&mut emitter, &ranges);
+            emit_codepoints(&mut emitter, ranges);
         }
 
         modules.push((property.to_lowercase().to_string(), emitter.file));
@@ -288,7 +288,7 @@ fn main() {
         for line in contents.lines() {
             if !line.trim().is_empty() {
                 table_file.push_str("    ");
-                table_file.push_str(&line);
+                table_file.push_str(line);
             }
             table_file.push('\n');
         }
@@ -312,7 +312,7 @@ fn version() -> String {
     let start = readme.find(prefix).unwrap() + prefix.len();
     let end = readme.find(" of the Unicode Standard.").unwrap();
     let version =
-        readme[start..end].split('.').map(|v| v.parse::<u32>().expect(&v)).collect::<Vec<_>>();
+        readme[start..end].split('.').map(|v| v.parse::<u32>().expect(v)).collect::<Vec<_>>();
     let [major, minor, micro] = [version[0], version[1], version[2]];
 
     out.push_str(&format!("({major}, {minor}, {micro});\n"));
@@ -320,7 +320,7 @@ fn version() -> String {
 }
 
 fn fmt_list<V: std::fmt::Debug>(values: impl IntoIterator<Item = V>) -> String {
-    let pieces = values.into_iter().map(|b| format!("{:?}, ", b)).collect::<Vec<_>>();
+    let pieces = values.into_iter().map(|b| format!("{b:?}, ")).collect::<Vec<_>>();
     let mut out = String::new();
     let mut line = String::from("\n    ");
     for piece in pieces {
@@ -348,7 +348,7 @@ fn generate_tests(data_path: &str, ranges: &[(&str, Vec<Range<u32>>)]) -> String
     s.push_str("\nfn main() {\n");
 
     for (property, ranges) in ranges {
-        s.push_str(&format!(r#"    println!("Testing {}");"#, property));
+        s.push_str(&format!(r#"    println!("Testing {property}");"#));
         s.push('\n');
         s.push_str(&format!("    {}_true();\n", property.to_lowercase()));
         s.push_str(&format!("    {}_false();\n", property.to_lowercase()));
@@ -373,7 +373,7 @@ fn generate_tests(data_path: &str, ranges: &[(&str, Vec<Range<u32>>)]) -> String
         s.push_str("    }\n\n");
     }
 
-    s.push_str("}");
+    s.push('}');
     s
 }
 
@@ -388,7 +388,7 @@ fn generate_asserts(s: &mut String, property: &str, points: &[u32], truthy: bool
                 range.start,
             ));
         } else {
-            s.push_str(&format!("        for chn in {:?}u32 {{\n", range));
+            s.push_str(&format!("        for chn in {range:?}u32 {{\n"));
             s.push_str(&format!(
                 "            assert!({}unicode_data::{}::lookup(std::char::from_u32(chn).unwrap()), \"{{:?}}\", chn);\n",
                 if truthy { "" } else { "!" },
@@ -439,7 +439,7 @@ fn merge_ranges(ranges: &mut Vec<Range<u32>>) {
     let mut last_end = None;
     for range in ranges {
         if let Some(last) = last_end {
-            assert!(range.start > last, "{:?}", range);
+            assert!(range.start > last, "{range:?}");
         }
         last_end = Some(range.end);
     }
diff --git a/src/tools/unicode-table-generator/src/raw_emitter.rs b/src/tools/unicode-table-generator/src/raw_emitter.rs
index ee94d3c93a6..e9e0efc4594 100644
--- a/src/tools/unicode-table-generator/src/raw_emitter.rs
+++ b/src/tools/unicode-table-generator/src/raw_emitter.rs
@@ -156,10 +156,10 @@ pub fn emit_codepoints(emitter: &mut RawEmitter, ranges: &[Range<u32>]) {
     emitter.blank_line();
 
     let mut bitset = emitter.clone();
-    let bitset_ok = bitset.emit_bitset(&ranges).is_ok();
+    let bitset_ok = bitset.emit_bitset(ranges).is_ok();
 
     let mut skiplist = emitter.clone();
-    skiplist.emit_skiplist(&ranges);
+    skiplist.emit_skiplist(ranges);
 
     if bitset_ok && bitset.bytes_used <= skiplist.bytes_used {
         *emitter = bitset;
@@ -174,7 +174,7 @@ pub fn emit_whitespace(emitter: &mut RawEmitter, ranges: &[Range<u32>]) {
     emitter.blank_line();
 
     let mut cascading = emitter.clone();
-    cascading.emit_cascading_map(&ranges);
+    cascading.emit_cascading_map(ranges);
     *emitter = cascading;
     emitter.desc = String::from("cascading");
 }
@@ -272,7 +272,7 @@ impl Canonicalized {
         // for canonical when possible.
         while let Some((&to, _)) = mappings
             .iter()
-            .find(|(&to, _)| to == 0)
+            .find(|&(&to, _)| to == 0)
             .or_else(|| mappings.iter().max_by_key(|m| m.1.len()))
         {
             // Get the mapping with the most entries. Currently, no mapping can
@@ -311,10 +311,9 @@ impl Canonicalized {
                     }
                 }
             }
-            assert!(
-                unique_mapping
-                    .insert(to, UniqueMapping::Canonical(canonical_words.len()))
-                    .is_none()
+            assert_eq!(
+                unique_mapping.insert(to, UniqueMapping::Canonical(canonical_words.len())),
+                None
             );
             canonical_words.push(to);
 
@@ -340,14 +339,10 @@ impl Canonicalized {
         // We'll probably always have some slack though so this loop will still
         // be needed.
         for &w in unique_words {
-            if !unique_mapping.contains_key(&w) {
-                assert!(
-                    unique_mapping
-                        .insert(w, UniqueMapping::Canonical(canonical_words.len()))
-                        .is_none()
-                );
+            unique_mapping.entry(w).or_insert_with(|| {
                 canonical_words.push(w);
-            }
+                UniqueMapping::Canonical(canonical_words.len())
+            });
         }
         assert_eq!(canonicalized_words.len() + canonical_words.len(), unique_words.len());
         assert_eq!(unique_mapping.len(), unique_words.len());
diff --git a/tests/assembly/cstring-merging.rs b/tests/assembly/cstring-merging.rs
index f7d0775f7af..03688e0068b 100644
--- a/tests/assembly/cstring-merging.rs
+++ b/tests/assembly/cstring-merging.rs
@@ -2,7 +2,7 @@
 // other architectures (including ARM and x86-64) use the prefix `.Lanon.`
 //@ only-linux
 //@ assembly-output: emit-asm
-//@ compile-flags: --crate-type=lib -Copt-level=3
+//@ compile-flags: --crate-type=lib -Copt-level=3 -Cllvm-args=-enable-global-merge=0
 //@ edition: 2024
 
 use std::ffi::CStr;
diff --git a/tests/assembly/sanitizer/kcfi/emit-arity-indicator.rs b/tests/assembly/sanitizer/kcfi/emit-arity-indicator.rs
index b3b623b509b..f9966a23446 100644
--- a/tests/assembly/sanitizer/kcfi/emit-arity-indicator.rs
+++ b/tests/assembly/sanitizer/kcfi/emit-arity-indicator.rs
@@ -8,6 +8,14 @@
 //@ min-llvm-version: 21.0.0
 
 #![crate_type = "lib"]
+#![feature(no_core)]
+#![no_core]
+
+extern crate minicore;
+
+unsafe extern "C" {
+    safe fn add(x: i32, y: i32) -> i32;
+}
 
 pub fn add_one(x: i32) -> i32 {
     // CHECK-LABEL: __cfi__{{.*}}7add_one{{.*}}:
@@ -23,7 +31,7 @@ pub fn add_one(x: i32) -> i32 {
     // CHECK-NEXT:  nop
     // CHECK-NEXT:  nop
     // CHECK-NEXT:  mov ecx, 2628068948
-    x + 1
+    add(x, 1)
 }
 
 pub fn add_two(x: i32, _y: i32) -> i32 {
@@ -40,7 +48,7 @@ pub fn add_two(x: i32, _y: i32) -> i32 {
     // CHECK-NEXT:  nop
     // CHECK-NEXT:  nop
     // CHECK-NEXT:  mov edx, 2505940310
-    x + 2
+    add(x, 2)
 }
 
 pub fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
@@ -57,5 +65,5 @@ pub fn do_twice(f: fn(i32) -> i32, arg: i32) -> i32 {
     // CHECK-NEXT:  nop
     // CHECK-NEXT:  nop
     // CHECK-NEXT:  mov edx, 653723426
-    f(arg) + f(arg)
+    add(f(arg), f(arg))
 }
diff --git a/tests/assembly/wasm_exceptions.rs b/tests/assembly/wasm_exceptions.rs
index f05ccfadc58..704e8026f3f 100644
--- a/tests/assembly/wasm_exceptions.rs
+++ b/tests/assembly/wasm_exceptions.rs
@@ -2,7 +2,6 @@
 //@ assembly-output: emit-asm
 //@ compile-flags: -C target-feature=+exception-handling
 //@ compile-flags: -C panic=unwind
-//@ compile-flags: -C llvm-args=-wasm-enable-eh
 
 #![crate_type = "lib"]
 #![feature(core_intrinsics)]
diff --git a/tests/codegen/enum/enum-discriminant-eq.rs b/tests/codegen/enum/enum-discriminant-eq.rs
new file mode 100644
index 00000000000..0494c5f551b
--- /dev/null
+++ b/tests/codegen/enum/enum-discriminant-eq.rs
@@ -0,0 +1,223 @@
+//@ compile-flags: -Copt-level=3 -Zmerge-functions=disabled
+//@ min-llvm-version: 20
+//@ only-64bit
+
+// The `derive(PartialEq)` on enums with field-less variants compares discriminants,
+// so make sure we emit that in some reasonable way.
+
+#![crate_type = "lib"]
+#![feature(ascii_char)]
+#![feature(core_intrinsics)]
+#![feature(repr128)]
+
+use std::ascii::Char as AC;
+use std::cmp::Ordering;
+use std::intrinsics::discriminant_value;
+use std::num::NonZero;
+
+// A type that's bigger than `isize`, unlike the usual cases that have small tags.
+#[repr(u128)]
+pub enum Giant {
+    Two = 2,
+    Three = 3,
+    Four = 4,
+}
+
+#[unsafe(no_mangle)]
+pub fn opt_bool_eq_discr(a: Option<bool>, b: Option<bool>) -> bool {
+    // CHECK-LABEL: @opt_bool_eq_discr(
+    // CHECK: %[[A:.+]] = icmp ne i8 %a, 2
+    // CHECK: %[[B:.+]] = icmp eq i8 %b, 2
+    // CHECK: %[[R:.+]] = xor i1 %[[A]], %[[B]]
+    // CHECK: ret i1 %[[R]]
+
+    discriminant_value(&a) == discriminant_value(&b)
+}
+
+#[unsafe(no_mangle)]
+pub fn opt_ord_eq_discr(a: Option<Ordering>, b: Option<Ordering>) -> bool {
+    // CHECK-LABEL: @opt_ord_eq_discr(
+    // CHECK: %[[A:.+]] = icmp ne i8 %a, 2
+    // CHECK: %[[B:.+]] = icmp eq i8 %b, 2
+    // CHECK: %[[R:.+]] = xor i1 %[[A]], %[[B]]
+    // CHECK: ret i1 %[[R]]
+
+    discriminant_value(&a) == discriminant_value(&b)
+}
+
+#[unsafe(no_mangle)]
+pub fn opt_nz32_eq_discr(a: Option<NonZero<u32>>, b: Option<NonZero<u32>>) -> bool {
+    // CHECK-LABEL: @opt_nz32_eq_discr(
+    // CHECK: %[[A:.+]] = icmp ne i32 %a, 0
+    // CHECK: %[[B:.+]] = icmp eq i32 %b, 0
+    // CHECK: %[[R:.+]] = xor i1 %[[A]], %[[B]]
+    // CHECK: ret i1 %[[R]]
+
+    discriminant_value(&a) == discriminant_value(&b)
+}
+
+#[unsafe(no_mangle)]
+pub fn opt_ac_eq_discr(a: Option<AC>, b: Option<AC>) -> bool {
+    // CHECK-LABEL: @opt_ac_eq_discr(
+    // CHECK: %[[A:.+]] = icmp ne i8 %a, -128
+    // CHECK: %[[B:.+]] = icmp eq i8 %b, -128
+    // CHECK: %[[R:.+]] = xor i1 %[[A]], %[[B]]
+    // CHECK: ret i1 %[[R]]
+
+    discriminant_value(&a) == discriminant_value(&b)
+}
+
+#[unsafe(no_mangle)]
+pub fn opt_giant_eq_discr(a: Option<Giant>, b: Option<Giant>) -> bool {
+    // CHECK-LABEL: @opt_giant_eq_discr(
+    // CHECK: %[[A:.+]] = icmp ne i128 %a, 1
+    // CHECK: %[[B:.+]] = icmp eq i128 %b, 1
+    // CHECK: %[[R:.+]] = xor i1 %[[A]], %[[B]]
+    // CHECK: ret i1 %[[R]]
+
+    discriminant_value(&a) == discriminant_value(&b)
+}
+
+pub enum Mid<T> {
+    Before,
+    Thing(T),
+    After,
+}
+
+#[unsafe(no_mangle)]
+pub fn mid_bool_eq_discr(a: Mid<bool>, b: Mid<bool>) -> bool {
+    // CHECK-LABEL: @mid_bool_eq_discr(
+
+    // CHECK: %[[A_REL_DISCR:.+]] = add nsw i8 %a, -2
+    // CHECK: %[[A_IS_NICHE:.+]] = icmp samesign ugt i8 %a, 1
+    // CHECK: %[[A_NOT_HOLE:.+]] = icmp ne i8 %[[A_REL_DISCR]], 1
+    // CHECK: tail call void @llvm.assume(i1 %[[A_NOT_HOLE]])
+    // CHECK: %[[A_DISCR:.+]] = select i1 %[[A_IS_NICHE]], i8 %[[A_REL_DISCR]], i8 1
+
+    // CHECK: %[[B_REL_DISCR:.+]] = add nsw i8 %b, -2
+    // CHECK: %[[B_IS_NICHE:.+]] = icmp samesign ugt i8 %b, 1
+    // CHECK: %[[B_NOT_HOLE:.+]] = icmp ne i8 %[[B_REL_DISCR]], 1
+    // CHECK: tail call void @llvm.assume(i1 %[[B_NOT_HOLE]])
+    // CHECK: %[[B_DISCR:.+]] = select i1 %[[B_IS_NICHE]], i8 %[[B_REL_DISCR]], i8 1
+
+    // CHECK: ret i1 %[[R]]
+    discriminant_value(&a) == discriminant_value(&b)
+}
+
+#[unsafe(no_mangle)]
+pub fn mid_ord_eq_discr(a: Mid<Ordering>, b: Mid<Ordering>) -> bool {
+    // CHECK-LABEL: @mid_ord_eq_discr(
+
+    // CHECK: %[[A_REL_DISCR:.+]] = add nsw i8 %a, -2
+    // CHECK: %[[A_IS_NICHE:.+]] = icmp sgt i8 %a, 1
+    // CHECK: %[[A_NOT_HOLE:.+]] = icmp ne i8 %[[A_REL_DISCR]], 1
+    // CHECK: tail call void @llvm.assume(i1 %[[A_NOT_HOLE]])
+    // CHECK: %[[A_DISCR:.+]] = select i1 %[[A_IS_NICHE]], i8 %[[A_REL_DISCR]], i8 1
+
+    // CHECK: %[[B_REL_DISCR:.+]] = add nsw i8 %b, -2
+    // CHECK: %[[B_IS_NICHE:.+]] = icmp sgt i8 %b, 1
+    // CHECK: %[[B_NOT_HOLE:.+]] = icmp ne i8 %[[B_REL_DISCR]], 1
+    // CHECK: tail call void @llvm.assume(i1 %[[B_NOT_HOLE]])
+    // CHECK: %[[B_DISCR:.+]] = select i1 %[[B_IS_NICHE]], i8 %[[B_REL_DISCR]], i8 1
+
+    // CHECK: %[[R:.+]] = icmp eq i8 %[[A_DISCR]], %[[B_DISCR]]
+    // CHECK: ret i1 %[[R]]
+    discriminant_value(&a) == discriminant_value(&b)
+}
+
+#[unsafe(no_mangle)]
+pub fn mid_nz32_eq_discr(a: Mid<NonZero<u32>>, b: Mid<NonZero<u32>>) -> bool {
+    // CHECK-LABEL: @mid_nz32_eq_discr(
+    // CHECK: %[[R:.+]] = icmp eq i32 %a.0, %b.0
+    // CHECK: ret i1 %[[R]]
+    discriminant_value(&a) == discriminant_value(&b)
+}
+
+#[unsafe(no_mangle)]
+pub fn mid_ac_eq_discr(a: Mid<AC>, b: Mid<AC>) -> bool {
+    // CHECK-LABEL: @mid_ac_eq_discr(
+
+    // CHECK: %[[A_REL_DISCR:.+]] = xor i8 %a, -128
+    // CHECK: %[[A_IS_NICHE:.+]] = icmp slt i8 %a, 0
+    // CHECK: %[[A_NOT_HOLE:.+]] = icmp ne i8 %a, -127
+    // CHECK: tail call void @llvm.assume(i1 %[[A_NOT_HOLE]])
+    // CHECK: %[[A_DISCR:.+]] = select i1 %[[A_IS_NICHE]], i8 %[[A_REL_DISCR]], i8 1
+
+    // CHECK: %[[B_REL_DISCR:.+]] = xor i8 %b, -128
+    // CHECK: %[[B_IS_NICHE:.+]] = icmp slt i8 %b, 0
+    // CHECK: %[[B_NOT_HOLE:.+]] = icmp ne i8 %b, -127
+    // CHECK: tail call void @llvm.assume(i1 %[[B_NOT_HOLE]])
+    // CHECK: %[[B_DISCR:.+]] = select i1 %[[B_IS_NICHE]], i8 %[[B_REL_DISCR]], i8 1
+
+    // CHECK: %[[R:.+]] = icmp eq i8 %[[A_DISCR]], %[[B_DISCR]]
+    // CHECK: ret i1 %[[R]]
+    discriminant_value(&a) == discriminant_value(&b)
+}
+
+// FIXME: This should be improved once our LLVM fork picks up the fix for
+// <https://github.com/llvm/llvm-project/issues/134024>
+#[unsafe(no_mangle)]
+pub fn mid_giant_eq_discr(a: Mid<Giant>, b: Mid<Giant>) -> bool {
+    // CHECK-LABEL: @mid_giant_eq_discr(
+
+    // CHECK: %[[A_TRUNC:.+]] = trunc nuw nsw i128 %a to i64
+    // CHECK: %[[A_REL_DISCR:.+]] = add nsw i64 %[[A_TRUNC]], -5
+    // CHECK: %[[A_IS_NICHE:.+]] = icmp samesign ugt i128 %a, 4
+    // CHECK: %[[A_NOT_HOLE:.+]] = icmp ne i64 %[[A_REL_DISCR]], 1
+    // CHECK: tail call void @llvm.assume(i1 %[[A_NOT_HOLE]])
+    // CHECK: %[[A_DISCR:.+]] = select i1 %[[A_IS_NICHE]], i64 %[[A_REL_DISCR]], i64 1
+
+    // CHECK: %[[B_TRUNC:.+]] = trunc nuw nsw i128 %b to i64
+    // CHECK: %[[B_REL_DISCR:.+]] = add nsw i64 %[[B_TRUNC]], -5
+    // CHECK: %[[B_IS_NICHE:.+]] = icmp samesign ugt i128 %b, 4
+    // CHECK: %[[B_NOT_HOLE:.+]] = icmp ne i64 %[[B_REL_DISCR]], 1
+    // CHECK: tail call void @llvm.assume(i1 %[[B_NOT_HOLE]])
+    // CHECK: %[[B_DISCR:.+]] = select i1 %[[B_IS_NICHE]], i64 %[[B_REL_DISCR]], i64 1
+
+    // CHECK: %[[R:.+]] = icmp eq i64 %[[A_DISCR]], %[[B_DISCR]]
+    // CHECK: ret i1 %[[R]]
+    discriminant_value(&a) == discriminant_value(&b)
+}
+
+// In niche-encoded enums, testing for the untagged variant should optimize to a
+// straight-forward comparison looking for the natural range of the payload value.
+
+#[unsafe(no_mangle)]
+pub fn mid_bool_is_thing(a: Mid<bool>) -> bool {
+    // CHECK-LABEL: @mid_bool_is_thing(
+    // CHECK: %[[R:.+]] = icmp samesign ult i8 %a, 2
+    // CHECK: ret i1 %[[R]]
+    discriminant_value(&a) == 1
+}
+
+#[unsafe(no_mangle)]
+pub fn mid_ord_is_thing(a: Mid<Ordering>) -> bool {
+    // CHECK-LABEL: @mid_ord_is_thing(
+    // CHECK: %[[R:.+]] = icmp slt i8 %a, 2
+    // CHECK: ret i1 %[[R]]
+    discriminant_value(&a) == 1
+}
+
+#[unsafe(no_mangle)]
+pub fn mid_nz32_is_thing(a: Mid<NonZero<u32>>) -> bool {
+    // CHECK-LABEL: @mid_nz32_is_thing(
+    // CHECK: %[[R:.+]] = icmp eq i32 %a.0, 1
+    // CHECK: ret i1 %[[R]]
+    discriminant_value(&a) == 1
+}
+
+#[unsafe(no_mangle)]
+pub fn mid_ac_is_thing(a: Mid<AC>) -> bool {
+    // CHECK-LABEL: @mid_ac_is_thing(
+    // CHECK: %[[R:.+]] = icmp sgt i8 %a, -1
+    // CHECK: ret i1 %[[R]]
+    discriminant_value(&a) == 1
+}
+
+#[unsafe(no_mangle)]
+pub fn mid_giant_is_thing(a: Mid<Giant>) -> bool {
+    // CHECK-LABEL: @mid_giant_is_thing(
+    // CHECK: %[[R:.+]] = icmp samesign ult i128 %a, 5
+    // CHECK: ret i1 %[[R]]
+    discriminant_value(&a) == 1
+}
diff --git a/tests/codegen/enum/enum-match.rs b/tests/codegen/enum/enum-match.rs
index 98635008d06..57db44ec74e 100644
--- a/tests/codegen/enum/enum-match.rs
+++ b/tests/codegen/enum/enum-match.rs
@@ -41,7 +41,7 @@ pub enum Enum1 {
 // CHECK-NEXT: start:
 // CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %0, -2
 // CHECK-NEXT: %[[REL_VAR_WIDE:.+]] = zext i8 %[[REL_VAR]] to i64
-// CHECK-NEXT: %[[IS_NICHE:.+]] = icmp ult i8 %[[REL_VAR]], 2
+// CHECK-NEXT: %[[IS_NICHE:.+]] = icmp{{( samesign)?}} ugt i8 %0, 1
 // CHECK-NEXT: %[[NICHE_DISCR:.+]] = add nuw nsw i64 %[[REL_VAR_WIDE]], 1
 // CHECK-NEXT: %[[DISCR:.+]] = select i1 %[[IS_NICHE]], i64 %[[NICHE_DISCR]], i64 0
 // CHECK-NEXT: switch i64 %[[DISCR]]
@@ -148,10 +148,10 @@ pub enum MiddleNiche {
 // CHECK-LABEL: define{{( dso_local)?}} noundef{{( range\(i8 -?[0-9]+, -?[0-9]+\))?}} i8 @match4(i8{{.+}}%0)
 // CHECK-NEXT: start:
 // CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %0, -2
-// CHECK-NEXT: %[[IS_NICHE:.+]] = icmp ult i8 %[[REL_VAR]], 5
 // CHECK-NEXT: %[[NOT_IMPOSSIBLE:.+]] = icmp ne i8 %[[REL_VAR]], 2
 // CHECK-NEXT: call void @llvm.assume(i1 %[[NOT_IMPOSSIBLE]])
-// CHECK-NEXT: %[[DISCR:.+]] = select i1 %[[IS_NICHE]], i8 %[[REL_VAR]], i8 2
+// CHECK-NEXT: %[[NOT_NICHE:.+]] = icmp{{( samesign)?}} ult i8 %0, 2
+// CHECK-NEXT: %[[DISCR:.+]] = select i1 %[[NOT_NICHE]], i8 2, i8 %[[REL_VAR]]
 // CHECK-NEXT: switch i8 %[[DISCR]]
 #[no_mangle]
 pub fn match4(e: MiddleNiche) -> u8 {
@@ -167,11 +167,10 @@ pub fn match4(e: MiddleNiche) -> u8 {
 
 // CHECK-LABEL: define{{.+}}i1 @match4_is_c(i8{{.+}}%e)
 // CHECK-NEXT: start
-// CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %e, -2
-// CHECK-NEXT: %[[NOT_NICHE:.+]] = icmp ugt i8 %[[REL_VAR]], 4
-// CHECK-NEXT: %[[NOT_IMPOSSIBLE:.+]] = icmp ne i8 %[[REL_VAR]], 2
+// CHECK-NEXT: %[[NOT_IMPOSSIBLE:.+]] = icmp ne i8 %e, 4
 // CHECK-NEXT: call void @llvm.assume(i1 %[[NOT_IMPOSSIBLE]])
-// CHECK-NEXT: ret i1 %[[NOT_NICHE]]
+// CHECK-NEXT: %[[IS_C:.+]] = icmp{{( samesign)?}} ult i8 %e, 2
+// CHECK-NEXT: ret i1 %[[IS_C]]
 #[no_mangle]
 pub fn match4_is_c(e: MiddleNiche) -> bool {
     // Before #139098, this couldn't optimize out the `select` because it looked
@@ -453,10 +452,10 @@ pub enum HugeVariantIndex {
 // CHECK-NEXT: start:
 // CHECK-NEXT: %[[REL_VAR:.+]] = add{{( nsw)?}} i8 %0, -2
 // CHECK-NEXT: %[[REL_VAR_WIDE:.+]] = zext i8 %[[REL_VAR]] to i64
-// CHECK-NEXT: %[[IS_NICHE:.+]] = icmp ult i8 %[[REL_VAR]], 3
-// CHECK-NEXT: %[[NOT_IMPOSSIBLE:.+]] = icmp ne i8 %[[REL_VAR]], 1
-// CHECK-NEXT: call void @llvm.assume(i1 %[[NOT_IMPOSSIBLE]])
+// CHECK-NEXT: %[[IS_NICHE:.+]] = icmp{{( samesign)?}} ugt i8 %0, 1
 // CHECK-NEXT: %[[NICHE_DISCR:.+]] = add nuw nsw i64 %[[REL_VAR_WIDE]], 257
+// CHECK-NEXT: %[[NOT_IMPOSSIBLE:.+]] = icmp ne i64 %[[NICHE_DISCR]], 258
+// CHECK-NEXT: call void @llvm.assume(i1 %[[NOT_IMPOSSIBLE]])
 // CHECK-NEXT: %[[DISCR:.+]] = select i1 %[[IS_NICHE]], i64 %[[NICHE_DISCR]], i64 258
 // CHECK-NEXT: switch i64 %[[DISCR]],
 // CHECK-NEXT:   i64 257,
@@ -471,3 +470,310 @@ pub fn match5(e: HugeVariantIndex) -> u8 {
         Possible259 => 100,
     }
 }
+
+// Make an enum where the niche tags wrap both as signed and as unsigned, to hit
+// the most-fallback case where there's just nothing smart to do.
+
+pub enum E10Through65 {
+    D10 = 10,
+    D11 = 11,
+    D12 = 12,
+    D13 = 13,
+    D14 = 14,
+    D15 = 15,
+    D16 = 16,
+    D17 = 17,
+    D18 = 18,
+    D19 = 19,
+    D20 = 20,
+    D21 = 21,
+    D22 = 22,
+    D23 = 23,
+    D24 = 24,
+    D25 = 25,
+    D26 = 26,
+    D27 = 27,
+    D28 = 28,
+    D29 = 29,
+    D30 = 30,
+    D31 = 31,
+    D32 = 32,
+    D33 = 33,
+    D34 = 34,
+    D35 = 35,
+    D36 = 36,
+    D37 = 37,
+    D38 = 38,
+    D39 = 39,
+    D40 = 40,
+    D41 = 41,
+    D42 = 42,
+    D43 = 43,
+    D44 = 44,
+    D45 = 45,
+    D46 = 46,
+    D47 = 47,
+    D48 = 48,
+    D49 = 49,
+    D50 = 50,
+    D51 = 51,
+    D52 = 52,
+    D53 = 53,
+    D54 = 54,
+    D55 = 55,
+    D56 = 56,
+    D57 = 57,
+    D58 = 58,
+    D59 = 59,
+    D60 = 60,
+    D61 = 61,
+    D62 = 62,
+    D63 = 63,
+    D64 = 64,
+    D65 = 65,
+}
+
+pub enum Tricky {
+    Untagged(E10Through65),
+    V001,
+    V002,
+    V003,
+    V004,
+    V005,
+    V006,
+    V007,
+    V008,
+    V009,
+    V010,
+    V011,
+    V012,
+    V013,
+    V014,
+    V015,
+    V016,
+    V017,
+    V018,
+    V019,
+    V020,
+    V021,
+    V022,
+    V023,
+    V024,
+    V025,
+    V026,
+    V027,
+    V028,
+    V029,
+    V030,
+    V031,
+    V032,
+    V033,
+    V034,
+    V035,
+    V036,
+    V037,
+    V038,
+    V039,
+    V040,
+    V041,
+    V042,
+    V043,
+    V044,
+    V045,
+    V046,
+    V047,
+    V048,
+    V049,
+    V050,
+    V051,
+    V052,
+    V053,
+    V054,
+    V055,
+    V056,
+    V057,
+    V058,
+    V059,
+    V060,
+    V061,
+    V062,
+    V063,
+    V064,
+    V065,
+    V066,
+    V067,
+    V068,
+    V069,
+    V070,
+    V071,
+    V072,
+    V073,
+    V074,
+    V075,
+    V076,
+    V077,
+    V078,
+    V079,
+    V080,
+    V081,
+    V082,
+    V083,
+    V084,
+    V085,
+    V086,
+    V087,
+    V088,
+    V089,
+    V090,
+    V091,
+    V092,
+    V093,
+    V094,
+    V095,
+    V096,
+    V097,
+    V098,
+    V099,
+    V100,
+    V101,
+    V102,
+    V103,
+    V104,
+    V105,
+    V106,
+    V107,
+    V108,
+    V109,
+    V110,
+    V111,
+    V112,
+    V113,
+    V114,
+    V115,
+    V116,
+    V117,
+    V118,
+    V119,
+    V120,
+    V121,
+    V122,
+    V123,
+    V124,
+    V125,
+    V126,
+    V127,
+    V128,
+    V129,
+    V130,
+    V131,
+    V132,
+    V133,
+    V134,
+    V135,
+    V136,
+    V137,
+    V138,
+    V139,
+    V140,
+    V141,
+    V142,
+    V143,
+    V144,
+    V145,
+    V146,
+    V147,
+    V148,
+    V149,
+    V150,
+    V151,
+    V152,
+    V153,
+    V154,
+    V155,
+    V156,
+    V157,
+    V158,
+    V159,
+    V160,
+    V161,
+    V162,
+    V163,
+    V164,
+    V165,
+    V166,
+    V167,
+    V168,
+    V169,
+    V170,
+    V171,
+    V172,
+    V173,
+    V174,
+    V175,
+    V176,
+    V177,
+    V178,
+    V179,
+    V180,
+    V181,
+    V182,
+    V183,
+    V184,
+    V185,
+    V186,
+    V187,
+    V188,
+    V189,
+    V190,
+    V191,
+    V192,
+    V193,
+    V194,
+    V195,
+    V196,
+    V197,
+    V198,
+    V199,
+    V200,
+}
+
+const _: () = assert!(std::intrinsics::discriminant_value(&Tricky::V100) == 100);
+
+// CHECK-LABEL: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @discriminant6(i8 noundef %e)
+// CHECK-NEXT: start:
+// CHECK-NEXT: %[[REL_VAR:.+]] = add i8 %e, -66
+// CHECK-NEXT: %[[IS_NICHE:.+]] = icmp ult i8 %[[REL_VAR]], -56
+// CHECK-NEXT: %[[TAGGED_DISCR:.+]] = add i8 %e, -65
+// CHECK-NEXT: %[[DISCR:.+]] = select i1 %[[IS_NICHE]], i8 %[[TAGGED_DISCR]], i8 0
+// CHECK-NEXT: ret i8 %[[DISCR]]
+#[no_mangle]
+pub fn discriminant6(e: Tricky) -> u8 {
+    std::intrinsics::discriminant_value(&e) as _
+}
+
+// Case from <https://github.com/rust-lang/rust/issues/104519>,
+// where sign-extension is important.
+
+pub enum OpenResult {
+    Ok(()),
+    Err(()),
+    TransportErr(TransportErr),
+}
+
+#[repr(i32)]
+pub enum TransportErr {
+    UnknownMethod = -2,
+}
+
+#[no_mangle]
+pub fn match7(result: OpenResult) -> u8 {
+    // CHECK-LABEL: define noundef{{( range\(i8 [0-9]+, [0-9]+\))?}} i8 @match7(i32{{.+}}%result)
+    // CHECK-NEXT: start:
+    // CHECK-NEXT: %[[NOT_OK:.+]] = icmp ne i32 %result, -1
+    // CHECK-NEXT: %[[RET:.+]] = zext i1 %[[NOT_OK]] to i8
+    // CHECK-NEXT: ret i8 %[[RET]]
+    match result {
+        OpenResult::Ok(()) => 0,
+        _ => 1,
+    }
+}
diff --git a/tests/codegen/repeat-operand-zero-len.rs b/tests/codegen/repeat-operand-zero-len.rs
new file mode 100644
index 00000000000..b4cec42a07c
--- /dev/null
+++ b/tests/codegen/repeat-operand-zero-len.rs
@@ -0,0 +1,28 @@
+//@ compile-flags: -Copt-level=1 -Cno-prepopulate-passes
+
+// This test is here to hit the `Rvalue::Repeat` case in `codegen_rvalue_operand`.
+// It only applies when the resulting array is a ZST, so the test is written in
+// such a way as to keep MIR optimizations from seeing that fact and removing
+// the local and statement altogether. (At the time of writing, no other codegen
+// test hit that code path, nor did a stage 2 build of the compiler.)
+
+#![crate_type = "lib"]
+
+#[repr(transparent)]
+pub struct Wrapper<T, const N: usize>([T; N]);
+
+// CHECK-LABEL: define {{.+}}do_repeat{{.+}}(i32 noundef %x)
+// CHECK-NEXT: start:
+// CHECK-NOT: alloca
+// CHECK-NEXT: ret void
+#[inline(never)]
+pub fn do_repeat<T: Copy, const N: usize>(x: T) -> Wrapper<T, N> {
+    Wrapper([x; N])
+}
+
+// CHECK-LABEL: @trigger_repeat_zero_len
+#[no_mangle]
+pub fn trigger_repeat_zero_len() -> Wrapper<u32, 0> {
+    // CHECK: call void {{.+}}do_repeat{{.+}}(i32 noundef 4)
+    do_repeat(4)
+}
diff --git a/tests/codegen/repeat-operand-zst-elem.rs b/tests/codegen/repeat-operand-zst-elem.rs
new file mode 100644
index 00000000000..c3637759afa
--- /dev/null
+++ b/tests/codegen/repeat-operand-zst-elem.rs
@@ -0,0 +1,28 @@
+//@ compile-flags: -Copt-level=1 -Cno-prepopulate-passes
+
+// This test is here to hit the `Rvalue::Repeat` case in `codegen_rvalue_operand`.
+// It only applies when the resulting array is a ZST, so the test is written in
+// such a way as to keep MIR optimizations from seeing that fact and removing
+// the local and statement altogether. (At the time of writing, no other codegen
+// test hit that code path, nor did a stage 2 build of the compiler.)
+
+#![crate_type = "lib"]
+
+#[repr(transparent)]
+pub struct Wrapper<T, const N: usize>([T; N]);
+
+// CHECK-LABEL: define {{.+}}do_repeat{{.+}}()
+// CHECK-NEXT: start:
+// CHECK-NOT: alloca
+// CHECK-NEXT: ret void
+#[inline(never)]
+pub fn do_repeat<T: Copy, const N: usize>(x: T) -> Wrapper<T, N> {
+    Wrapper([x; N])
+}
+
+// CHECK-LABEL: @trigger_repeat_zst_elem
+#[no_mangle]
+pub fn trigger_repeat_zst_elem() -> Wrapper<(), 8> {
+    // CHECK: call void {{.+}}do_repeat{{.+}}()
+    do_repeat(())
+}
diff --git a/tests/mir-opt/inline_double_cycle.a.Inline.panic-abort.diff b/tests/mir-opt/inline_double_cycle.a.Inline.panic-abort.diff
new file mode 100644
index 00000000000..90a4a509ac1
--- /dev/null
+++ b/tests/mir-opt/inline_double_cycle.a.Inline.panic-abort.diff
@@ -0,0 +1,48 @@
+- // MIR for `a` before Inline
++ // MIR for `a` after Inline
+  
+  fn a() -> () {
+      let mut _0: ();
+      let _1: ();
+      let mut _2: ();
+      let _3: ();
+      let mut _4: ();
++     let mut _5: fn() {a};
++     let mut _6: fn() {b};
++     scope 1 (inlined <fn() {a} as FnOnce<()>>::call_once - shim(fn() {a})) {
++     }
++     scope 2 (inlined <fn() {b} as FnOnce<()>>::call_once - shim(fn() {b})) {
++     }
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = ();
+-         _1 = <fn() {a} as FnOnce<()>>::call_once(a, move _2) -> [return: bb1, unwind unreachable];
++         StorageLive(_5);
++         _5 = a;
++         _1 = move _5() -> [return: bb1, unwind unreachable];
+      }
+  
+      bb1: {
++         StorageDead(_5);
+          StorageDead(_2);
+          StorageDead(_1);
+          StorageLive(_3);
+          StorageLive(_4);
+          _4 = ();
+-         _3 = <fn() {b} as FnOnce<()>>::call_once(b, move _4) -> [return: bb2, unwind unreachable];
++         StorageLive(_6);
++         _6 = b;
++         _3 = move _6() -> [return: bb2, unwind unreachable];
+      }
+  
+      bb2: {
++         StorageDead(_6);
+          StorageDead(_4);
+          StorageDead(_3);
+          _0 = const ();
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/inline_double_cycle.a.Inline.panic-unwind.diff b/tests/mir-opt/inline_double_cycle.a.Inline.panic-unwind.diff
new file mode 100644
index 00000000000..55da685a3d4
--- /dev/null
+++ b/tests/mir-opt/inline_double_cycle.a.Inline.panic-unwind.diff
@@ -0,0 +1,48 @@
+- // MIR for `a` before Inline
++ // MIR for `a` after Inline
+  
+  fn a() -> () {
+      let mut _0: ();
+      let _1: ();
+      let mut _2: ();
+      let _3: ();
+      let mut _4: ();
++     let mut _5: fn() {a};
++     let mut _6: fn() {b};
++     scope 1 (inlined <fn() {a} as FnOnce<()>>::call_once - shim(fn() {a})) {
++     }
++     scope 2 (inlined <fn() {b} as FnOnce<()>>::call_once - shim(fn() {b})) {
++     }
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = ();
+-         _1 = <fn() {a} as FnOnce<()>>::call_once(a, move _2) -> [return: bb1, unwind continue];
++         StorageLive(_5);
++         _5 = a;
++         _1 = move _5() -> [return: bb1, unwind continue];
+      }
+  
+      bb1: {
++         StorageDead(_5);
+          StorageDead(_2);
+          StorageDead(_1);
+          StorageLive(_3);
+          StorageLive(_4);
+          _4 = ();
+-         _3 = <fn() {b} as FnOnce<()>>::call_once(b, move _4) -> [return: bb2, unwind continue];
++         StorageLive(_6);
++         _6 = b;
++         _3 = move _6() -> [return: bb2, unwind continue];
+      }
+  
+      bb2: {
++         StorageDead(_6);
+          StorageDead(_4);
+          StorageDead(_3);
+          _0 = const ();
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/inline_double_cycle.b.Inline.panic-abort.diff b/tests/mir-opt/inline_double_cycle.b.Inline.panic-abort.diff
new file mode 100644
index 00000000000..2090411276c
--- /dev/null
+++ b/tests/mir-opt/inline_double_cycle.b.Inline.panic-abort.diff
@@ -0,0 +1,48 @@
+- // MIR for `b` before Inline
++ // MIR for `b` after Inline
+  
+  fn b() -> () {
+      let mut _0: ();
+      let _1: ();
+      let mut _2: ();
+      let _3: ();
+      let mut _4: ();
++     let mut _5: fn() {b};
++     let mut _6: fn() {a};
++     scope 1 (inlined <fn() {b} as FnOnce<()>>::call_once - shim(fn() {b})) {
++     }
++     scope 2 (inlined <fn() {a} as FnOnce<()>>::call_once - shim(fn() {a})) {
++     }
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = ();
+-         _1 = <fn() {b} as FnOnce<()>>::call_once(b, move _2) -> [return: bb1, unwind unreachable];
++         StorageLive(_5);
++         _5 = b;
++         _1 = move _5() -> [return: bb1, unwind unreachable];
+      }
+  
+      bb1: {
++         StorageDead(_5);
+          StorageDead(_2);
+          StorageDead(_1);
+          StorageLive(_3);
+          StorageLive(_4);
+          _4 = ();
+-         _3 = <fn() {a} as FnOnce<()>>::call_once(a, move _4) -> [return: bb2, unwind unreachable];
++         StorageLive(_6);
++         _6 = a;
++         _3 = move _6() -> [return: bb2, unwind unreachable];
+      }
+  
+      bb2: {
++         StorageDead(_6);
+          StorageDead(_4);
+          StorageDead(_3);
+          _0 = const ();
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/inline_double_cycle.b.Inline.panic-unwind.diff b/tests/mir-opt/inline_double_cycle.b.Inline.panic-unwind.diff
new file mode 100644
index 00000000000..9e6eef1fa30
--- /dev/null
+++ b/tests/mir-opt/inline_double_cycle.b.Inline.panic-unwind.diff
@@ -0,0 +1,48 @@
+- // MIR for `b` before Inline
++ // MIR for `b` after Inline
+  
+  fn b() -> () {
+      let mut _0: ();
+      let _1: ();
+      let mut _2: ();
+      let _3: ();
+      let mut _4: ();
++     let mut _5: fn() {b};
++     let mut _6: fn() {a};
++     scope 1 (inlined <fn() {b} as FnOnce<()>>::call_once - shim(fn() {b})) {
++     }
++     scope 2 (inlined <fn() {a} as FnOnce<()>>::call_once - shim(fn() {a})) {
++     }
+  
+      bb0: {
+          StorageLive(_1);
+          StorageLive(_2);
+          _2 = ();
+-         _1 = <fn() {b} as FnOnce<()>>::call_once(b, move _2) -> [return: bb1, unwind continue];
++         StorageLive(_5);
++         _5 = b;
++         _1 = move _5() -> [return: bb1, unwind continue];
+      }
+  
+      bb1: {
++         StorageDead(_5);
+          StorageDead(_2);
+          StorageDead(_1);
+          StorageLive(_3);
+          StorageLive(_4);
+          _4 = ();
+-         _3 = <fn() {a} as FnOnce<()>>::call_once(a, move _4) -> [return: bb2, unwind continue];
++         StorageLive(_6);
++         _6 = a;
++         _3 = move _6() -> [return: bb2, unwind continue];
+      }
+  
+      bb2: {
++         StorageDead(_6);
+          StorageDead(_4);
+          StorageDead(_3);
+          _0 = const ();
+          return;
+      }
+  }
+  
diff --git a/tests/mir-opt/inline_double_cycle.rs b/tests/mir-opt/inline_double_cycle.rs
new file mode 100644
index 00000000000..cf3b87cf0ad
--- /dev/null
+++ b/tests/mir-opt/inline_double_cycle.rs
@@ -0,0 +1,22 @@
+// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
+// skip-filecheck
+//@ test-mir-pass: Inline
+//@ edition: 2021
+//@ compile-flags: -Zinline-mir --crate-type=lib
+
+// EMIT_MIR inline_double_cycle.a.Inline.diff
+// EMIT_MIR inline_double_cycle.b.Inline.diff
+
+#![feature(fn_traits)]
+
+#[inline]
+pub fn a() {
+    FnOnce::call_once(a, ());
+    FnOnce::call_once(b, ());
+}
+
+#[inline]
+pub fn b() {
+    FnOnce::call_once(b, ());
+    FnOnce::call_once(a, ());
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/README.md b/tests/run-make/autodiff/type-trees/type-analysis/README.md
new file mode 100644
index 00000000000..c712edfaf50
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/README.md
@@ -0,0 +1,13 @@
+# Autodiff Type-Trees Type Analysis Tests
+
+This directory contains run-make tests for the autodiff type-trees type analysis functionality. These tests verify that the autodiff compiler correctly analyzes and tracks type information for different Rust types during automatic differentiation.
+
+## What These Tests Do
+
+Each test compiles a simple Rust function with the `#[autodiff_reverse]` attribute and verifies that the compiler:
+
+1. **Correctly identifies type information** in the generated LLVM IR
+2. **Tracks type annotations** for variables and operations
+3. **Preserves type context** through the autodiff transformation process
+
+The tests capture the stdout from the autodiff compiler (which contains type analysis information) and verify it matches expected patterns using FileCheck.
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/array/array.check b/tests/run-make/autodiff/type-trees/type-analysis/array/array.check
new file mode 100644
index 00000000000..6e4197692a7
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/array/array.check
@@ -0,0 +1,26 @@
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float, [-1,4]:Float@float, [-1,8]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw i8, ptr %{{[0-9]+}}, i64 4, !dbg !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float, [-1,4]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fadd float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw i8, ptr %{{[0-9]+}}, i64 8, !dbg !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fadd float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float, [-1,4]:Float@float, [-1,8]:Float@float}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float, [-1,4]:Float@float, [-1,8]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw i8, ptr %{{[0-9]+}}, i64 4, !dbg !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float, [-1,4]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fadd float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw i8, ptr %{{[0-9]+}}, i64 8, !dbg !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fadd float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/array/array.rs b/tests/run-make/autodiff/type-trees/type-analysis/array/array.rs
new file mode 100644
index 00000000000..9a859418b10
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/array/array.rs
@@ -0,0 +1,20 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &[f32; 3]) -> f32 {
+    x[0] * x[0] + x[1] * x[1] + x[2] * x[2]
+}
+
+fn main() {
+    let x = [1.0f32, 2.0, 3.0];
+    let mut df_dx = [0.0f32; 3];
+    let out = callee(&x);
+    let out_ = d_square(&x, &mut df_dx, 1.0);
+    assert_eq!(out, out_);
+    assert_eq!(2.0, df_dx[0]);
+    assert_eq!(4.0, df_dx[1]);
+    assert_eq!(6.0, df_dx[2]);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/array/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/array/rmake.rs
new file mode 100644
index 00000000000..d68ab46bb94
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/array/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+    // Compile the Rust file with the required flags, capturing both stdout and stderr
+    let output = rustc()
+        .input("array.rs")
+        .arg("-Zautodiff=Enable,PrintTAFn=callee")
+        .arg("-Zautodiff=NoPostopt")
+        .opt_level("3")
+        .arg("-Clto=fat")
+        .arg("-g")
+        .run();
+
+    let stdout = output.stdout_utf8();
+    let stderr = output.stderr_utf8();
+
+    // Write the outputs to files
+    rfs::write("array.stdout", stdout);
+    rfs::write("array.stderr", stderr);
+
+    // Run FileCheck on the stdout using the check file
+    llvm_filecheck().patterns("array.check").stdin_buf(rfs::read("array.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/array3d/array3d.check b/tests/run-make/autodiff/type-trees/type-analysis/array3d/array3d.check
new file mode 100644
index 00000000000..ed81ad4869a
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/array3d/array3d.check
@@ -0,0 +1,54 @@
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: br label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ 0.000000e+00, %{{[0-9]+}} ], [ %{{[0-9]+}}, %{{[0-9]+}} ]: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = phi i1 [ true, %{{[0-9]+}} ], [ false, %{{[0-9]+}} ]: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = phi i64 [ 0, %{{[0-9]+}} ], [ 1, %{{[0-9]+}} ]: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw [2 x [2 x float]], ptr %{{[0-9]+}}, i64 %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: br label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], [ %{{[0-9]+}}, %{{[0-9]+}} ]: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = phi i1 [ true, %{{[0-9]+}} ], [ false, %{{[0-9]+}} ]: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = phi i64 [ 0, %{{[0-9]+}} ], [ 1, %{{[0-9]+}} ]: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw [2 x float], ptr %{{[0-9]+}}, i64 %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: br label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], [ %{{[0-9]+}}, %{{[0-9]+}} ]: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = phi i1 [ true, %{{[0-9]+}} ], [ false, %{{[0-9]+}} ]: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = phi i64 [ 0, %{{[0-9]+}} ], [ 1, %{{[0-9]+}} ]: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw float, ptr %{{[0-9]+}}, i64 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fadd float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: br label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ 0.000000e+00, %{{[0-9]+}} ], [ %{{[0-9]+}}, %{{[0-9]+}} ]: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = phi i1 [ true, %{{[0-9]+}} ], [ false, %{{[0-9]+}} ]: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = phi i64 [ 0, %{{[0-9]+}} ], [ 1, %{{[0-9]+}} ]: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw [2 x [2 x float]], ptr %{{[0-9]+}}, i64 %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: br label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], [ %{{[0-9]+}}, %{{[0-9]+}} ]: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = phi i1 [ true, %{{[0-9]+}} ], [ false, %{{[0-9]+}} ]: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = phi i64 [ 0, %{{[0-9]+}} ], [ 1, %{{[0-9]+}} ]: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw [2 x float], ptr %{{[0-9]+}}, i64 %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: br label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], [ %{{[0-9]+}}, %{{[0-9]+}} ]: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = phi i1 [ true, %{{[0-9]+}} ], [ false, %{{[0-9]+}} ]: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = phi i64 [ 0, %{{[0-9]+}} ], [ 1, %{{[0-9]+}} ]: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw float, ptr %{{[0-9]+}}, i64 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fadd float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/array3d/array3d.rs b/tests/run-make/autodiff/type-trees/type-analysis/array3d/array3d.rs
new file mode 100644
index 00000000000..a95111a0dae
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/array3d/array3d.rs
@@ -0,0 +1,32 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &[[[f32; 2]; 2]; 2]) -> f32 {
+    let mut sum = 0.0;
+    for i in 0..2 {
+        for j in 0..2 {
+            for k in 0..2 {
+                sum += x[i][j][k] * x[i][j][k];
+            }
+        }
+    }
+    sum
+}
+
+fn main() {
+    let x = [[[1.0f32, 2.0], [3.0, 4.0]], [[5.0, 6.0], [7.0, 8.0]]];
+    let mut df_dx = [[[0.0f32; 2]; 2]; 2];
+    let out = callee(&x);
+    let out_ = d_square(&x, &mut df_dx, 1.0);
+    assert_eq!(out, out_);
+    for i in 0..2 {
+        for j in 0..2 {
+            for k in 0..2 {
+                assert_eq!(df_dx[i][j][k], 2.0 * x[i][j][k]);
+            }
+        }
+    }
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/array3d/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/array3d/rmake.rs
new file mode 100644
index 00000000000..8e75c21c9d6
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/array3d/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+    // Compile the Rust file with the required flags, capturing both stdout and stderr
+    let output = rustc()
+        .input("array3d.rs")
+        .arg("-Zautodiff=Enable,PrintTAFn=callee")
+        .arg("-Zautodiff=NoPostopt")
+        .opt_level("3")
+        .arg("-Clto=fat")
+        .arg("-g")
+        .run();
+
+    let stdout = output.stdout_utf8();
+    let stderr = output.stderr_utf8();
+
+    // Write the outputs to files
+    rfs::write("array3d.stdout", stdout);
+    rfs::write("array3d.stderr", stderr);
+
+    // Run FileCheck on the stdout using the check file
+    llvm_filecheck().patterns("array3d.check").stdin_buf(rfs::read("array3d.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/box/box.check b/tests/run-make/autodiff/type-trees/type-analysis/box/box.check
new file mode 100644
index 00000000000..1911e18a137
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/box/box.check
@@ -0,0 +1,12 @@
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Pointer, [-1,0,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load ptr, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !nonnull !{{[0-9]+}}, !align !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Pointer, [-1,0,0]:Float@float}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Pointer, [-1,0,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load ptr, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !nonnull !{{[0-9]+}}, !align !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/box/box.rs b/tests/run-make/autodiff/type-trees/type-analysis/box/box.rs
new file mode 100644
index 00000000000..658ccffc74e
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/box/box.rs
@@ -0,0 +1,18 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &Box<f32>) -> f32 {
+    **x * **x
+}
+
+fn main() {
+    let x = Box::new(7.0f32);
+    let mut df_dx = Box::new(0.0f32);
+    let out = callee(&x);
+    let out_ = d_square(&x, &mut df_dx, 1.0);
+    assert_eq!(out, out_);
+    assert_eq!(14.0, *df_dx);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/box/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/box/rmake.rs
new file mode 100644
index 00000000000..1e8c8f9ccbd
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/box/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+    // Compile the Rust file with the required flags, capturing both stdout and stderr
+    let output = rustc()
+        .input("box.rs")
+        .arg("-Zautodiff=Enable,PrintTAFn=callee")
+        .arg("-Zautodiff=NoPostopt")
+        .opt_level("3")
+        .arg("-Clto=fat")
+        .arg("-g")
+        .run();
+
+    let stdout = output.stdout_utf8();
+    let stderr = output.stderr_utf8();
+
+    // Write the outputs to files
+    rfs::write("box.stdout", stdout);
+    rfs::write("box.stderr", stderr);
+
+    // Run FileCheck on the stdout using the check file
+    llvm_filecheck().patterns("box.check").stdin_buf(rfs::read("box.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/const_pointer/const_pointer.check b/tests/run-make/autodiff/type-trees/type-analysis/const_pointer/const_pointer.check
new file mode 100644
index 00000000000..e7503453f8e
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/const_pointer/const_pointer.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/const_pointer/const_pointer.rs b/tests/run-make/autodiff/type-trees/type-analysis/const_pointer/const_pointer.rs
new file mode 100644
index 00000000000..8c877bfec05
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/const_pointer/const_pointer.rs
@@ -0,0 +1,18 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: *const f32) -> f32 {
+    unsafe { *x * *x }
+}
+
+fn main() {
+    let x: f32 = 7.0;
+    let out = callee(&x as *const f32);
+    let mut df_dx: f32 = 0.0;
+    let out_ = d_square(&x as *const f32, &mut df_dx, 1.0);
+    assert_eq!(out, out_);
+    assert_eq!(14.0, df_dx);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/const_pointer/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/const_pointer/rmake.rs
new file mode 100644
index 00000000000..ce38c6bd2ae
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/const_pointer/rmake.rs
@@ -0,0 +1,31 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+    // Compile the Rust file with the required flags, capturing both stdout and stderr
+    let output = rustc()
+        .input("const_pointer.rs")
+        .arg("-Zautodiff=Enable,PrintTAFn=callee")
+        .arg("-Zautodiff=NoPostopt")
+        .opt_level("3")
+        .arg("-Clto=fat")
+        .arg("-g")
+        .run();
+
+    let stdout = output.stdout_utf8();
+    let stderr = output.stderr_utf8();
+
+    // Write the outputs to files
+    rfs::write("const_pointer.stdout", stdout);
+    rfs::write("const_pointer.stderr", stderr);
+
+    // Run FileCheck on the stdout using the check file
+    llvm_filecheck()
+        .patterns("const_pointer.check")
+        .stdin_buf(rfs::read("const_pointer.stdout"))
+        .run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/f32/f32.check b/tests/run-make/autodiff/type-trees/type-analysis/f32/f32.check
new file mode 100644
index 00000000000..0cc0ffda43d
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/f32/f32.check
@@ -0,0 +1,12 @@
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {} 
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/f32/f32.rs b/tests/run-make/autodiff/type-trees/type-analysis/f32/f32.rs
new file mode 100644
index 00000000000..b945821934a
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/f32/f32.rs
@@ -0,0 +1,19 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &f32) -> f32 {
+    *x * *x
+}
+
+fn main() {
+    let x: f32 = 7.0;
+    let mut df_dx: f32 = 0.0;
+    let out = callee(&x);
+    let out_ = d_square(&x, &mut df_dx, 1.0);
+
+    assert_eq!(out, out_);
+    assert_eq!(14.0, df_dx);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/f32/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/f32/rmake.rs
new file mode 100644
index 00000000000..d7e49219da6
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/f32/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+    // Compile the Rust file with the required flags, capturing both stdout and stderr
+    let output = rustc()
+        .input("f32.rs")
+        .arg("-Zautodiff=Enable,PrintTAFn=callee")
+        .arg("-Zautodiff=NoPostopt")
+        .opt_level("3")
+        .arg("-Clto=fat")
+        .arg("-g")
+        .run();
+
+    let stdout = output.stdout_utf8();
+    let stderr = output.stderr_utf8();
+
+    // Write the outputs to files
+    rfs::write("f32.stdout", stdout);
+    rfs::write("f32.stderr", stderr);
+
+    // Run FileCheck on the stdout using the check file
+    llvm_filecheck().patterns("f32.check").stdin_buf(rfs::read("f32.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/f64/f64.check b/tests/run-make/autodiff/type-trees/type-analysis/f64/f64.check
new file mode 100644
index 00000000000..efc49da5ffc
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/f64/f64.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Float@double} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@double}
+// CHECK-DAG: %{{[0-9]+}} = load double, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@double}
+// CHECK-DAG: %{{[0-9]+}} = fmul double %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@double}
+// CHECK-DAG: ret double %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Float@double} |{[-1]:Pointer, [-1,0]:Float@double}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@double}
+// CHECK-DAG: %{{[0-9]+}} = load double, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@double}
+// CHECK-DAG: %{{[0-9]+}} = fmul double %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@double}
+// CHECK-DAG: ret double %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/f64/f64.rs b/tests/run-make/autodiff/type-trees/type-analysis/f64/f64.rs
new file mode 100644
index 00000000000..9b47569652e
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/f64/f64.rs
@@ -0,0 +1,20 @@
+#![feature(autodiff)]
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_callee, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &f64) -> f64 {
+    x * x
+}
+
+fn main() {
+    let x = std::hint::black_box(3.0);
+
+    let output = callee(&x);
+    assert_eq!(9.0, output);
+
+    let mut df_dx = 0.0;
+    let output_ = d_callee(&x, &mut df_dx, 1.0);
+    assert_eq!(output, output_);
+    assert_eq!(6.0, df_dx);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/f64/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/f64/rmake.rs
new file mode 100644
index 00000000000..8bf92b8c1bd
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/f64/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+    // Compile the Rust file with the required flags, capturing both stdout and stderr
+    let output = rustc()
+        .input("f64.rs")
+        .arg("-Zautodiff=Enable,PrintTAFn=callee")
+        .arg("-Zautodiff=NoPostopt")
+        .opt_level("3")
+        .arg("-Clto=fat")
+        .arg("-g")
+        .run();
+
+    let stdout = output.stdout_utf8();
+    let stderr = output.stderr_utf8();
+
+    // Write the outputs to files
+    rfs::write("f64.stdout", stdout);
+    rfs::write("f64.stderr", stderr);
+
+    // Run FileCheck on the stdout using the check file
+    llvm_filecheck().patterns("f64.check").stdin_buf(rfs::read("f64.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/i128/i128.check b/tests/run-make/autodiff/type-trees/type-analysis/i128/i128.check
new file mode 100644
index 00000000000..31a07219e74
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/i128/i128.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer, [-1,8]:Integer, [-1,9]:Integer, [-1,10]:Integer, [-1,11]:Integer, [-1,12]:Integer, [-1,13]:Integer, [-1,14]:Integer, [-1,15]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i128, ptr %{{[0-9]+}}, align 16, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i128 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i128 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer, [-1,8]:Integer, [-1,9]:Integer, [-1,10]:Integer, [-1,11]:Integer, [-1,12]:Integer, [-1,13]:Integer, [-1,14]:Integer, [-1,15]:Integer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer, [-1,8]:Integer, [-1,9]:Integer, [-1,10]:Integer, [-1,11]:Integer, [-1,12]:Integer, [-1,13]:Integer, [-1,14]:Integer, [-1,15]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i128, ptr %{{[0-9]+}}, align 16, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i128 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i128 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/i128/i128.rs b/tests/run-make/autodiff/type-trees/type-analysis/i128/i128.rs
new file mode 100644
index 00000000000..19dfbbb22db
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/i128/i128.rs
@@ -0,0 +1,14 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &i128) -> i128 {
+    *x * *x
+}
+
+fn main() {
+    let x: i128 = 7;
+    let _ = callee(&x);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/i128/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/i128/rmake.rs
new file mode 100644
index 00000000000..21e8698634f
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/i128/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+    // Compile the Rust file with the required flags, capturing both stdout and stderr
+    let output = rustc()
+        .input("i128.rs")
+        .arg("-Zautodiff=Enable,PrintTAFn=callee")
+        .arg("-Zautodiff=NoPostopt")
+        .opt_level("3")
+        .arg("-Clto=fat")
+        .arg("-g")
+        .run();
+
+    let stdout = output.stdout_utf8();
+    let stderr = output.stderr_utf8();
+
+    // Write the outputs to files
+    rfs::write("i128.stdout", stdout);
+    rfs::write("i128.stderr", stderr);
+
+    // Run FileCheck on the stdout using the check file
+    llvm_filecheck().patterns("i128.check").stdin_buf(rfs::read("i128.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/i16/i16.check b/tests/run-make/autodiff/type-trees/type-analysis/i16/i16.check
new file mode 100644
index 00000000000..8cc299532c5
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/i16/i16.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i16, ptr %{{[0-9]+}}, align 2, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i16 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i16 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i16, ptr %{{[0-9]+}}, align 2, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i16 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i16 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/i16/i16.rs b/tests/run-make/autodiff/type-trees/type-analysis/i16/i16.rs
new file mode 100644
index 00000000000..82099198a2e
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/i16/i16.rs
@@ -0,0 +1,14 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &i16) -> i16 {
+    *x * *x
+}
+
+fn main() {
+    let x: i16 = 7;
+    let _ = callee(&x);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/i16/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/i16/rmake.rs
new file mode 100644
index 00000000000..a2875a8c573
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/i16/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+    // Compile the Rust file with the required flags, capturing both stdout and stderr
+    let output = rustc()
+        .input("i16.rs")
+        .arg("-Zautodiff=Enable,PrintTAFn=callee")
+        .arg("-Zautodiff=NoPostopt")
+        .opt_level("3")
+        .arg("-Clto=fat")
+        .arg("-g")
+        .run();
+
+    let stdout = output.stdout_utf8();
+    let stderr = output.stderr_utf8();
+
+    // Write the outputs to files
+    rfs::write("i16.stdout", stdout);
+    rfs::write("i16.stderr", stderr);
+
+    // Run FileCheck on the stdout using the check file
+    llvm_filecheck().patterns("i16.check").stdin_buf(rfs::read("i16.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/i32/i32.check b/tests/run-make/autodiff/type-trees/type-analysis/i32/i32.check
new file mode 100644
index 00000000000..4df982887d7
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/i32/i32.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i32, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i32 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i32 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i32, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i32 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i32 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/i32/i32.rs b/tests/run-make/autodiff/type-trees/type-analysis/i32/i32.rs
new file mode 100644
index 00000000000..e95068d5c49
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/i32/i32.rs
@@ -0,0 +1,14 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &i32) -> i32 {
+    *x * *x
+}
+
+fn main() {
+    let x: i32 = 7;
+    let _ = callee(&x);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/i32/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/i32/rmake.rs
new file mode 100644
index 00000000000..857017feeab
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/i32/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+    // Compile the Rust file with the required flags, capturing both stdout and stderr
+    let output = rustc()
+        .input("i32.rs")
+        .arg("-Zautodiff=Enable,PrintTAFn=callee")
+        .arg("-Zautodiff=NoPostopt")
+        .opt_level("3")
+        .arg("-Clto=fat")
+        .arg("-g")
+        .run();
+
+    let stdout = output.stdout_utf8();
+    let stderr = output.stderr_utf8();
+
+    // Write the outputs to files
+    rfs::write("i32.stdout", stdout);
+    rfs::write("i32.stderr", stderr);
+
+    // Run FileCheck on the stdout using the check file
+    llvm_filecheck().patterns("i32.check").stdin_buf(rfs::read("i32.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/i8/i8.check b/tests/run-make/autodiff/type-trees/type-analysis/i8/i8.check
new file mode 100644
index 00000000000..651a2085bc6
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/i8/i8.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i8, ptr %{{[0-9]+}}, align 1, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i8 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i8 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i8, ptr %{{[0-9]+}}, align 1, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i8 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i8 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/i8/i8.rs b/tests/run-make/autodiff/type-trees/type-analysis/i8/i8.rs
new file mode 100644
index 00000000000..afc0cad703c
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/i8/i8.rs
@@ -0,0 +1,14 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &i8) -> i8 {
+    *x * *x
+}
+
+fn main() {
+    let x: i8 = 7;
+    let _ = callee(&x);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/i8/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/i8/rmake.rs
new file mode 100644
index 00000000000..6551e2d6c4e
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/i8/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+    // Compile the Rust file with the required flags, capturing both stdout and stderr
+    let output = rustc()
+        .input("i8.rs")
+        .arg("-Zautodiff=Enable,PrintTAFn=callee")
+        .arg("-Zautodiff=NoPostopt")
+        .opt_level("3")
+        .arg("-Clto=fat")
+        .arg("-g")
+        .run();
+
+    let stdout = output.stdout_utf8();
+    let stderr = output.stderr_utf8();
+
+    // Write the outputs to files
+    rfs::write("i8.stdout", stdout);
+    rfs::write("i8.stderr", stderr);
+
+    // Run FileCheck on the stdout using the check file
+    llvm_filecheck().patterns("i8.check").stdin_buf(rfs::read("i8.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/isize/isize.check b/tests/run-make/autodiff/type-trees/type-analysis/isize/isize.check
new file mode 100644
index 00000000000..40ee6edc02c
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/isize/isize.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i64, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i64 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i64 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i64, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i64 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i64 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/isize/isize.rs b/tests/run-make/autodiff/type-trees/type-analysis/isize/isize.rs
new file mode 100644
index 00000000000..dd160984a4e
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/isize/isize.rs
@@ -0,0 +1,14 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &isize) -> isize {
+    *x * *x
+}
+
+fn main() {
+    let x: isize = 7;
+    let _ = callee(&x);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/isize/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/isize/rmake.rs
new file mode 100644
index 00000000000..09277f63ed4
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/isize/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+    // Compile the Rust file with the required flags, capturing both stdout and stderr
+    let output = rustc()
+        .input("isize.rs")
+        .arg("-Zautodiff=Enable,PrintTAFn=callee")
+        .arg("-Zautodiff=NoPostopt")
+        .opt_level("3")
+        .arg("-Clto=fat")
+        .arg("-g")
+        .run();
+
+    let stdout = output.stdout_utf8();
+    let stderr = output.stderr_utf8();
+
+    // Write the outputs to files
+    rfs::write("isize.stdout", stdout);
+    rfs::write("isize.stderr", stderr);
+
+    // Run FileCheck on the stdout using the check file
+    llvm_filecheck().patterns("isize.check").stdin_buf(rfs::read("isize.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/mut_pointer/mut_pointer.check b/tests/run-make/autodiff/type-trees/type-analysis/mut_pointer/mut_pointer.check
new file mode 100644
index 00000000000..e7503453f8e
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/mut_pointer/mut_pointer.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/mut_pointer/mut_pointer.rs b/tests/run-make/autodiff/type-trees/type-analysis/mut_pointer/mut_pointer.rs
new file mode 100644
index 00000000000..2b672f6d3f8
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/mut_pointer/mut_pointer.rs
@@ -0,0 +1,18 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: *mut f32) -> f32 {
+    unsafe { *x * *x }
+}
+
+fn main() {
+    let mut x: f32 = 7.0;
+    let out = callee(&mut x as *mut f32);
+    let mut df_dx: f32 = 0.0;
+    let out_ = d_square(&mut x as *mut f32, &mut df_dx, 1.0);
+    assert_eq!(out, out_);
+    assert_eq!(14.0, df_dx);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/mut_pointer/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/mut_pointer/rmake.rs
new file mode 100644
index 00000000000..4d5a5042141
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/mut_pointer/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+    // Compile the Rust file with the required flags, capturing both stdout and stderr
+    let output = rustc()
+        .input("mut_pointer.rs")
+        .arg("-Zautodiff=Enable,PrintTAFn=callee")
+        .arg("-Zautodiff=NoPostopt")
+        .opt_level("3")
+        .arg("-Clto=fat")
+        .arg("-g")
+        .run();
+
+    let stdout = output.stdout_utf8();
+    let stderr = output.stderr_utf8();
+
+    // Write the outputs to files
+    rfs::write("mut_pointer.stdout", stdout);
+    rfs::write("mut_pointer.stderr", stderr);
+
+    // Run FileCheck on the stdout using the check file
+    llvm_filecheck().patterns("mut_pointer.check").stdin_buf(rfs::read("mut_pointer.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/mut_ref/mut_ref.check b/tests/run-make/autodiff/type-trees/type-analysis/mut_ref/mut_ref.check
new file mode 100644
index 00000000000..e7503453f8e
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/mut_ref/mut_ref.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/mut_ref/mut_ref.rs b/tests/run-make/autodiff/type-trees/type-analysis/mut_ref/mut_ref.rs
new file mode 100644
index 00000000000..7019e3f71ed
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/mut_ref/mut_ref.rs
@@ -0,0 +1,18 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &mut f32) -> f32 {
+    *x * *x
+}
+
+fn main() {
+    let mut x: f32 = 7.0;
+    let mut df_dx: f32 = 0.0;
+    let out = callee(&mut x);
+    let out_ = d_square(&mut x, &mut df_dx, 1.0);
+    assert_eq!(out, out_);
+    assert_eq!(14.0, df_dx);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/mut_ref/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/mut_ref/rmake.rs
new file mode 100644
index 00000000000..13668c54e78
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/mut_ref/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+    // Compile the Rust file with the required flags, capturing both stdout and stderr
+    let output = rustc()
+        .input("mut_ref.rs")
+        .arg("-Zautodiff=Enable,PrintTAFn=callee")
+        .arg("-Zautodiff=NoPostopt")
+        .opt_level("3")
+        .arg("-Clto=fat")
+        .arg("-g")
+        .run();
+
+    let stdout = output.stdout_utf8();
+    let stderr = output.stderr_utf8();
+
+    // Write the outputs to files
+    rfs::write("mut_ref.stdout", stdout);
+    rfs::write("mut_ref.stderr", stderr);
+
+    // Run FileCheck on the stdout using the check file
+    llvm_filecheck().patterns("mut_ref.check").stdin_buf(rfs::read("mut_ref.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/ref/ref.check b/tests/run-make/autodiff/type-trees/type-analysis/ref/ref.check
new file mode 100644
index 00000000000..e7503453f8e
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/ref/ref.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/ref/ref.rs b/tests/run-make/autodiff/type-trees/type-analysis/ref/ref.rs
new file mode 100644
index 00000000000..3ced164b86f
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/ref/ref.rs
@@ -0,0 +1,18 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &f32) -> f32 {
+    *x * *x
+}
+
+fn main() {
+    let x: f32 = 7.0;
+    let mut df_dx: f32 = 0.0;
+    let out = callee(&x);
+    let out_ = d_square(&x, &mut df_dx, 1.0);
+    assert_eq!(out, out_);
+    assert_eq!(14.0, df_dx);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/ref/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/ref/rmake.rs
new file mode 100644
index 00000000000..b68e4e5b8ac
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/ref/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+    // Compile the Rust file with the required flags, capturing both stdout and stderr
+    let output = rustc()
+        .input("ref.rs")
+        .arg("-Zautodiff=Enable,PrintTAFn=callee")
+        .arg("-Zautodiff=NoPostopt")
+        .opt_level("3")
+        .arg("-Clto=fat")
+        .arg("-g")
+        .run();
+
+    let stdout = output.stdout_utf8();
+    let stderr = output.stderr_utf8();
+
+    // Write the outputs to files
+    rfs::write("ref.stdout", stdout);
+    rfs::write("ref.stderr", stderr);
+
+    // Run FileCheck on the stdout using the check file
+    llvm_filecheck().patterns("ref.check").stdin_buf(rfs::read("ref.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/struct/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/struct/rmake.rs
new file mode 100644
index 00000000000..4073f7554cc
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/struct/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+    // Compile the Rust file with the required flags, capturing both stdout and stderr
+    let output = rustc()
+        .input("struct.rs")
+        .arg("-Zautodiff=Enable,PrintTAFn=callee")
+        .arg("-Zautodiff=NoPostopt")
+        .opt_level("3")
+        .arg("-Clto=fat")
+        .arg("-g")
+        .run();
+
+    let stdout = output.stdout_utf8();
+    let stderr = output.stderr_utf8();
+
+    // Write the outputs to files
+    rfs::write("struct.stdout", stdout);
+    rfs::write("struct.stderr", stderr);
+
+    // Run FileCheck on the stdout using the check file
+    llvm_filecheck().patterns("struct.check").stdin_buf(rfs::read("struct.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/struct/struct.check b/tests/run-make/autodiff/type-trees/type-analysis/struct/struct.check
new file mode 100644
index 00000000000..e7503453f8e
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/struct/struct.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/struct/struct.rs b/tests/run-make/autodiff/type-trees/type-analysis/struct/struct.rs
new file mode 100644
index 00000000000..52cb6a9a6b9
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/struct/struct.rs
@@ -0,0 +1,23 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[derive(Copy, Clone)]
+struct MyStruct {
+    f: f32,
+}
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &MyStruct) -> f32 {
+    x.f * x.f
+}
+
+fn main() {
+    let x = MyStruct { f: 7.0 };
+    let mut df_dx = MyStruct { f: 0.0 };
+    let out = callee(&x);
+    let out_ = d_square(&x, &mut df_dx, 1.0);
+    assert_eq!(out, out_);
+    assert_eq!(14.0, df_dx.f);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/u128/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/u128/rmake.rs
new file mode 100644
index 00000000000..3f605d47c68
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/u128/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+    // Compile the Rust file with the required flags, capturing both stdout and stderr
+    let output = rustc()
+        .input("u128.rs")
+        .arg("-Zautodiff=Enable,PrintTAFn=callee")
+        .arg("-Zautodiff=NoPostopt")
+        .opt_level("3")
+        .arg("-Clto=fat")
+        .arg("-g")
+        .run();
+
+    let stdout = output.stdout_utf8();
+    let stderr = output.stderr_utf8();
+
+    // Write the outputs to files
+    rfs::write("u128.stdout", stdout);
+    rfs::write("u128.stderr", stderr);
+
+    // Run FileCheck on the stdout using the check file
+    llvm_filecheck().patterns("u128.check").stdin_buf(rfs::read("u128.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/u128/u128.check b/tests/run-make/autodiff/type-trees/type-analysis/u128/u128.check
new file mode 100644
index 00000000000..31a07219e74
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/u128/u128.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer, [-1,8]:Integer, [-1,9]:Integer, [-1,10]:Integer, [-1,11]:Integer, [-1,12]:Integer, [-1,13]:Integer, [-1,14]:Integer, [-1,15]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i128, ptr %{{[0-9]+}}, align 16, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i128 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i128 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer, [-1,8]:Integer, [-1,9]:Integer, [-1,10]:Integer, [-1,11]:Integer, [-1,12]:Integer, [-1,13]:Integer, [-1,14]:Integer, [-1,15]:Integer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer, [-1,8]:Integer, [-1,9]:Integer, [-1,10]:Integer, [-1,11]:Integer, [-1,12]:Integer, [-1,13]:Integer, [-1,14]:Integer, [-1,15]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i128, ptr %{{[0-9]+}}, align 16, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i128 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i128 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/u128/u128.rs b/tests/run-make/autodiff/type-trees/type-analysis/u128/u128.rs
new file mode 100644
index 00000000000..d19d2faa51b
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/u128/u128.rs
@@ -0,0 +1,14 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &u128) -> u128 {
+    *x * *x
+}
+
+fn main() {
+    let x: u128 = 7;
+    let _ = callee(&x);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/u16/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/u16/rmake.rs
new file mode 100644
index 00000000000..0051f6f9795
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/u16/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+    // Compile the Rust file with the required flags, capturing both stdout and stderr
+    let output = rustc()
+        .input("u16.rs")
+        .arg("-Zautodiff=Enable,PrintTAFn=callee")
+        .arg("-Zautodiff=NoPostopt")
+        .opt_level("3")
+        .arg("-Clto=fat")
+        .arg("-g")
+        .run();
+
+    let stdout = output.stdout_utf8();
+    let stderr = output.stderr_utf8();
+
+    // Write the outputs to files
+    rfs::write("u16.stdout", stdout);
+    rfs::write("u16.stderr", stderr);
+
+    // Run FileCheck on the stdout using the check file
+    llvm_filecheck().patterns("u16.check").stdin_buf(rfs::read("u16.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/u16/u16.check b/tests/run-make/autodiff/type-trees/type-analysis/u16/u16.check
new file mode 100644
index 00000000000..8cc299532c5
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/u16/u16.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i16, ptr %{{[0-9]+}}, align 2, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i16 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i16 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i16, ptr %{{[0-9]+}}, align 2, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i16 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i16 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/u16/u16.rs b/tests/run-make/autodiff/type-trees/type-analysis/u16/u16.rs
new file mode 100644
index 00000000000..f5f5b50622b
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/u16/u16.rs
@@ -0,0 +1,14 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &u16) -> u16 {
+    *x * *x
+}
+
+fn main() {
+    let x: u16 = 7;
+    let _ = callee(&x);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/u32/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/u32/rmake.rs
new file mode 100644
index 00000000000..0882230b1c6
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/u32/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+    // Compile the Rust file with the required flags, capturing both stdout and stderr
+    let output = rustc()
+        .input("u32.rs")
+        .arg("-Zautodiff=Enable,PrintTAFn=callee")
+        .arg("-Zautodiff=NoPostopt")
+        .opt_level("3")
+        .arg("-Clto=fat")
+        .arg("-g")
+        .run();
+
+    let stdout = output.stdout_utf8();
+    let stderr = output.stderr_utf8();
+
+    // Write the outputs to files
+    rfs::write("u32.stdout", stdout);
+    rfs::write("u32.stderr", stderr);
+
+    // Run FileCheck on the stdout using the check file
+    llvm_filecheck().patterns("u32.check").stdin_buf(rfs::read("u32.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/u32/u32.check b/tests/run-make/autodiff/type-trees/type-analysis/u32/u32.check
new file mode 100644
index 00000000000..4df982887d7
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/u32/u32.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i32, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i32 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i32 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i32, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i32 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i32 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/u32/u32.rs b/tests/run-make/autodiff/type-trees/type-analysis/u32/u32.rs
new file mode 100644
index 00000000000..66b4c222c51
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/u32/u32.rs
@@ -0,0 +1,14 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &u32) -> u32 {
+    *x * *x
+}
+
+fn main() {
+    let x: u32 = 7;
+    let _ = callee(&x);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/u8/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/u8/rmake.rs
new file mode 100644
index 00000000000..100b4f498f2
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/u8/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+    // Compile the Rust file with the required flags, capturing both stdout and stderr
+    let output = rustc()
+        .input("u8.rs")
+        .arg("-Zautodiff=Enable,PrintTAFn=callee")
+        .arg("-Zautodiff=NoPostopt")
+        .opt_level("3")
+        .arg("-Clto=fat")
+        .arg("-g")
+        .run();
+
+    let stdout = output.stdout_utf8();
+    let stderr = output.stderr_utf8();
+
+    // Write the outputs to files
+    rfs::write("u8.stdout", stdout);
+    rfs::write("u8.stderr", stderr);
+
+    // Run FileCheck on the stdout using the check file
+    llvm_filecheck().patterns("u8.check").stdin_buf(rfs::read("u8.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/u8/u8.check b/tests/run-make/autodiff/type-trees/type-analysis/u8/u8.check
new file mode 100644
index 00000000000..651a2085bc6
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/u8/u8.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i8, ptr %{{[0-9]+}}, align 1, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i8 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i8 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i8, ptr %{{[0-9]+}}, align 1, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i8 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i8 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/u8/u8.rs b/tests/run-make/autodiff/type-trees/type-analysis/u8/u8.rs
new file mode 100644
index 00000000000..de9cdeb631e
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/u8/u8.rs
@@ -0,0 +1,14 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &u8) -> u8 {
+    *x * *x
+}
+
+fn main() {
+    let x: u8 = 7;
+    let _ = callee(&x);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/union/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/union/rmake.rs
new file mode 100644
index 00000000000..67f0fe18481
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/union/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+    // Compile the Rust file with the required flags, capturing both stdout and stderr
+    let output = rustc()
+        .input("union.rs")
+        .arg("-Zautodiff=Enable,PrintTAFn=callee")
+        .arg("-Zautodiff=NoPostopt")
+        .opt_level("3")
+        .arg("-Clto=fat")
+        .arg("-g")
+        .run();
+
+    let stdout = output.stdout_utf8();
+    let stderr = output.stderr_utf8();
+
+    // Write the outputs to files
+    rfs::write("union.stdout", stdout);
+    rfs::write("union.stderr", stderr);
+
+    // Run FileCheck on the stdout using the check file
+    llvm_filecheck().patterns("union.check").stdin_buf(rfs::read("union.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/union/union.check b/tests/run-make/autodiff/type-trees/type-analysis/union/union.check
new file mode 100644
index 00000000000..e7503453f8e
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/union/union.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer, [-1,0]:Float@float}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fmul float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/union/union.rs b/tests/run-make/autodiff/type-trees/type-analysis/union/union.rs
new file mode 100644
index 00000000000..8d997f8c839
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/union/union.rs
@@ -0,0 +1,20 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[allow(dead_code)]
+union MyUnion {
+    f: f32,
+    i: i32,
+}
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &MyUnion) -> f32 {
+    unsafe { x.f * x.f }
+}
+
+fn main() {
+    let x = MyUnion { f: 7.0 };
+    let _ = callee(&x);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/usize/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/usize/rmake.rs
new file mode 100644
index 00000000000..d5cfd708c3a
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/usize/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+    // Compile the Rust file with the required flags, capturing both stdout and stderr
+    let output = rustc()
+        .input("usize.rs")
+        .arg("-Zautodiff=Enable,PrintTAFn=callee")
+        .arg("-Zautodiff=NoPostopt")
+        .opt_level("3")
+        .arg("-Clto=fat")
+        .arg("-g")
+        .run();
+
+    let stdout = output.stdout_utf8();
+    let stderr = output.stderr_utf8();
+
+    // Write the outputs to files
+    rfs::write("usize.stdout", stdout);
+    rfs::write("usize.stderr", stderr);
+
+    // Run FileCheck on the stdout using the check file
+    llvm_filecheck().patterns("usize.check").stdin_buf(rfs::read("usize.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/usize/usize.check b/tests/run-make/autodiff/type-trees/type-analysis/usize/usize.check
new file mode 100644
index 00000000000..40ee6edc02c
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/usize/usize.check
@@ -0,0 +1,10 @@
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i64, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i64 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i64 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK: callee - {[-1]:Integer} |{[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Integer, [-1,1]:Integer, [-1,2]:Integer, [-1,3]:Integer, [-1,4]:Integer, [-1,5]:Integer, [-1,6]:Integer, [-1,7]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = load i64, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = mul i64 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: ret i64 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/usize/usize.rs b/tests/run-make/autodiff/type-trees/type-analysis/usize/usize.rs
new file mode 100644
index 00000000000..8e758be57d4
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/usize/usize.rs
@@ -0,0 +1,14 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(x: &usize) -> usize {
+    *x * *x
+}
+
+fn main() {
+    let x: usize = 7;
+    let _ = callee(&x);
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/vec/rmake.rs b/tests/run-make/autodiff/type-trees/type-analysis/vec/rmake.rs
new file mode 100644
index 00000000000..94491fab8d6
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/vec/rmake.rs
@@ -0,0 +1,28 @@
+//@ needs-enzyme
+//@ ignore-cross-compile
+
+use std::fs;
+
+use run_make_support::{llvm_filecheck, rfs, rustc};
+
+fn main() {
+    // Compile the Rust file with the required flags, capturing both stdout and stderr
+    let output = rustc()
+        .input("vec.rs")
+        .arg("-Zautodiff=Enable,PrintTAFn=callee")
+        .arg("-Zautodiff=NoPostopt")
+        .opt_level("3")
+        .arg("-Clto=fat")
+        .arg("-g")
+        .run();
+
+    let stdout = output.stdout_utf8();
+    let stderr = output.stderr_utf8();
+
+    // Write the outputs to files
+    rfs::write("vec.stdout", stdout);
+    rfs::write("vec.stderr", stderr);
+
+    // Run FileCheck on the stdout using the check file
+    llvm_filecheck().patterns("vec.check").stdin_buf(rfs::read("vec.stdout")).run();
+}
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/vec/vec.check b/tests/run-make/autodiff/type-trees/type-analysis/vec/vec.check
new file mode 100644
index 00000000000..dcf9508b69d
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/vec/vec.check
@@ -0,0 +1,18 @@
+// CHECK: callee - {[-1]:Float@float} |{[-1]:Pointer}:{}
+// CHECK: ptr %{{[0-9]+}}: {[-1]:Pointer}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw i8, ptr %{{[0-9]+}}, i64 8, !dbg !{{[0-9]+}}: {[-1]:Pointer}
+// CHECK-DAG: %{{[0-9]+}} = load ptr, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !nonnull !102, !noundef !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw i8, ptr %{{[0-9]+}}, i64 16, !dbg !{{[0-9]+}}: {[-1]:Pointer}
+// CHECK-DAG: %{{[0-9]+}} = load i64, ptr %{{[0-9]+}}, align 8, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = icmp eq i64 %{{[0-9]+}}, 0, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi i64 [ %{{[0-9]+}}, %{{[0-9]+}} ], [ 0, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ %{{[0-9]+}}, %{{[0-9]+}} ], [ -0.000000e+00, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = getelementptr inbounds nuw float, ptr %{{[0-9]+}}, i64 %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Pointer, [-1,0]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = load float, ptr %{{[0-9]+}}, align 4, !dbg !{{[0-9]+}}, !noundef !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = fadd float %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: %{{[0-9]+}} = add nuw i64 %{{[0-9]+}}, 1, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: %{{[0-9]+}} = icmp eq i64 %{{[0-9]+}}, %{{[0-9]+}}, !dbg !{{[0-9]+}}: {[-1]:Integer}
+// CHECK-DAG: br i1 %{{[0-9]+}}, label %{{[0-9]+}}, label %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
+// CHECK-DAG: %{{[0-9]+}} = phi float [ -0.000000e+00, %{{[0-9]+}} ], [ %{{[0-9]+}}, %{{[0-9]+}} ], !dbg !{{[0-9]+}}: {[-1]:Float@float}
+// CHECK-DAG: ret float %{{[0-9]+}}, !dbg !{{[0-9]+}}: {}
\ No newline at end of file
diff --git a/tests/run-make/autodiff/type-trees/type-analysis/vec/vec.rs b/tests/run-make/autodiff/type-trees/type-analysis/vec/vec.rs
new file mode 100644
index 00000000000..b60c2a88064
--- /dev/null
+++ b/tests/run-make/autodiff/type-trees/type-analysis/vec/vec.rs
@@ -0,0 +1,14 @@
+#![feature(autodiff)]
+
+use std::autodiff::autodiff_reverse;
+
+#[autodiff_reverse(d_square, Duplicated, Active)]
+#[no_mangle]
+fn callee(arg: &std::vec::Vec<f32>) -> f32 {
+    arg.iter().sum()
+}
+
+fn main() {
+    let v = vec![1.0f32, 2.0, 3.0];
+    let _ = callee(&v);
+}
diff --git a/tests/run-make/link-eh-frame-terminator/rmake.rs b/tests/run-make/link-eh-frame-terminator/rmake.rs
index 6bfae386ea1..06b77f011ec 100644
--- a/tests/run-make/link-eh-frame-terminator/rmake.rs
+++ b/tests/run-make/link-eh-frame-terminator/rmake.rs
@@ -9,6 +9,7 @@
 //@ ignore-32bit
 // Reason: the usage of a large array in the test causes an out-of-memory
 // error on 32 bit systems.
+//@ ignore-cross-compile
 
 use run_make_support::{bin_name, llvm_objdump, run, rustc};
 
diff --git a/tests/rustdoc-js-std/alias-lev.js b/tests/rustdoc-js-std/alias-lev.js
new file mode 100644
index 00000000000..17f3dc25d76
--- /dev/null
+++ b/tests/rustdoc-js-std/alias-lev.js
@@ -0,0 +1,11 @@
+// This test ensures that aliases are also allowed to be partially matched.
+
+// ignore-order
+
+const EXPECTED = {
+    // The full alias name is `getcwd`.
+    'query': 'getcw',
+    'others': [
+        { 'path': 'std::env', 'name': 'current_dir', 'alias': 'getcwd' },
+    ],
+};
diff --git a/tests/rustdoc-js/non-english-identifier.js b/tests/rustdoc-js/non-english-identifier.js
index f2180b4c755..3d50bd3ee90 100644
--- a/tests/rustdoc-js/non-english-identifier.js
+++ b/tests/rustdoc-js/non-english-identifier.js
@@ -115,11 +115,10 @@ const EXPECTED = [
         query: '加法',
         others: [
             {
-                name: "add",
+                name: "加法",
                 path: "non_english_identifier",
-                is_alias: true,
-                alias: "加法",
-                href: "../non_english_identifier/macro.add.html"
+                href: "../non_english_identifier/trait.加法.html",
+                desc: "Add"
             },
             {
                 name: "add",
@@ -129,11 +128,13 @@ const EXPECTED = [
                 href: "../non_english_identifier/fn.add.html"
             },
             {
-                name: "加法",
+                name: "add",
                 path: "non_english_identifier",
-                href: "../non_english_identifier/trait.加法.html",
-                desc: "Add"
-            }],
+                is_alias: true,
+                alias: "加法",
+                href: "../non_english_identifier/macro.add.html"
+            },
+        ],
         in_args: [{
             name: "加上",
             path: "non_english_identifier::加法",
diff --git a/tests/ui/cfg/crt-static-with-target-features-works.rs b/tests/ui/cfg/crt-static-with-target-features-works.rs
new file mode 100644
index 00000000000..bce02229624
--- /dev/null
+++ b/tests/ui/cfg/crt-static-with-target-features-works.rs
@@ -0,0 +1,24 @@
+// Test to ensure that specifying a value for crt-static in target features
+// does not result in skipping the features following it.
+// This is a regression test for #144143
+
+//@ add-core-stubs
+//@ needs-llvm-components: x86
+//@ compile-flags: --target=x86_64-unknown-linux-gnu
+//@ compile-flags: -Ctarget-feature=+crt-static,+avx2
+
+#![crate_type = "rlib"]
+#![feature(no_core, rustc_attrs, lang_items)]
+#![no_core]
+
+extern crate minicore;
+use minicore::*;
+
+#[rustc_builtin_macro]
+macro_rules! compile_error {
+    () => {};
+}
+
+#[cfg(target_feature = "avx2")]
+compile_error!("+avx2");
+//~^ ERROR: +avx2
diff --git a/tests/ui/cfg/crt-static-with-target-features-works.stderr b/tests/ui/cfg/crt-static-with-target-features-works.stderr
new file mode 100644
index 00000000000..6f265c685bb
--- /dev/null
+++ b/tests/ui/cfg/crt-static-with-target-features-works.stderr
@@ -0,0 +1,8 @@
+error: +avx2
+  --> $DIR/crt-static-with-target-features-works.rs:23:1
+   |
+LL | compile_error!("+avx2");
+   | ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/contracts/contract-attributes-generics.rs b/tests/ui/contracts/contract-attributes-generics.rs
index fd79c6abedd..3763ce116f8 100644
--- a/tests/ui/contracts/contract-attributes-generics.rs
+++ b/tests/ui/contracts/contract-attributes-generics.rs
@@ -5,9 +5,9 @@
 //@ [unchk_pass] run-pass
 //@ [chk_pass] run-pass
 //
-//@ [chk_fail_pre] run-fail
-//@ [chk_fail_post] run-fail
-//@ [chk_const_fail] run-fail
+//@ [chk_fail_pre] run-crash
+//@ [chk_fail_post] run-crash
+//@ [chk_const_fail] run-crash
 //
 //@ [unchk_pass] compile-flags: -Zcontract-checks=no
 //
diff --git a/tests/ui/contracts/contract-attributes-nest.rs b/tests/ui/contracts/contract-attributes-nest.rs
index e1e61b88f28..d367687b84e 100644
--- a/tests/ui/contracts/contract-attributes-nest.rs
+++ b/tests/ui/contracts/contract-attributes-nest.rs
@@ -5,8 +5,8 @@
 //@ [unchk_fail_post] run-pass
 //@ [chk_pass] run-pass
 //
-//@ [chk_fail_pre] run-fail
-//@ [chk_fail_post] run-fail
+//@ [chk_fail_pre] run-crash
+//@ [chk_fail_post] run-crash
 //
 //@ [unchk_pass] compile-flags: -Zcontract-checks=no
 //@ [unchk_fail_pre] compile-flags: -Zcontract-checks=no
diff --git a/tests/ui/contracts/contract-attributes-tail.rs b/tests/ui/contracts/contract-attributes-tail.rs
index ce4a6be5b82..43edfe5e803 100644
--- a/tests/ui/contracts/contract-attributes-tail.rs
+++ b/tests/ui/contracts/contract-attributes-tail.rs
@@ -5,8 +5,8 @@
 //@ [unchk_fail_post] run-pass
 //@ [chk_pass] run-pass
 //
-//@ [chk_fail_pre] run-fail
-//@ [chk_fail_post] run-fail
+//@ [chk_fail_pre] run-crash
+//@ [chk_fail_post] run-crash
 //
 //@ [unchk_pass] compile-flags: -Zcontract-checks=no
 //@ [unchk_fail_pre] compile-flags: -Zcontract-checks=no
diff --git a/tests/ui/contracts/contract-captures-via-closure-copy.rs b/tests/ui/contracts/contract-captures-via-closure-copy.rs
index 32c6d2bf4fe..bc7e5b9b6f1 100644
--- a/tests/ui/contracts/contract-captures-via-closure-copy.rs
+++ b/tests/ui/contracts/contract-captures-via-closure-copy.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Zcontract-checks=yes
 
 #![feature(contracts)]
diff --git a/tests/ui/contracts/contract-const-fn.rs b/tests/ui/contracts/contract-const-fn.rs
index 733a06ae570..fe8dd37b1f5 100644
--- a/tests/ui/contracts/contract-const-fn.rs
+++ b/tests/ui/contracts/contract-const-fn.rs
@@ -8,8 +8,8 @@
 //
 //@ [all_pass] run-pass
 //
-//@ [runtime_fail_pre] run-fail
-//@ [runtime_fail_post] run-fail
+//@ [runtime_fail_pre] run-crash
+//@ [runtime_fail_post] run-crash
 //
 //@ [all_pass] compile-flags: -Zcontract-checks=yes
 //@ [runtime_fail_pre] compile-flags: -Zcontract-checks=yes
diff --git a/tests/ui/contracts/contracts-ensures-early-fn-exit.rs b/tests/ui/contracts/contracts-ensures-early-fn-exit.rs
index 034cead3b4e..44ae07d8c95 100644
--- a/tests/ui/contracts/contracts-ensures-early-fn-exit.rs
+++ b/tests/ui/contracts/contracts-ensures-early-fn-exit.rs
@@ -2,9 +2,9 @@
 //
 //@ [unchk_pass] run-pass
 //@ [chk_pass] run-pass
-//@ [chk_fail_try] run-fail
-//@ [chk_fail_ret] run-fail
-//@ [chk_fail_yeet] run-fail
+//@ [chk_fail_try] run-crash
+//@ [chk_fail_ret] run-crash
+//@ [chk_fail_yeet] run-crash
 //
 //@ [unchk_pass] compile-flags: -Zcontract-checks=no
 //@ [chk_pass] compile-flags: -Zcontract-checks=yes
diff --git a/tests/ui/contracts/internal_machinery/contract-ast-extensions-nest.rs b/tests/ui/contracts/internal_machinery/contract-ast-extensions-nest.rs
index 6d8cd3949ee..4da0480f8bc 100644
--- a/tests/ui/contracts/internal_machinery/contract-ast-extensions-nest.rs
+++ b/tests/ui/contracts/internal_machinery/contract-ast-extensions-nest.rs
@@ -5,8 +5,8 @@
 //@ [unchk_fail_post] run-pass
 //@ [chk_pass] run-pass
 //
-//@ [chk_fail_pre] run-fail
-//@ [chk_fail_post] run-fail
+//@ [chk_fail_pre] run-crash
+//@ [chk_fail_post] run-crash
 //
 //@ [unchk_pass] compile-flags: -Zcontract-checks=no
 //@ [unchk_fail_pre] compile-flags: -Zcontract-checks=no
diff --git a/tests/ui/contracts/internal_machinery/contract-ast-extensions-tail.rs b/tests/ui/contracts/internal_machinery/contract-ast-extensions-tail.rs
index 07ec26f921b..f3cf5ce082c 100644
--- a/tests/ui/contracts/internal_machinery/contract-ast-extensions-tail.rs
+++ b/tests/ui/contracts/internal_machinery/contract-ast-extensions-tail.rs
@@ -5,8 +5,8 @@
 //@ [unchk_fail_post] run-pass
 //@ [chk_pass] run-pass
 //
-//@ [chk_fail_pre] run-fail
-//@ [chk_fail_post] run-fail
+//@ [chk_fail_pre] run-crash
+//@ [chk_fail_post] run-crash
 //
 //@ [unchk_pass] compile-flags: -Zcontract-checks=no
 //@ [unchk_fail_pre] compile-flags: -Zcontract-checks=no
diff --git a/tests/ui/contracts/internal_machinery/contract-intrinsics.rs b/tests/ui/contracts/internal_machinery/contract-intrinsics.rs
index c62b8cca75a..6e613b53fc9 100644
--- a/tests/ui/contracts/internal_machinery/contract-intrinsics.rs
+++ b/tests/ui/contracts/internal_machinery/contract-intrinsics.rs
@@ -3,8 +3,8 @@
 //@ [default] run-pass
 //@ [unchk_pass] run-pass
 //@ [chk_pass] run-pass
-//@ [chk_fail_requires] run-fail
-//@ [chk_fail_ensures] run-fail
+//@ [chk_fail_requires] run-crash
+//@ [chk_fail_ensures] run-crash
 //
 //@ [unchk_pass] compile-flags: -Zcontract-checks=no
 //@ [chk_pass] compile-flags: -Zcontract-checks=yes
diff --git a/tests/ui/contracts/internal_machinery/contract-lang-items.rs b/tests/ui/contracts/internal_machinery/contract-lang-items.rs
index 73c59194531..ac72d233bf6 100644
--- a/tests/ui/contracts/internal_machinery/contract-lang-items.rs
+++ b/tests/ui/contracts/internal_machinery/contract-lang-items.rs
@@ -4,7 +4,7 @@
 //@ [unchk_fail_post] run-pass
 //@ [chk_pass] run-pass
 //
-//@ [chk_fail_post] run-fail
+//@ [chk_fail_post] run-crash
 //
 //@ [unchk_pass] compile-flags: -Zcontract-checks=no
 //@ [unchk_fail_post] compile-flags: -Zcontract-checks=no
diff --git a/tests/ui/extern/extern-types-field-offset.rs b/tests/ui/extern/extern-types-field-offset.rs
index 75f3eab3e27..035f063cd50 100644
--- a/tests/ui/extern/extern-types-field-offset.rs
+++ b/tests/ui/extern/extern-types-field-offset.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ check-run-results
 //@ exec-env:RUST_BACKTRACE=0
 //@ normalize-stderr: "(core/src/panicking\.rs):[0-9]+:[0-9]+" -> "$1:$$LINE:$$COL"
diff --git a/tests/ui/impl-trait/in-bindings/implicit-sized.rs b/tests/ui/impl-trait/in-bindings/implicit-sized.rs
new file mode 100644
index 00000000000..2f16db94189
--- /dev/null
+++ b/tests/ui/impl-trait/in-bindings/implicit-sized.rs
@@ -0,0 +1,19 @@
+#![feature(impl_trait_in_bindings)]
+
+trait Trait {}
+impl<T: ?Sized> Trait for T {}
+
+fn doesnt_work() {
+    let x: &impl Trait = "hi";
+    //~^ ERROR the size for values of type `str` cannot be known at compilation time
+}
+
+fn works() {
+    let x: &(impl Trait + ?Sized) = "hi";
+    // No implicit sized.
+
+    let x: &impl Trait = &();
+    // Is actually sized.
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/in-bindings/implicit-sized.stderr b/tests/ui/impl-trait/in-bindings/implicit-sized.stderr
new file mode 100644
index 00000000000..465a928cf86
--- /dev/null
+++ b/tests/ui/impl-trait/in-bindings/implicit-sized.stderr
@@ -0,0 +1,11 @@
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/implicit-sized.rs:7:13
+   |
+LL |     let x: &impl Trait = "hi";
+   |             ^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `str`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/lint/invalid_null_args.rs b/tests/ui/lint/invalid_null_args.rs
index f40f06a0d36..ee29d622ad7 100644
--- a/tests/ui/lint/invalid_null_args.rs
+++ b/tests/ui/lint/invalid_null_args.rs
@@ -58,10 +58,9 @@ unsafe fn null_ptr() {
     let _a: A = ptr::read_unaligned(ptr::null_mut());
     //~^ ERROR calling this function with a null pointer is undefined behavior
 
+    // These two should *not* fire the lint.
     let _a: A = ptr::read_volatile(ptr::null());
-    //~^ ERROR calling this function with a null pointer is undefined behavior
     let _a: A = ptr::read_volatile(ptr::null_mut());
-    //~^ ERROR calling this function with a null pointer is undefined behavior
 
     let _a: A = ptr::replace(ptr::null_mut(), v);
     //~^ ERROR calling this function with a null pointer is undefined behavior
@@ -82,8 +81,8 @@ unsafe fn null_ptr() {
     ptr::write_unaligned(ptr::null_mut(), v);
     //~^ ERROR calling this function with a null pointer is undefined behavior
 
+    // This one should *not* fire the lint.
     ptr::write_volatile(ptr::null_mut(), v);
-    //~^ ERROR calling this function with a null pointer is undefined behavior
 
     ptr::write_bytes::<usize>(ptr::null_mut(), 42, 0);
     //~^ ERROR calling this function with a null pointer is undefined behavior
diff --git a/tests/ui/lint/invalid_null_args.stderr b/tests/ui/lint/invalid_null_args.stderr
index 11c6270cfb7..028bd7051dc 100644
--- a/tests/ui/lint/invalid_null_args.stderr
+++ b/tests/ui/lint/invalid_null_args.stderr
@@ -164,27 +164,7 @@ LL |     let _a: A = ptr::read_unaligned(ptr::null_mut());
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:61:17
-   |
-LL |     let _a: A = ptr::read_volatile(ptr::null());
-   |                 ^^^^^^^^^^^^^^^^^^^-----------^
-   |                                    |
-   |                                    null pointer originates from here
-   |
-   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
-
-error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:63:17
-   |
-LL |     let _a: A = ptr::read_volatile(ptr::null_mut());
-   |                 ^^^^^^^^^^^^^^^^^^^---------------^
-   |                                    |
-   |                                    null pointer originates from here
-   |
-   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
-
-error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:66:17
+  --> $DIR/invalid_null_args.rs:65:17
    |
 LL |     let _a: A = ptr::replace(ptr::null_mut(), v);
    |                 ^^^^^^^^^^^^^---------------^^^^
@@ -194,7 +174,7 @@ LL |     let _a: A = ptr::replace(ptr::null_mut(), v);
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:69:5
+  --> $DIR/invalid_null_args.rs:68:5
    |
 LL |     ptr::swap::<A>(ptr::null_mut(), &mut v);
    |     ^^^^^^^^^^^^^^^---------------^^^^^^^^^
@@ -204,7 +184,7 @@ LL |     ptr::swap::<A>(ptr::null_mut(), &mut v);
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:71:5
+  --> $DIR/invalid_null_args.rs:70:5
    |
 LL |     ptr::swap::<A>(&mut v, ptr::null_mut());
    |     ^^^^^^^^^^^^^^^^^^^^^^^---------------^
@@ -214,7 +194,7 @@ LL |     ptr::swap::<A>(&mut v, ptr::null_mut());
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:74:5
+  --> $DIR/invalid_null_args.rs:73:5
    |
 LL |     ptr::swap_nonoverlapping::<A>(ptr::null_mut(), &mut v, 0);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^^^^^^^^^
@@ -224,7 +204,7 @@ LL |     ptr::swap_nonoverlapping::<A>(ptr::null_mut(), &mut v, 0);
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:76:5
+  --> $DIR/invalid_null_args.rs:75:5
    |
 LL |     ptr::swap_nonoverlapping::<A>(&mut v, ptr::null_mut(), 0);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^
@@ -234,7 +214,7 @@ LL |     ptr::swap_nonoverlapping::<A>(&mut v, ptr::null_mut(), 0);
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:79:5
+  --> $DIR/invalid_null_args.rs:78:5
    |
 LL |     ptr::write(ptr::null_mut(), v);
    |     ^^^^^^^^^^^---------------^^^^
@@ -244,7 +224,7 @@ LL |     ptr::write(ptr::null_mut(), v);
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:82:5
+  --> $DIR/invalid_null_args.rs:81:5
    |
 LL |     ptr::write_unaligned(ptr::null_mut(), v);
    |     ^^^^^^^^^^^^^^^^^^^^^---------------^^^^
@@ -254,17 +234,7 @@ LL |     ptr::write_unaligned(ptr::null_mut(), v);
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:85:5
-   |
-LL |     ptr::write_volatile(ptr::null_mut(), v);
-   |     ^^^^^^^^^^^^^^^^^^^^---------------^^^^
-   |                         |
-   |                         null pointer originates from here
-   |
-   = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
-
-error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:88:5
+  --> $DIR/invalid_null_args.rs:87:5
    |
 LL |     ptr::write_bytes::<usize>(ptr::null_mut(), 42, 0);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^^^^^
@@ -274,7 +244,7 @@ LL |     ptr::write_bytes::<usize>(ptr::null_mut(), 42, 0);
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:93:18
+  --> $DIR/invalid_null_args.rs:92:18
    |
 LL |     let _a: u8 = ptr::read(const_ptr);
    |                  ^^^^^^^^^^^^^^^^^^^^
@@ -287,7 +257,7 @@ LL |     let null_ptr = ptr::null_mut();
    |                    ^^^^^^^^^^^^^^^
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:100:5
+  --> $DIR/invalid_null_args.rs:99:5
    |
 LL |     std::slice::from_raw_parts::<()>(ptr::null(), 0);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^
@@ -297,7 +267,7 @@ LL |     std::slice::from_raw_parts::<()>(ptr::null(), 0);
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:102:5
+  --> $DIR/invalid_null_args.rs:101:5
    |
 LL |     std::slice::from_raw_parts::<Zst>(ptr::null(), 0);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^^^^
@@ -307,7 +277,7 @@ LL |     std::slice::from_raw_parts::<Zst>(ptr::null(), 0);
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:104:5
+  --> $DIR/invalid_null_args.rs:103:5
    |
 LL |     std::slice::from_raw_parts_mut::<()>(ptr::null_mut(), 0);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^
@@ -317,7 +287,7 @@ LL |     std::slice::from_raw_parts_mut::<()>(ptr::null_mut(), 0);
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
 error: calling this function with a null pointer is undefined behavior, even if the result of the function is unused
-  --> $DIR/invalid_null_args.rs:106:5
+  --> $DIR/invalid_null_args.rs:105:5
    |
 LL |     std::slice::from_raw_parts_mut::<Zst>(ptr::null_mut(), 0);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------^^^^
@@ -326,5 +296,5 @@ LL |     std::slice::from_raw_parts_mut::<Zst>(ptr::null_mut(), 0);
    |
    = help: for more information, visit <https://doc.rust-lang.org/std/ptr/index.html> and <https://doc.rust-lang.org/reference/behavior-considered-undefined.html>
 
-error: aborting due to 31 previous errors
+error: aborting due to 28 previous errors
 
diff --git a/tests/ui/lto/debuginfo-lto-alloc.rs b/tests/ui/lto/debuginfo-lto-alloc.rs
index 89043275329..d6855f8760d 100644
--- a/tests/ui/lto/debuginfo-lto-alloc.rs
+++ b/tests/ui/lto/debuginfo-lto-alloc.rs
@@ -8,8 +8,9 @@
 // This test reproduces the circumstances that caused the error to appear, and checks
 // that compilation is successful.
 
-//@ check-pass
+//@ build-pass
 //@ compile-flags: --test -C debuginfo=2 -C lto=fat
+//@ no-prefer-dynamic
 //@ incremental
 
 extern crate alloc;
diff --git a/tests/ui/mir/alignment/borrow_misaligned_field_projection.rs b/tests/ui/mir/alignment/borrow_misaligned_field_projection.rs
index a22965ce1d8..6ba895f172d 100644
--- a/tests/ui/mir/alignment/borrow_misaligned_field_projection.rs
+++ b/tests/ui/mir/alignment/borrow_misaligned_field_projection.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ ignore-i686-pc-windows-msvc: #112480
 //@ compile-flags: -C debug-assertions
 //@ error-pattern: misaligned pointer dereference: address must be a multiple of 0x4 but is
diff --git a/tests/ui/mir/alignment/misaligned_borrow.rs b/tests/ui/mir/alignment/misaligned_borrow.rs
index de8912c7038..60c21deaba5 100644
--- a/tests/ui/mir/alignment/misaligned_borrow.rs
+++ b/tests/ui/mir/alignment/misaligned_borrow.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ ignore-i686-pc-windows-msvc: #112480
 //@ compile-flags: -C debug-assertions
 //@ error-pattern: misaligned pointer dereference: address must be a multiple of 0x4 but is
diff --git a/tests/ui/mir/alignment/misaligned_lhs.rs b/tests/ui/mir/alignment/misaligned_lhs.rs
index b169823bc08..e8ddb10fd9c 100644
--- a/tests/ui/mir/alignment/misaligned_lhs.rs
+++ b/tests/ui/mir/alignment/misaligned_lhs.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ ignore-i686-pc-windows-msvc: #112480
 //@ compile-flags: -C debug-assertions
 //@ error-pattern: misaligned pointer dereference: address must be a multiple of 0x4 but is
diff --git a/tests/ui/mir/alignment/misaligned_mut_borrow.rs b/tests/ui/mir/alignment/misaligned_mut_borrow.rs
index bba20edecfd..c066cc0efcd 100644
--- a/tests/ui/mir/alignment/misaligned_mut_borrow.rs
+++ b/tests/ui/mir/alignment/misaligned_mut_borrow.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ ignore-i686-pc-windows-msvc: #112480
 //@ compile-flags: -C debug-assertions
 //@ error-pattern: misaligned pointer dereference: address must be a multiple of 0x4 but is
diff --git a/tests/ui/mir/alignment/misaligned_rhs.rs b/tests/ui/mir/alignment/misaligned_rhs.rs
index 55da30a2fd7..6bdc39c9d91 100644
--- a/tests/ui/mir/alignment/misaligned_rhs.rs
+++ b/tests/ui/mir/alignment/misaligned_rhs.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ ignore-i686-pc-windows-msvc: #112480
 //@ compile-flags: -C debug-assertions
 //@ error-pattern: misaligned pointer dereference: address must be a multiple of 0x4 but is
diff --git a/tests/ui/mir/alignment/two_pointers.rs b/tests/ui/mir/alignment/two_pointers.rs
index 198a1c9853d..fd8b2f543aa 100644
--- a/tests/ui/mir/alignment/two_pointers.rs
+++ b/tests/ui/mir/alignment/two_pointers.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ ignore-i686-pc-windows-msvc: #112480
 //@ compile-flags: -C debug-assertions
 //@ error-pattern: misaligned pointer dereference: address must be a multiple of 0x4 but is
diff --git a/tests/ui/mir/enum/convert_non_integer_break.rs b/tests/ui/mir/enum/convert_non_integer_break.rs
index 29795190bf6..b0778e2024f 100644
--- a/tests/ui/mir/enum/convert_non_integer_break.rs
+++ b/tests/ui/mir/enum/convert_non_integer_break.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -C debug-assertions
 //@ error-pattern: trying to construct an enum from an invalid value
 
diff --git a/tests/ui/mir/enum/convert_non_integer_niche_break.rs b/tests/ui/mir/enum/convert_non_integer_niche_break.rs
index 9ff4849c5b1..d26a3aeb506 100644
--- a/tests/ui/mir/enum/convert_non_integer_niche_break.rs
+++ b/tests/ui/mir/enum/convert_non_integer_niche_break.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -C debug-assertions
 //@ error-pattern: trying to construct an enum from an invalid value 0x5
 
diff --git a/tests/ui/mir/enum/negative_discr_break.rs b/tests/ui/mir/enum/negative_discr_break.rs
index fa1284f72a0..35ee8aa3fc8 100644
--- a/tests/ui/mir/enum/negative_discr_break.rs
+++ b/tests/ui/mir/enum/negative_discr_break.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -C debug-assertions
 //@ error-pattern: trying to construct an enum from an invalid value 0xfd
 
diff --git a/tests/ui/mir/enum/niche_option_tuple_break.rs b/tests/ui/mir/enum/niche_option_tuple_break.rs
index affdc4784a3..0a933afa153 100644
--- a/tests/ui/mir/enum/niche_option_tuple_break.rs
+++ b/tests/ui/mir/enum/niche_option_tuple_break.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -C debug-assertions
 //@ error-pattern: trying to construct an enum from an invalid value
 
diff --git a/tests/ui/mir/enum/numbered_variants_break.rs b/tests/ui/mir/enum/numbered_variants_break.rs
index e3e71dc8aec..fbe7d6627a3 100644
--- a/tests/ui/mir/enum/numbered_variants_break.rs
+++ b/tests/ui/mir/enum/numbered_variants_break.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -C debug-assertions
 //@ error-pattern: trying to construct an enum from an invalid value 0x3
 
diff --git a/tests/ui/mir/enum/option_with_bigger_niche_break.rs b/tests/ui/mir/enum/option_with_bigger_niche_break.rs
index c66614b845b..675d27f0ec2 100644
--- a/tests/ui/mir/enum/option_with_bigger_niche_break.rs
+++ b/tests/ui/mir/enum/option_with_bigger_niche_break.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -C debug-assertions
 //@ error-pattern: trying to construct an enum from an invalid value 0x0
 
diff --git a/tests/ui/mir/enum/plain_no_data_break.rs b/tests/ui/mir/enum/plain_no_data_break.rs
index db68e752479..966dd641873 100644
--- a/tests/ui/mir/enum/plain_no_data_break.rs
+++ b/tests/ui/mir/enum/plain_no_data_break.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -C debug-assertions
 //@ error-pattern: trying to construct an enum from an invalid value 0x1
 
diff --git a/tests/ui/mir/enum/single_with_repr_break.rs b/tests/ui/mir/enum/single_with_repr_break.rs
index 5a4ec85a9b5..53e4932d5fd 100644
--- a/tests/ui/mir/enum/single_with_repr_break.rs
+++ b/tests/ui/mir/enum/single_with_repr_break.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -C debug-assertions
 //@ error-pattern: trying to construct an enum from an invalid value 0x1
 
diff --git a/tests/ui/mir/enum/with_niche_int_break.rs b/tests/ui/mir/enum/with_niche_int_break.rs
index 6a97eaa8f4f..d363dc7568a 100644
--- a/tests/ui/mir/enum/with_niche_int_break.rs
+++ b/tests/ui/mir/enum/with_niche_int_break.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -C debug-assertions
 //@ error-pattern: trying to construct an enum from an invalid value
 
diff --git a/tests/ui/mir/enum/wrap_break.rs b/tests/ui/mir/enum/wrap_break.rs
index 4491394ca5a..5c410afa511 100644
--- a/tests/ui/mir/enum/wrap_break.rs
+++ b/tests/ui/mir/enum/wrap_break.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -C debug-assertions
 //@ error-pattern: trying to construct an enum from an invalid value 0x0
 #![feature(never_type)]
diff --git a/tests/ui/mir/null/borrowed_mut_null.rs b/tests/ui/mir/null/borrowed_mut_null.rs
index d26452b9dac..a4660f4bf57 100644
--- a/tests/ui/mir/null/borrowed_mut_null.rs
+++ b/tests/ui/mir/null/borrowed_mut_null.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -C debug-assertions
 //@ error-pattern: null pointer dereference occurred
 
diff --git a/tests/ui/mir/null/borrowed_null.rs b/tests/ui/mir/null/borrowed_null.rs
index fefac3a7212..2a50058a482 100644
--- a/tests/ui/mir/null/borrowed_null.rs
+++ b/tests/ui/mir/null/borrowed_null.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -C debug-assertions
 //@ error-pattern: null pointer dereference occurred
 
diff --git a/tests/ui/mir/null/borrowed_null_zst.rs b/tests/ui/mir/null/borrowed_null_zst.rs
index 835727c068b..106fa00b1db 100644
--- a/tests/ui/mir/null/borrowed_null_zst.rs
+++ b/tests/ui/mir/null/borrowed_null_zst.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -C debug-assertions
 //@ error-pattern: null pointer dereference occurred
 
diff --git a/tests/ui/mir/null/null_lhs.rs b/tests/ui/mir/null/null_lhs.rs
index 238d350d1bd..b59338588a5 100644
--- a/tests/ui/mir/null/null_lhs.rs
+++ b/tests/ui/mir/null/null_lhs.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -C debug-assertions
 //@ error-pattern: null pointer dereference occurred
 
diff --git a/tests/ui/mir/null/null_rhs.rs b/tests/ui/mir/null/null_rhs.rs
index 18eafb61869..18fdad759fd 100644
--- a/tests/ui/mir/null/null_rhs.rs
+++ b/tests/ui/mir/null/null_rhs.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -C debug-assertions
 //@ error-pattern: null pointer dereference occurred
 
diff --git a/tests/ui/mir/null/two_pointers.rs b/tests/ui/mir/null/two_pointers.rs
index 52b9510be12..b2aa7cf0384 100644
--- a/tests/ui/mir/null/two_pointers.rs
+++ b/tests/ui/mir/null/two_pointers.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -C debug-assertions
 //@ error-pattern: null pointer dereference occurred
 
diff --git a/tests/ui/mir/validate/critical-edge.rs b/tests/ui/mir/validate/critical-edge.rs
index 2a3bf6a6181..7fe3891d642 100644
--- a/tests/ui/mir/validate/critical-edge.rs
+++ b/tests/ui/mir/validate/critical-edge.rs
@@ -21,6 +21,8 @@ pub fn f(a: u32) -> u32 {
         }
         bb1 = {
             Call(RET = f(1), ReturnTo(bb2), UnwindTerminate(ReasonAbi))
+//~^ ERROR broken MIR in Item
+//~| ERROR encountered critical edge in `Call` terminator
         }
 
         bb2 = {
@@ -29,5 +31,3 @@ pub fn f(a: u32) -> u32 {
         }
     }
 }
-
-//~? RAW encountered critical edge in `Call` terminator
diff --git a/tests/ui/panics/panic-in-cleanup.rs b/tests/ui/panics/panic-in-cleanup.rs
index 8cddeb37348..2e307de4393 100644
--- a/tests/ui/panics/panic-in-cleanup.rs
+++ b/tests/ui/panics/panic-in-cleanup.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ exec-env:RUST_BACKTRACE=0
 //@ check-run-results
 //@ error-pattern: panic in a destructor during cleanup
diff --git a/tests/ui/panics/panic-in-ffi.rs b/tests/ui/panics/panic-in-ffi.rs
index 6068e4fdc59..b926d0fa776 100644
--- a/tests/ui/panics/panic-in-ffi.rs
+++ b/tests/ui/panics/panic-in-ffi.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ exec-env:RUST_BACKTRACE=0
 //@ check-run-results
 //@ error-pattern: panic in a function that cannot unwind
diff --git a/tests/ui/panics/panic-in-message-fmt.rs b/tests/ui/panics/panic-in-message-fmt.rs
index 1e9bbaf45c5..4d539f17a0a 100644
--- a/tests/ui/panics/panic-in-message-fmt.rs
+++ b/tests/ui/panics/panic-in-message-fmt.rs
@@ -1,6 +1,6 @@
 // Checks what happens when formatting the panic message panics.
 
-//@ run-fail
+//@ run-crash
 //@ exec-env:RUST_BACKTRACE=0
 //@ check-run-results
 //@ error-pattern: panicked while processing panic
diff --git a/tests/ui/panics/panic-main.rs b/tests/ui/panics/panic-main.rs
index bf79de78a57..2009f69e19e 100644
--- a/tests/ui/panics/panic-main.rs
+++ b/tests/ui/panics/panic-main.rs
@@ -1,27 +1,37 @@
 //@ revisions: default abort-zero abort-one abort-full unwind-zero unwind-one unwind-full
 
+//@[default] run-fail
+
 //@[abort-zero] compile-flags: -Cpanic=abort
 //@[abort-zero] no-prefer-dynamic
 //@[abort-zero] exec-env:RUST_BACKTRACE=0
+//@[abort-zero] run-crash
 
 //@[abort-one] compile-flags: -Cpanic=abort
 //@[abort-one] no-prefer-dynamic
 //@[abort-one] exec-env:RUST_BACKTRACE=1
+//@[abort-one] run-crash
 
 //@[abort-full] compile-flags: -Cpanic=abort
 //@[abort-full] no-prefer-dynamic
 //@[abort-full] exec-env:RUST_BACKTRACE=full
+//@[abort-full] run-crash
 
 //@[unwind-zero] compile-flags: -Cpanic=unwind
 //@[unwind-zero] exec-env:RUST_BACKTRACE=0
+//@[unwind-zero] needs-unwind
+//@[unwind-zero] run-fail
 
 //@[unwind-one] compile-flags: -Cpanic=unwind
 //@[unwind-one] exec-env:RUST_BACKTRACE=1
+//@[unwind-one] needs-unwind
+//@[unwind-one] run-fail
 
 //@[unwind-full] compile-flags: -Cpanic=unwind
 //@[unwind-full] exec-env:RUST_BACKTRACE=full
+//@[unwind-full] needs-unwind
+//@[unwind-full] run-fail
 
-//@ run-fail
 //@ error-pattern:moop
 //@ needs-subprocess
 
diff --git a/tests/ui/precondition-checks/alignment.rs b/tests/ui/precondition-checks/alignment.rs
index 92400528fa0..038a625bed7 100644
--- a/tests/ui/precondition-checks/alignment.rs
+++ b/tests/ui/precondition-checks/alignment.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: Alignment::new_unchecked requires
 
diff --git a/tests/ui/precondition-checks/ascii-char-digit_unchecked.rs b/tests/ui/precondition-checks/ascii-char-digit_unchecked.rs
index 30c6f79fb08..41ba2c5254a 100644
--- a/tests/ui/precondition-checks/ascii-char-digit_unchecked.rs
+++ b/tests/ui/precondition-checks/ascii-char-digit_unchecked.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: `ascii::Char::digit_unchecked` input cannot exceed 9
 
diff --git a/tests/ui/precondition-checks/assert_unchecked.rs b/tests/ui/precondition-checks/assert_unchecked.rs
index 22b2b414550..da5383cdea0 100644
--- a/tests/ui/precondition-checks/assert_unchecked.rs
+++ b/tests/ui/precondition-checks/assert_unchecked.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: hint::assert_unchecked must never be called when the condition is false
 
diff --git a/tests/ui/precondition-checks/char-from_u32_unchecked.rs b/tests/ui/precondition-checks/char-from_u32_unchecked.rs
index d950f20c772..7c34d926d3e 100644
--- a/tests/ui/precondition-checks/char-from_u32_unchecked.rs
+++ b/tests/ui/precondition-checks/char-from_u32_unchecked.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: invalid value for `char`
 
diff --git a/tests/ui/precondition-checks/copy-nonoverlapping.rs b/tests/ui/precondition-checks/copy-nonoverlapping.rs
index eacaa63e543..1d584ddef4c 100644
--- a/tests/ui/precondition-checks/copy-nonoverlapping.rs
+++ b/tests/ui/precondition-checks/copy-nonoverlapping.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: ptr::copy_nonoverlapping requires
 //@ revisions: null_src null_dst misaligned_src misaligned_dst overlapping
diff --git a/tests/ui/precondition-checks/copy.rs b/tests/ui/precondition-checks/copy.rs
index 1fadd90bf70..8faa56a880e 100644
--- a/tests/ui/precondition-checks/copy.rs
+++ b/tests/ui/precondition-checks/copy.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: ptr::copy requires
 //@ revisions: null_src null_dst misaligned_src misaligned_dst
diff --git a/tests/ui/precondition-checks/layout.rs b/tests/ui/precondition-checks/layout.rs
index 4ee66cc9328..6755ebce854 100644
--- a/tests/ui/precondition-checks/layout.rs
+++ b/tests/ui/precondition-checks/layout.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: Layout::from_size_align_unchecked requires
 //@ revisions: toolarge badalign
diff --git a/tests/ui/precondition-checks/nonnull.rs b/tests/ui/precondition-checks/nonnull.rs
index 6b8edd4e582..75bbd65b486 100644
--- a/tests/ui/precondition-checks/nonnull.rs
+++ b/tests/ui/precondition-checks/nonnull.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: NonNull::new_unchecked requires
 
diff --git a/tests/ui/precondition-checks/nonzero-from_mut_unchecked.rs b/tests/ui/precondition-checks/nonzero-from_mut_unchecked.rs
index 46ce7dc356f..d55707fdd0b 100644
--- a/tests/ui/precondition-checks/nonzero-from_mut_unchecked.rs
+++ b/tests/ui/precondition-checks/nonzero-from_mut_unchecked.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: NonZero::from_mut_unchecked requires
 
diff --git a/tests/ui/precondition-checks/nonzero-new_unchecked.rs b/tests/ui/precondition-checks/nonzero-new_unchecked.rs
index 7827a42844f..978f01f150f 100644
--- a/tests/ui/precondition-checks/nonzero-new_unchecked.rs
+++ b/tests/ui/precondition-checks/nonzero-new_unchecked.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: NonZero::new_unchecked requires
 
diff --git a/tests/ui/precondition-checks/read_volatile.rs b/tests/ui/precondition-checks/read_volatile.rs
index ada8932c398..33350dfbc4f 100644
--- a/tests/ui/precondition-checks/read_volatile.rs
+++ b/tests/ui/precondition-checks/read_volatile.rs
@@ -1,9 +1,7 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: ptr::read_volatile requires
-//@ revisions: null misaligned
-
-#![allow(invalid_null_arguments)]
+//@ revisions: misaligned
 
 use std::ptr;
 
@@ -11,8 +9,6 @@ fn main() {
     let src = [0u16; 2];
     let src = src.as_ptr();
     unsafe {
-        #[cfg(null)]
-        ptr::read_volatile(ptr::null::<u8>());
         #[cfg(misaligned)]
         ptr::read_volatile(src.byte_add(1));
     }
diff --git a/tests/ui/precondition-checks/replace.rs b/tests/ui/precondition-checks/replace.rs
index 44afbd8174c..447a00c6572 100644
--- a/tests/ui/precondition-checks/replace.rs
+++ b/tests/ui/precondition-checks/replace.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: ptr::replace requires
 //@ revisions: null misaligned
diff --git a/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs b/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs
index 9b9ded69a83..b6397ab2a12 100644
--- a/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs
+++ b/tests/ui/precondition-checks/slice-from-raw-parts-mut.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts_mut requires
 //@ revisions: null misaligned toolarge
diff --git a/tests/ui/precondition-checks/slice-from-raw-parts.rs b/tests/ui/precondition-checks/slice-from-raw-parts.rs
index 96578c1eae5..a317e3d41a0 100644
--- a/tests/ui/precondition-checks/slice-from-raw-parts.rs
+++ b/tests/ui/precondition-checks/slice-from-raw-parts.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: slice::from_raw_parts requires
 //@ revisions: null misaligned toolarge
diff --git a/tests/ui/precondition-checks/slice-get_unchecked.rs b/tests/ui/precondition-checks/slice-get_unchecked.rs
index 1d8188fb953..7bcb8442540 100644
--- a/tests/ui/precondition-checks/slice-get_unchecked.rs
+++ b/tests/ui/precondition-checks/slice-get_unchecked.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: slice::get_unchecked requires
 //@ revisions: usize range range_to range_from backwards_range
diff --git a/tests/ui/precondition-checks/slice-get_unchecked_mut.rs b/tests/ui/precondition-checks/slice-get_unchecked_mut.rs
index 34c1454af43..2ba3227f39e 100644
--- a/tests/ui/precondition-checks/slice-get_unchecked_mut.rs
+++ b/tests/ui/precondition-checks/slice-get_unchecked_mut.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: slice::get_unchecked_mut requires
 //@ revisions: usize range range_to range_from backwards_range
diff --git a/tests/ui/precondition-checks/str-get_unchecked.rs b/tests/ui/precondition-checks/str-get_unchecked.rs
index 14d17f997ec..2273190e9f4 100644
--- a/tests/ui/precondition-checks/str-get_unchecked.rs
+++ b/tests/ui/precondition-checks/str-get_unchecked.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: str::get_unchecked requires
 //@ revisions: range range_to range_from backwards_range
diff --git a/tests/ui/precondition-checks/str-get_unchecked_mut.rs b/tests/ui/precondition-checks/str-get_unchecked_mut.rs
index ca1b1690055..53e6ee64d47 100644
--- a/tests/ui/precondition-checks/str-get_unchecked_mut.rs
+++ b/tests/ui/precondition-checks/str-get_unchecked_mut.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: str::get_unchecked_mut requires
 //@ revisions: range range_to range_from backwards_range
diff --git a/tests/ui/precondition-checks/swap-nonoverlapping.rs b/tests/ui/precondition-checks/swap-nonoverlapping.rs
index ea1f6f36ad7..81ba72382c0 100644
--- a/tests/ui/precondition-checks/swap-nonoverlapping.rs
+++ b/tests/ui/precondition-checks/swap-nonoverlapping.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: ptr::swap_nonoverlapping requires
 //@ revisions: null_src null_dst misaligned_src misaligned_dst overlapping
diff --git a/tests/ui/precondition-checks/unchecked_add.rs b/tests/ui/precondition-checks/unchecked_add.rs
index f44a6ea32ad..b7727aeb968 100644
--- a/tests/ui/precondition-checks/unchecked_add.rs
+++ b/tests/ui/precondition-checks/unchecked_add.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: u8::unchecked_add cannot overflow
 
diff --git a/tests/ui/precondition-checks/unchecked_mul.rs b/tests/ui/precondition-checks/unchecked_mul.rs
index 66655dda136..3eea8b66abb 100644
--- a/tests/ui/precondition-checks/unchecked_mul.rs
+++ b/tests/ui/precondition-checks/unchecked_mul.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: u8::unchecked_add cannot overflow
 
diff --git a/tests/ui/precondition-checks/unchecked_shl.rs b/tests/ui/precondition-checks/unchecked_shl.rs
index 1c96db0b1ec..57c617e0845 100644
--- a/tests/ui/precondition-checks/unchecked_shl.rs
+++ b/tests/ui/precondition-checks/unchecked_shl.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: u8::unchecked_shl cannot overflow
 
diff --git a/tests/ui/precondition-checks/unchecked_shr.rs b/tests/ui/precondition-checks/unchecked_shr.rs
index 4a6d9ffb1d3..18502d2b645 100644
--- a/tests/ui/precondition-checks/unchecked_shr.rs
+++ b/tests/ui/precondition-checks/unchecked_shr.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: u8::unchecked_shr cannot overflow
 
diff --git a/tests/ui/precondition-checks/unchecked_sub.rs b/tests/ui/precondition-checks/unchecked_sub.rs
index 545dde0e278..bfe8f5849f5 100644
--- a/tests/ui/precondition-checks/unchecked_sub.rs
+++ b/tests/ui/precondition-checks/unchecked_sub.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: u8::unchecked_sub cannot overflow
 
diff --git a/tests/ui/precondition-checks/unreachable_unchecked.rs b/tests/ui/precondition-checks/unreachable_unchecked.rs
index 2435450c4b5..f2855d03a3e 100644
--- a/tests/ui/precondition-checks/unreachable_unchecked.rs
+++ b/tests/ui/precondition-checks/unreachable_unchecked.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: hint::unreachable_unchecked must never be reached
 
diff --git a/tests/ui/precondition-checks/vec-from-parts.rs b/tests/ui/precondition-checks/vec-from-parts.rs
index 0bafb5aa715..ace90770360 100644
--- a/tests/ui/precondition-checks/vec-from-parts.rs
+++ b/tests/ui/precondition-checks/vec-from-parts.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Cdebug-assertions=yes
 //@ error-pattern: unsafe precondition(s) violated: Vec::from_parts_in requires that length <= capacity
 #![feature(allocator_api)]
diff --git a/tests/ui/precondition-checks/vec-from-raw-parts.rs b/tests/ui/precondition-checks/vec-from-raw-parts.rs
index 884d34c0a56..1bc8e6ada10 100644
--- a/tests/ui/precondition-checks/vec-from-raw-parts.rs
+++ b/tests/ui/precondition-checks/vec-from-raw-parts.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Cdebug-assertions=yes
 //@ error-pattern: unsafe precondition(s) violated: Vec::from_raw_parts_in requires that length <= capacity
 //@ revisions: vec_from_raw_parts vec_from_raw_parts_in string_from_raw_parts
diff --git a/tests/ui/precondition-checks/vec-set-len.rs b/tests/ui/precondition-checks/vec-set-len.rs
index 0987e7fe028..c6bdee7dc67 100644
--- a/tests/ui/precondition-checks/vec-set-len.rs
+++ b/tests/ui/precondition-checks/vec-set-len.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Cdebug-assertions=yes
 //@ error-pattern: unsafe precondition(s) violated: Vec::set_len requires that new_len <= capacity()
 
diff --git a/tests/ui/precondition-checks/write_volatile.rs b/tests/ui/precondition-checks/write_volatile.rs
index 0d5ecb014b3..d6ad6320e41 100644
--- a/tests/ui/precondition-checks/write_volatile.rs
+++ b/tests/ui/precondition-checks/write_volatile.rs
@@ -1,9 +1,7 @@
-//@ run-fail
+//@ run-crash
 //@ compile-flags: -Copt-level=3 -Cdebug-assertions=no -Zub-checks=yes
 //@ error-pattern: unsafe precondition(s) violated: ptr::write_volatile requires
-//@ revisions: null misaligned
-
-#![allow(invalid_null_arguments)]
+//@ revisions: misaligned
 
 use std::ptr;
 
@@ -11,8 +9,6 @@ fn main() {
     let mut dst = [0u16; 2];
     let mut dst = dst.as_mut_ptr();
     unsafe {
-        #[cfg(null)]
-        ptr::write_volatile(ptr::null_mut::<u8>(), 1u8);
         #[cfg(misaligned)]
         ptr::write_volatile(dst.byte_add(1), 1u16);
     }
diff --git a/tests/ui/print-request/supported-crate-types.rs b/tests/ui/print-request/supported-crate-types.rs
index c8b4c0c1a41..50185a231ee 100644
--- a/tests/ui/print-request/supported-crate-types.rs
+++ b/tests/ui/print-request/supported-crate-types.rs
@@ -8,6 +8,11 @@
 
 //@ check-pass
 
+// FIXME: musl targets are currently statically linked, but running on a musl host
+// requires dynamic linkage, which in turn changes the supported crate types for
+// x86_64-unknown-linux-musl.
+//@ ignore-musl
+
 //@ revisions: wasm musl linux
 
 //@[wasm] compile-flags: --target=wasm32-unknown-unknown --print=supported-crate-types -Zunstable-options
diff --git a/tests/ui/privacy/private-in-public-warn.rs b/tests/ui/privacy/private-in-public-warn.rs
index 746b98fbd07..f79e4641312 100644
--- a/tests/ui/privacy/private-in-public-warn.rs
+++ b/tests/ui/privacy/private-in-public-warn.rs
@@ -35,6 +35,7 @@ mod types {
 
 mod traits {
     trait PrivTr {}
+    impl PrivTr for () {}
     pub struct Pub<T>(T);
     pub trait PubTr {}
 
@@ -45,7 +46,10 @@ mod traits {
     pub trait Tr3 {
         type Alias: PrivTr;
         //~^ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr3::Alias`
-        fn f<T: PrivTr>(arg: T) {} //~ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr3::f`
+        fn f<T: PrivTr>(arg: T) {}
+        //~^ ERROR trait `traits::PrivTr` is more private than the item `traits::Tr3::f`
+        fn g() -> impl PrivTr;
+        fn h() -> impl PrivTr {}
     }
     impl<T: PrivTr> Pub<T> {} //~ ERROR trait `traits::PrivTr` is more private than the item `traits::Pub<T>`
     impl<T: PrivTr> PubTr for Pub<T> {} // OK, trait impl predicates
@@ -75,12 +79,18 @@ mod generics {
     pub struct Pub<T = u8>(T);
     trait PrivTr<T> {}
     pub trait PubTr<T> {}
+    impl PrivTr<Priv<()>> for () {}
 
     pub trait Tr1: PrivTr<Pub> {}
         //~^ ERROR trait `generics::PrivTr<generics::Pub>` is more private than the item `generics::Tr1`
     pub trait Tr2: PubTr<Priv> {} //~ ERROR type `generics::Priv` is more private than the item `generics::Tr2`
     pub trait Tr3: PubTr<[Priv; 1]> {} //~ ERROR type `generics::Priv` is more private than the item `generics::Tr3`
     pub trait Tr4: PubTr<Pub<Priv>> {} //~ ERROR type `generics::Priv` is more private than the item `Tr4`
+
+    pub trait Tr5 {
+        fn required() -> impl PrivTr<Priv<()>>;
+        fn provided() -> impl PrivTr<Priv<()>> {}
+    }
 }
 
 mod impls {
diff --git a/tests/ui/privacy/private-in-public-warn.stderr b/tests/ui/privacy/private-in-public-warn.stderr
index 3743879ffa6..c2a57e3b82c 100644
--- a/tests/ui/privacy/private-in-public-warn.stderr
+++ b/tests/ui/privacy/private-in-public-warn.stderr
@@ -130,7 +130,7 @@ LL |         type Alias = Priv;
    |         ^^^^^^^^^^ can't leak private type
 
 error: trait `traits::PrivTr` is more private than the item `traits::Alias`
-  --> $DIR/private-in-public-warn.rs:41:5
+  --> $DIR/private-in-public-warn.rs:42:5
    |
 LL |     pub type Alias<T: PrivTr> = T;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ type alias `traits::Alias` is reachable at visibility `pub(crate)`
@@ -147,7 +147,7 @@ LL | #![deny(private_interfaces, private_bounds)]
    |                             ^^^^^^^^^^^^^^
 
 error: trait `traits::PrivTr` is more private than the item `traits::Tr1`
-  --> $DIR/private-in-public-warn.rs:43:5
+  --> $DIR/private-in-public-warn.rs:44:5
    |
 LL |     pub trait Tr1: PrivTr {}
    |     ^^^^^^^^^^^^^^^^^^^^^ trait `traits::Tr1` is reachable at visibility `pub(crate)`
@@ -159,7 +159,7 @@ LL |     trait PrivTr {}
    |     ^^^^^^^^^^^^
 
 error: trait `traits::PrivTr` is more private than the item `traits::Tr2`
-  --> $DIR/private-in-public-warn.rs:44:5
+  --> $DIR/private-in-public-warn.rs:45:5
    |
 LL |     pub trait Tr2<T: PrivTr> {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ trait `traits::Tr2` is reachable at visibility `pub(crate)`
@@ -171,7 +171,7 @@ LL |     trait PrivTr {}
    |     ^^^^^^^^^^^^
 
 error: trait `traits::PrivTr` is more private than the item `traits::Tr3::Alias`
-  --> $DIR/private-in-public-warn.rs:46:9
+  --> $DIR/private-in-public-warn.rs:47:9
    |
 LL |         type Alias: PrivTr;
    |         ^^^^^^^^^^^^^^^^^^ associated type `traits::Tr3::Alias` is reachable at visibility `pub(crate)`
@@ -183,7 +183,7 @@ LL |     trait PrivTr {}
    |     ^^^^^^^^^^^^
 
 error: trait `traits::PrivTr` is more private than the item `traits::Tr3::f`
-  --> $DIR/private-in-public-warn.rs:48:9
+  --> $DIR/private-in-public-warn.rs:49:9
    |
 LL |         fn f<T: PrivTr>(arg: T) {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^ associated function `traits::Tr3::f` is reachable at visibility `pub(crate)`
@@ -195,7 +195,7 @@ LL |     trait PrivTr {}
    |     ^^^^^^^^^^^^
 
 error: trait `traits::PrivTr` is more private than the item `traits::Pub<T>`
-  --> $DIR/private-in-public-warn.rs:50:5
+  --> $DIR/private-in-public-warn.rs:54:5
    |
 LL |     impl<T: PrivTr> Pub<T> {}
    |     ^^^^^^^^^^^^^^^^^^^^^^ implementation `traits::Pub<T>` is reachable at visibility `pub(crate)`
@@ -207,103 +207,103 @@ LL |     trait PrivTr {}
    |     ^^^^^^^^^^^^
 
 error: trait `traits_where::PrivTr` is more private than the item `traits_where::Alias`
-  --> $DIR/private-in-public-warn.rs:59:5
+  --> $DIR/private-in-public-warn.rs:63:5
    |
 LL |     pub type Alias<T> where T: PrivTr = T;
    |     ^^^^^^^^^^^^^^^^^ type alias `traits_where::Alias` is reachable at visibility `pub(crate)`
    |
 note: but trait `traits_where::PrivTr` is only usable at visibility `pub(self)`
-  --> $DIR/private-in-public-warn.rs:55:5
+  --> $DIR/private-in-public-warn.rs:59:5
    |
 LL |     trait PrivTr {}
    |     ^^^^^^^^^^^^
 
 error: trait `traits_where::PrivTr` is more private than the item `traits_where::Tr2`
-  --> $DIR/private-in-public-warn.rs:62:5
+  --> $DIR/private-in-public-warn.rs:66:5
    |
 LL |     pub trait Tr2<T> where T: PrivTr {}
    |     ^^^^^^^^^^^^^^^^ trait `traits_where::Tr2` is reachable at visibility `pub(crate)`
    |
 note: but trait `traits_where::PrivTr` is only usable at visibility `pub(self)`
-  --> $DIR/private-in-public-warn.rs:55:5
+  --> $DIR/private-in-public-warn.rs:59:5
    |
 LL |     trait PrivTr {}
    |     ^^^^^^^^^^^^
 
 error: trait `traits_where::PrivTr` is more private than the item `traits_where::Tr3::f`
-  --> $DIR/private-in-public-warn.rs:65:9
+  --> $DIR/private-in-public-warn.rs:69:9
    |
 LL |         fn f<T>(arg: T) where T: PrivTr {}
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ associated function `traits_where::Tr3::f` is reachable at visibility `pub(crate)`
    |
 note: but trait `traits_where::PrivTr` is only usable at visibility `pub(self)`
-  --> $DIR/private-in-public-warn.rs:55:5
+  --> $DIR/private-in-public-warn.rs:59:5
    |
 LL |     trait PrivTr {}
    |     ^^^^^^^^^^^^
 
 error: trait `traits_where::PrivTr` is more private than the item `traits_where::Pub<T>`
-  --> $DIR/private-in-public-warn.rs:68:5
+  --> $DIR/private-in-public-warn.rs:72:5
    |
 LL |     impl<T> Pub<T> where T: PrivTr {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation `traits_where::Pub<T>` is reachable at visibility `pub(crate)`
    |
 note: but trait `traits_where::PrivTr` is only usable at visibility `pub(self)`
-  --> $DIR/private-in-public-warn.rs:55:5
+  --> $DIR/private-in-public-warn.rs:59:5
    |
 LL |     trait PrivTr {}
    |     ^^^^^^^^^^^^
 
 error: trait `generics::PrivTr<generics::Pub>` is more private than the item `generics::Tr1`
-  --> $DIR/private-in-public-warn.rs:79:5
+  --> $DIR/private-in-public-warn.rs:84:5
    |
 LL |     pub trait Tr1: PrivTr<Pub> {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `generics::Tr1` is reachable at visibility `pub(crate)`
    |
 note: but trait `generics::PrivTr<generics::Pub>` is only usable at visibility `pub(self)`
-  --> $DIR/private-in-public-warn.rs:76:5
+  --> $DIR/private-in-public-warn.rs:80:5
    |
 LL |     trait PrivTr<T> {}
    |     ^^^^^^^^^^^^^^^
 
 error: type `generics::Priv` is more private than the item `generics::Tr2`
-  --> $DIR/private-in-public-warn.rs:81:5
+  --> $DIR/private-in-public-warn.rs:86:5
    |
 LL |     pub trait Tr2: PubTr<Priv> {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `generics::Tr2` is reachable at visibility `pub(crate)`
    |
 note: but type `generics::Priv` is only usable at visibility `pub(self)`
-  --> $DIR/private-in-public-warn.rs:74:5
+  --> $DIR/private-in-public-warn.rs:78:5
    |
 LL |     struct Priv<T = u8>(T);
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: type `generics::Priv` is more private than the item `generics::Tr3`
-  --> $DIR/private-in-public-warn.rs:82:5
+  --> $DIR/private-in-public-warn.rs:87:5
    |
 LL |     pub trait Tr3: PubTr<[Priv; 1]> {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `generics::Tr3` is reachable at visibility `pub(crate)`
    |
 note: but type `generics::Priv` is only usable at visibility `pub(self)`
-  --> $DIR/private-in-public-warn.rs:74:5
+  --> $DIR/private-in-public-warn.rs:78:5
    |
 LL |     struct Priv<T = u8>(T);
    |     ^^^^^^^^^^^^^^^^^^^
 
 error: type `generics::Priv` is more private than the item `Tr4`
-  --> $DIR/private-in-public-warn.rs:83:5
+  --> $DIR/private-in-public-warn.rs:88:5
    |
 LL |     pub trait Tr4: PubTr<Pub<Priv>> {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `Tr4` is reachable at visibility `pub(crate)`
    |
 note: but type `generics::Priv` is only usable at visibility `pub(self)`
-  --> $DIR/private-in-public-warn.rs:74:5
+  --> $DIR/private-in-public-warn.rs:78:5
    |
 LL |     struct Priv<T = u8>(T);
    |     ^^^^^^^^^^^^^^^^^^^
 
 error[E0446]: private type `impls::Priv` in public interface
-  --> $DIR/private-in-public-warn.rs:109:9
+  --> $DIR/private-in-public-warn.rs:119:9
    |
 LL |     struct Priv;
    |     ----------- `impls::Priv` declared as private
@@ -312,19 +312,19 @@ LL |         type Alias = Priv;
    |         ^^^^^^^^^^ can't leak private type
 
 error: type `aliases_pub::Priv` is more private than the item `aliases_pub::<impl Pub2>::f`
-  --> $DIR/private-in-public-warn.rs:180:9
+  --> $DIR/private-in-public-warn.rs:190:9
    |
 LL |         pub fn f(arg: Priv) {}
    |         ^^^^^^^^^^^^^^^^^^^ associated function `aliases_pub::<impl Pub2>::f` is reachable at visibility `pub(crate)`
    |
 note: but type `aliases_pub::Priv` is only usable at visibility `pub(self)`
-  --> $DIR/private-in-public-warn.rs:153:5
+  --> $DIR/private-in-public-warn.rs:163:5
    |
 LL |     struct Priv;
    |     ^^^^^^^^^^^
 
 error[E0446]: private type `aliases_pub::Priv` in public interface
-  --> $DIR/private-in-public-warn.rs:183:9
+  --> $DIR/private-in-public-warn.rs:193:9
    |
 LL |     struct Priv;
    |     ----------- `aliases_pub::Priv` declared as private
@@ -333,7 +333,7 @@ LL |         type Check = Priv;
    |         ^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `aliases_pub::Priv` in public interface
-  --> $DIR/private-in-public-warn.rs:186:9
+  --> $DIR/private-in-public-warn.rs:196:9
    |
 LL |     struct Priv;
    |     ----------- `aliases_pub::Priv` declared as private
@@ -342,7 +342,7 @@ LL |         type Check = Priv;
    |         ^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `aliases_pub::Priv` in public interface
-  --> $DIR/private-in-public-warn.rs:189:9
+  --> $DIR/private-in-public-warn.rs:199:9
    |
 LL |     struct Priv;
    |     ----------- `aliases_pub::Priv` declared as private
@@ -351,7 +351,7 @@ LL |         type Check = Priv;
    |         ^^^^^^^^^^ can't leak private type
 
 error[E0446]: private type `aliases_pub::Priv` in public interface
-  --> $DIR/private-in-public-warn.rs:192:9
+  --> $DIR/private-in-public-warn.rs:202:9
    |
 LL |     struct Priv;
    |     ----------- `aliases_pub::Priv` declared as private
@@ -360,43 +360,43 @@ LL |         type Check = Priv;
    |         ^^^^^^^^^^ can't leak private type
 
 error: trait `PrivTr1` is more private than the item `aliases_priv::Tr1`
-  --> $DIR/private-in-public-warn.rs:222:5
+  --> $DIR/private-in-public-warn.rs:232:5
    |
 LL |     pub trait Tr1: PrivUseAliasTr {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `aliases_priv::Tr1` is reachable at visibility `pub(crate)`
    |
 note: but trait `PrivTr1` is only usable at visibility `pub(self)`
-  --> $DIR/private-in-public-warn.rs:208:5
+  --> $DIR/private-in-public-warn.rs:218:5
    |
 LL |     trait PrivTr1<T = u8> {
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error: trait `PrivTr1<Priv2>` is more private than the item `aliases_priv::Tr2`
-  --> $DIR/private-in-public-warn.rs:224:5
+  --> $DIR/private-in-public-warn.rs:234:5
    |
 LL |     pub trait Tr2: PrivUseAliasTr<PrivAlias> {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `aliases_priv::Tr2` is reachable at visibility `pub(crate)`
    |
 note: but trait `PrivTr1<Priv2>` is only usable at visibility `pub(self)`
-  --> $DIR/private-in-public-warn.rs:208:5
+  --> $DIR/private-in-public-warn.rs:218:5
    |
 LL |     trait PrivTr1<T = u8> {
    |     ^^^^^^^^^^^^^^^^^^^^^
 
 error: type `Priv2` is more private than the item `aliases_priv::Tr2`
-  --> $DIR/private-in-public-warn.rs:224:5
+  --> $DIR/private-in-public-warn.rs:234:5
    |
 LL |     pub trait Tr2: PrivUseAliasTr<PrivAlias> {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trait `aliases_priv::Tr2` is reachable at visibility `pub(crate)`
    |
 note: but type `Priv2` is only usable at visibility `pub(self)`
-  --> $DIR/private-in-public-warn.rs:206:5
+  --> $DIR/private-in-public-warn.rs:216:5
    |
 LL |     struct Priv2;
    |     ^^^^^^^^^^^^
 
 warning: bounds on generic parameters in type aliases are not enforced
-  --> $DIR/private-in-public-warn.rs:41:23
+  --> $DIR/private-in-public-warn.rs:42:23
    |
 LL |     pub type Alias<T: PrivTr> = T;
    |                     --^^^^^^
@@ -410,7 +410,7 @@ LL |     pub type Alias<T: PrivTr> = T;
    = note: `#[warn(type_alias_bounds)]` on by default
 
 warning: where clauses on type aliases are not enforced
-  --> $DIR/private-in-public-warn.rs:59:29
+  --> $DIR/private-in-public-warn.rs:63:29
    |
 LL |     pub type Alias<T> where T: PrivTr = T;
    |                       ------^^^^^^^^^
diff --git a/tests/ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs b/tests/ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs
index 4eeecdc0569..75640147026 100644
--- a/tests/ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs
+++ b/tests/ui/privacy/pub-priv-dep/auxiliary/priv_dep.rs
@@ -1,5 +1,6 @@
 pub struct OtherType;
 pub trait OtherTrait {}
+impl OtherTrait for OtherType {}
 
 #[macro_export]
 macro_rules! m {
diff --git a/tests/ui/privacy/pub-priv-dep/pub-priv1.rs b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs
index 192ca0db8bd..b85f2754fb1 100644
--- a/tests/ui/privacy/pub-priv-dep/pub-priv1.rs
+++ b/tests/ui/privacy/pub-priv-dep/pub-priv1.rs
@@ -44,8 +44,12 @@ impl PublicType {
 
 pub trait MyPubTrait {
     type Foo: OtherTrait;
+    //~^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface
+
+    fn required() -> impl OtherTrait;
+
+    fn provided() -> impl OtherTrait { OtherType }
 }
-//~^^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface
 
 pub trait WithSuperTrait: OtherTrait {}
 //~^ ERROR trait `OtherTrait` from private dependency 'priv_dep' in public interface
diff --git a/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr b/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr
index 9da47827be4..24bd071567f 100644
--- a/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr
+++ b/tests/ui/privacy/pub-priv-dep/pub-priv1.stderr
@@ -11,31 +11,31 @@ LL | #![deny(exported_private_dependencies)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: macro `m` from private dependency 'priv_dep' is re-exported
-  --> $DIR/pub-priv1.rs:94:9
+  --> $DIR/pub-priv1.rs:98:9
    |
 LL | pub use priv_dep::m;
    |         ^^^^^^^^^^^
 
 error: macro `fn_like` from private dependency 'pm' is re-exported
-  --> $DIR/pub-priv1.rs:96:9
+  --> $DIR/pub-priv1.rs:100:9
    |
 LL | pub use pm::fn_like;
    |         ^^^^^^^^^^^
 
 error: derive macro `PmDerive` from private dependency 'pm' is re-exported
-  --> $DIR/pub-priv1.rs:98:9
+  --> $DIR/pub-priv1.rs:102:9
    |
 LL | pub use pm::PmDerive;
    |         ^^^^^^^^^^^^
 
 error: attribute macro `pm_attr` from private dependency 'pm' is re-exported
-  --> $DIR/pub-priv1.rs:100:9
+  --> $DIR/pub-priv1.rs:104:9
    |
 LL | pub use pm::pm_attr;
    |         ^^^^^^^^^^^
 
 error: variant `V1` from private dependency 'priv_dep' is re-exported
-  --> $DIR/pub-priv1.rs:103:9
+  --> $DIR/pub-priv1.rs:107:9
    |
 LL | pub use priv_dep::E::V1;
    |         ^^^^^^^^^^^^^^^
@@ -65,61 +65,61 @@ LL |     type Foo: OtherTrait;
    |     ^^^^^^^^^^^^^^^^^^^^
 
 error: trait `OtherTrait` from private dependency 'priv_dep' in public interface
-  --> $DIR/pub-priv1.rs:50:1
+  --> $DIR/pub-priv1.rs:54:1
    |
 LL | pub trait WithSuperTrait: OtherTrait {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: type `OtherType` from private dependency 'priv_dep' in public interface
-  --> $DIR/pub-priv1.rs:59:5
+  --> $DIR/pub-priv1.rs:63:5
    |
 LL |     type X = OtherType;
    |     ^^^^^^
 
 error: trait `OtherTrait` from private dependency 'priv_dep' in public interface
-  --> $DIR/pub-priv1.rs:63:1
+  --> $DIR/pub-priv1.rs:67:1
    |
 LL | pub fn in_bounds<T: OtherTrait>(x: T) { unimplemented!() }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: type `OtherType` from private dependency 'priv_dep' in public interface
-  --> $DIR/pub-priv1.rs:66:1
+  --> $DIR/pub-priv1.rs:70:1
    |
 LL | pub fn private_in_generic() -> std::num::Saturating<OtherType> { unimplemented!() }
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: type `OtherType` from private dependency 'priv_dep' in public interface
-  --> $DIR/pub-priv1.rs:69:1
+  --> $DIR/pub-priv1.rs:73:1
    |
 LL | pub static STATIC: OtherType = OtherType;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: type `OtherType` from private dependency 'priv_dep' in public interface
-  --> $DIR/pub-priv1.rs:72:1
+  --> $DIR/pub-priv1.rs:76:1
    |
 LL | pub const CONST: OtherType = OtherType;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: type `OtherType` from private dependency 'priv_dep' in public interface
-  --> $DIR/pub-priv1.rs:75:1
+  --> $DIR/pub-priv1.rs:79:1
    |
 LL | pub type Alias = OtherType;
    | ^^^^^^^^^^^^^^
 
 error: trait `OtherTrait` from private dependency 'priv_dep' in public interface
-  --> $DIR/pub-priv1.rs:80:1
+  --> $DIR/pub-priv1.rs:84:1
    |
 LL | impl OtherTrait for PublicWithPrivateImpl {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: type `OtherType` from private dependency 'priv_dep' in public interface
-  --> $DIR/pub-priv1.rs:85:1
+  --> $DIR/pub-priv1.rs:89:1
    |
 LL | impl PubTraitOnPrivate for OtherType {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: type `OtherType` from private dependency 'priv_dep' in public interface
-  --> $DIR/pub-priv1.rs:85:1
+  --> $DIR/pub-priv1.rs:89:1
    |
 LL | impl PubTraitOnPrivate for OtherType {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/sanitizer/address.rs b/tests/ui/sanitizer/address.rs
index 7a5e767687c..704d84764c1 100644
--- a/tests/ui/sanitizer/address.rs
+++ b/tests/ui/sanitizer/address.rs
@@ -4,7 +4,7 @@
 //
 //@ compile-flags: -Z sanitizer=address -O -g
 //
-//@ run-fail
+//@ run-fail-or-crash
 //@ error-pattern: AddressSanitizer: stack-buffer-overflow
 //@ error-pattern: 'xs' (line 14) <== Memory access at offset
 
diff --git a/tests/ui/sanitizer/badfree.rs b/tests/ui/sanitizer/badfree.rs
index ecbb58eba00..6b3aea7239c 100644
--- a/tests/ui/sanitizer/badfree.rs
+++ b/tests/ui/sanitizer/badfree.rs
@@ -4,7 +4,7 @@
 //
 //@ compile-flags: -Z sanitizer=address -O
 //
-//@ run-fail
+//@ run-fail-or-crash
 //@ regex-error-pattern: AddressSanitizer: (SEGV|attempting free on address which was not malloc)
 
 use std::ffi::c_void;
diff --git a/tests/ui/sanitizer/new-llvm-pass-manager-thin-lto.rs b/tests/ui/sanitizer/new-llvm-pass-manager-thin-lto.rs
index b7dd4a43782..c1a2c2f26ac 100644
--- a/tests/ui/sanitizer/new-llvm-pass-manager-thin-lto.rs
+++ b/tests/ui/sanitizer/new-llvm-pass-manager-thin-lto.rs
@@ -11,7 +11,7 @@
 //@ compile-flags: -Zsanitizer=address -Clto=thin
 //@[opt0]compile-flags: -Copt-level=0
 //@[opt1]compile-flags: -Copt-level=1
-//@ run-fail
+//@ run-fail-or-crash
 //@ error-pattern: ERROR: AddressSanitizer: stack-use-after-scope
 
 static mut P: *mut usize = std::ptr::null_mut();
diff --git a/tests/ui/sanitizer/thread.rs b/tests/ui/sanitizer/thread.rs
index 566774d6b1d..9073124d1bd 100644
--- a/tests/ui/sanitizer/thread.rs
+++ b/tests/ui/sanitizer/thread.rs
@@ -15,7 +15,7 @@
 //
 //@ compile-flags: -Z sanitizer=thread -O
 //
-//@ run-fail
+//@ run-fail-or-crash
 //@ error-pattern: WARNING: ThreadSanitizer: data race
 //@ error-pattern: Location is heap block of size 4
 //@ error-pattern: allocated by main thread
diff --git a/tests/ui/sanitizer/use-after-scope.rs b/tests/ui/sanitizer/use-after-scope.rs
index 4d7f6f6c2f2..106dc6466d6 100644
--- a/tests/ui/sanitizer/use-after-scope.rs
+++ b/tests/ui/sanitizer/use-after-scope.rs
@@ -3,7 +3,7 @@
 //@ ignore-cross-compile
 //
 //@ compile-flags: -Zsanitizer=address
-//@ run-fail
+//@ run-fail-or-crash
 //@ error-pattern: ERROR: AddressSanitizer: stack-use-after-scope
 
 static mut P: *mut usize = std::ptr::null_mut();
diff --git a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.next.stderr b/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.current_sized_hierarchy.stderr
index cf56f42afc8..b904b784df7 100644
--- a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.next.stderr
+++ b/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.current_sized_hierarchy.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/incomplete-inference-issue-143992.rs:27:28
+  --> $DIR/incomplete-inference-issue-143992.rs:30:28
    |
 LL |     let _x = T::Assoc::new(());
    |              ------------- ^^ expected `[u32; 1]`, found `()`
@@ -7,7 +7,7 @@ LL |     let _x = T::Assoc::new(());
    |              arguments to this function are incorrect
    |
 note: associated function defined here
-  --> $DIR/incomplete-inference-issue-143992.rs:18:8
+  --> $DIR/incomplete-inference-issue-143992.rs:21:8
    |
 LL |     fn new(r: R) -> R {
    |        ^^^ ----
diff --git a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.next_sized_hierarchy.stderr b/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.next_sized_hierarchy.stderr
new file mode 100644
index 00000000000..b904b784df7
--- /dev/null
+++ b/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.next_sized_hierarchy.stderr
@@ -0,0 +1,17 @@
+error[E0308]: mismatched types
+  --> $DIR/incomplete-inference-issue-143992.rs:30:28
+   |
+LL |     let _x = T::Assoc::new(());
+   |              ------------- ^^ expected `[u32; 1]`, found `()`
+   |              |
+   |              arguments to this function are incorrect
+   |
+note: associated function defined here
+  --> $DIR/incomplete-inference-issue-143992.rs:21:8
+   |
+LL |     fn new(r: R) -> R {
+   |        ^^^ ----
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs b/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs
index 3e3e1dc50e5..b9e65ed2839 100644
--- a/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs
+++ b/tests/ui/sized-hierarchy/incomplete-inference-issue-143992.rs
@@ -1,9 +1,12 @@
 //@ compile-flags: --crate-type=lib
-//@ revisions: current next
+//@ revisions: current next current_sized_hierarchy next_sized_hierarchy
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[current] check-pass
+//@[next] check-pass
 //@[next] compile-flags: -Znext-solver
-//@[next] check-fail
+//@[next_sized_hierarchy] compile-flags: -Znext-solver
+
+#![cfg_attr(any(current_sized_hierarchy, next_sized_hierarchy), feature(sized_hierarchy))]
 
 // Test that we avoid incomplete inference when normalizing. Without this,
 // `Trait`'s implicit `MetaSized` supertrait requires proving `T::Assoc<_>: MetaSized`
@@ -25,5 +28,6 @@ where
     T::Assoc<[u32; 1]>: Clone,
 {
     let _x = T::Assoc::new(());
-//[next]~^ ERROR mismatched types
+    //[next_sized_hierarchy]~^ ERROR mismatched types
+    //[current_sized_hierarchy]~^^ ERROR mismatched types
 }
diff --git a/tests/ui/std/issue-81357-unsound-file-methods.rs b/tests/ui/std/issue-81357-unsound-file-methods.rs
index 838df40c32d..99bd31aa260 100644
--- a/tests/ui/std/issue-81357-unsound-file-methods.rs
+++ b/tests/ui/std/issue-81357-unsound-file-methods.rs
@@ -1,4 +1,4 @@
-//@ run-fail
+//@ run-crash
 //@ only-windows
 
 fn main() {
diff --git a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr
index 1eb445f4848..8901805a20f 100644
--- a/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr
+++ b/tests/ui/traits/next-solver/cycles/normalizes-to-is-not-productive.stderr
@@ -12,13 +12,6 @@ LL | impl<T: Bound, U> Trait<U> for T {
    |         -----     ^^^^^^^^     ^
    |         |
    |         unsatisfied trait bound introduced here
-note: required by a bound in `Bound`
-  --> $DIR/normalizes-to-is-not-productive.rs:8:1
-   |
-LL | / trait Bound {
-LL | |     fn method();
-LL | | }
-   | |_^ required by this bound in `Bound`
 
 error[E0277]: the trait bound `Foo: Bound` is not satisfied
   --> $DIR/normalizes-to-is-not-productive.rs:47:19
diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr
index 8d8909625ff..d179c805962 100644
--- a/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr
+++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr
@@ -19,23 +19,6 @@ error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc: A<T>`
 LL |         Self::Assoc: A<T>,
    |                      ^^^^
 
-error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc: MetaSized`
-  --> $DIR/normalize-param-env-2.rs:24:22
-   |
-LL |         Self::Assoc: A<T>,
-   |                      ^^^^
-   |
-note: required by a bound in `A`
-  --> $DIR/normalize-param-env-2.rs:9:1
-   |
-LL | / trait A<T> {
-LL | |     type Assoc;
-LL | |
-LL | |     fn f()
-...  |
-LL | | }
-   | |_^ required by this bound in `A`
-
 error[E0275]: overflow evaluating the requirement `<() as A<T>>::Assoc well-formed`
   --> $DIR/normalize-param-env-2.rs:24:22
    |
@@ -63,6 +46,6 @@ LL |     where
 LL |         Self::Assoc: A<T>,
    |                      ^^^^ required by this bound in `A::f`
 
-error: aborting due to 6 previous errors
+error: aborting due to 5 previous errors
 
 For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr
index 9f7f74f9466..f5fd9ce9864 100644
--- a/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr
+++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-4.next.stderr
@@ -4,20 +4,6 @@ error[E0275]: overflow evaluating the requirement `<T as Trait>::Assoc: Trait`
 LL |     <T as Trait>::Assoc: Trait,
    |                          ^^^^^
 
-error[E0275]: overflow evaluating the requirement `<T as Trait>::Assoc: MetaSized`
-  --> $DIR/normalize-param-env-4.rs:19:26
-   |
-LL |     <T as Trait>::Assoc: Trait,
-   |                          ^^^^^
-   |
-note: required by a bound in `Trait`
-  --> $DIR/normalize-param-env-4.rs:7:1
-   |
-LL | / trait Trait {
-LL | |     type Assoc;
-LL | | }
-   | |_^ required by this bound in `Trait`
-
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/where-clauses/ignore-err-clauses.rs b/tests/ui/where-clauses/ignore-err-clauses.rs
index 428ebf4b408..6f21e5ccbaa 100644
--- a/tests/ui/where-clauses/ignore-err-clauses.rs
+++ b/tests/ui/where-clauses/ignore-err-clauses.rs
@@ -1,13 +1,13 @@
 use std::ops::Add;
 
 fn dbl<T>(x: T) -> <T as Add>::Output
-//~^ ERROR type annotations needed
 where
     T: Copy + Add,
     UUU: Copy,
     //~^ ERROR cannot find type `UUU` in this scope
 {
     x + x
+    //~^ ERROR use of moved value: `x`
 }
 
 fn main() {
diff --git a/tests/ui/where-clauses/ignore-err-clauses.stderr b/tests/ui/where-clauses/ignore-err-clauses.stderr
index fbf1b99334f..9c76c1c6a04 100644
--- a/tests/ui/where-clauses/ignore-err-clauses.stderr
+++ b/tests/ui/where-clauses/ignore-err-clauses.stderr
@@ -1,16 +1,33 @@
 error[E0412]: cannot find type `UUU` in this scope
-  --> $DIR/ignore-err-clauses.rs:7:5
+  --> $DIR/ignore-err-clauses.rs:6:5
    |
 LL |     UUU: Copy,
    |     ^^^ not found in this scope
 
-error[E0282]: type annotations needed
-  --> $DIR/ignore-err-clauses.rs:3:14
+error[E0382]: use of moved value: `x`
+  --> $DIR/ignore-err-clauses.rs:9:9
    |
 LL | fn dbl<T>(x: T) -> <T as Add>::Output
-   |              ^ cannot infer type for type parameter `T`
+   |           - move occurs because `x` has type `T`, which does not implement the `Copy` trait
+...
+LL |     x + x
+   |     ----^
+   |     |   |
+   |     |   value used here after move
+   |     `x` moved due to usage in operator
+   |
+help: if `T` implemented `Clone`, you could clone the value
+  --> $DIR/ignore-err-clauses.rs:3:8
+   |
+LL | fn dbl<T>(x: T) -> <T as Add>::Output
+   |        ^ consider constraining this type parameter with `Clone`
+...
+LL |     x + x
+   |     - you could clone this value
+note: calling this operator moves the left-hand side
+  --> $SRC_DIR/core/src/ops/arith.rs:LL:COL
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0282, E0412.
-For more information about an error, try `rustc --explain E0282`.
+Some errors have detailed explanations: E0382, E0412.
+For more information about an error, try `rustc --explain E0382`.